/**
 *
 * test23.c
 *
 **/

#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/Label.h>
#include <Xm/FormP.h>


Boolean GlobalResult = True;

static String FallBack[] = {
	"*geometry: +500+500",
	"*borderWidth: 1",
NULL};

typedef struct {
		XtGeometryResult result;
		XtWidgetGeometry geo;
} QueryResult;

static char *
XdbBoolean2String(int b)
{
    if (b)
    {
	return "True";
    }

    return "False";
}

static char *
XdbGeometryResult2String(XtGeometryResult r)
{
    switch (r)
    {
    case XtGeometryYes:
	return "Yes";

    case XtGeometryNo:
	return "No";

    case XtGeometryAlmost:
	return "Almost";

    case XtGeometryDone:
	return "Done";

    default:
	return "(invalid geometry result)";
    }
}

static char *
XdbWidgetGeometry2String(XtWidgetGeometry *g)
{
    static char o1[128], o2[128], b[20], *out = NULL;
    int i;

    if (g == NULL)
    {
	return "NULL_GEOMETRY";
    }

    if (g->request_mode == 0)
    {
	return "GEOMETRY_NO_FIELDS";
    }

/* Some magic to ensure you can call this sucker twice in one C function call */
    if (out == &o1[0])
    {
	out = &o2[0];
    }
    else
    {
	out = &o1[0];
    }

    out[0] = '\0';
    if (g->request_mode & CWX)
    {
	sprintf(b, "x %d ", g->x);
	strcat(out, b);
    }
    if (g->request_mode & CWY)
    {
	sprintf(b, "y %d ", g->y);
	strcat(out, b);
    }
    if (g->request_mode & CWWidth)
    {
	sprintf(b, "w %d ", g->width);
	strcat(out, b);
    }
    if (g->request_mode & CWHeight)
    {
	sprintf(b, "h %d ", g->height);
	strcat(out, b);
    }
    if (g->request_mode & CWBorderWidth)
    {
	sprintf(b, "bw %d ", g->border_width);
	strcat(out, b);
    }

    for (i = 0; out[i]; i++)
    {
    }

    if (i > 0 && out[i - 1] == ' ')
    {
	out[i - 1] = '\0';
    }

    return out;
}

static Boolean QueryGeometry(Widget W, XtWidgetGeometry *request, QueryResult *Expected, XtWidgetGeometry *desired)
{
Boolean status = True;
XtWidgetGeometry OriginalRequest;
XtGeometryResult result;

	if (request)
		OriginalRequest = *request;

	printf("QueryGeometry asked for (%s) ",
		XdbWidgetGeometry2String(request));

	result = XtQueryGeometry(W, request, desired);

	printf("got (%s %s) ",
		XdbWidgetGeometry2String(desired),
		XdbGeometryResult2String(result));
	printf("expected (%s %s) ",
		XdbWidgetGeometry2String(&Expected->geo),
		XdbGeometryResult2String(Expected->result),
		XdbWidgetGeometry2String(request));
	/*
	printf("original return (%s) ",
		XdbWidgetGeometry2String(request));
		*/

	if ((desired->request_mode & Expected->geo.request_mode) == Expected->geo.request_mode &&
	    desired->width  == Expected->geo.width  &&
	    desired->height == Expected->geo.height &&
	    result == Expected->result &&
	    (!request ? True : (OriginalRequest.request_mode == request->request_mode &&
	    			OriginalRequest.width == request->width &&
	    			OriginalRequest.height == request->height))
	   )
	{
		printf("Passed\n");
	}
	else
	{
		printf("Failed\n");
		status = False;
	}
	return(status);
}

static void DoTests(Widget Form)
{
XtWidgetGeometry Preferred;

	{ /* Ask what it wants */
	QueryResult Expect;
	XtWidgetGeometry desired;
	Dimension mh, mw;
	WidgetList children;
	Cardinal numKids;

		Expect.geo.request_mode = CWWidth | CWHeight;
		XtVaGetValues(Form,
			XmNchildren, &children,
			XmNnumChildren, &numKids,
			NULL);
		if (numKids == 0 || !XtIsManaged(children[0]))
		{
			Expect.geo.width = 1;
			Expect.geo.height = 1;
			Expect.result = XtGeometryAlmost;
		}
		else
		{
		Dimension bw;

			XtVaGetValues(children[0],
				XmNborderWidth, &bw,
				XmNwidth, &Expect.geo.width,
				XmNheight, &Expect.geo.height,
				NULL);
			Expect.geo.width += 2 * bw;
			Expect.geo.height += 2 * bw;
			if (XtIsRealized(Form))
			{
				Expect.result = XtGeometryNo;
			}
			else
			{
				Expect.result = XtGeometryAlmost;
			}
		}

		GlobalResult &= QueryGeometry(Form, NULL, &Expect, &desired);
		Preferred = desired;
	}
	{ /* Propose what it wants */
	QueryResult Expect;
	XtWidgetGeometry Proposed;
	XtWidgetGeometry desired;

		Expect.geo.request_mode = CWWidth | CWHeight;
		Expect.geo.width = Preferred.width;
		Expect.geo.height = Preferred.height;
		Expect.result = XtGeometryYes;

		Proposed.request_mode = CWWidth | CWHeight;
		Proposed.width = Preferred.width;
		Proposed.height = Preferred.height;
		GlobalResult &= QueryGeometry(Form, &Proposed, &Expect, &desired);
	}
	{ /* propose something bigger in width */
	QueryResult Expect;
	XtWidgetGeometry Proposed;
	XtWidgetGeometry desired;

		Expect.geo.request_mode = CWWidth | CWHeight;
		Expect.geo.width = Preferred.width + 1;
		Expect.geo.height = Preferred.height;
		Expect.result = XtGeometryAlmost;

		Proposed.request_mode = CWWidth;
		Proposed.width = Preferred.width + 1;
		Proposed.height = Preferred.height;
		GlobalResult &= QueryGeometry(Form, &Proposed, &Expect, &desired);
	}
	{ /* propose something bigger */
	QueryResult Expect;
	XtWidgetGeometry Proposed;
	XtWidgetGeometry desired;

		Expect.geo.request_mode = CWWidth | CWHeight;
		Expect.geo.width = Preferred.width + 1;
		Expect.geo.height = Preferred.height + 1;
		Expect.result = XtGeometryYes;

		Proposed.request_mode = CWWidth | CWHeight;
		Proposed.width = Preferred.width + 1;
		Proposed.height = Preferred.height + 1;
		GlobalResult &= QueryGeometry(Form, &Proposed, &Expect, &desired);
	}
	{ /* propose something smaller */
	QueryResult Expect;
	XtWidgetGeometry Proposed;
	XtWidgetGeometry desired;

		Expect.geo.request_mode = CWWidth | CWHeight;
		Expect.geo.width = Preferred.width;
		Expect.geo.height = Preferred.height;
		if (XtIsRealized(Form))
		{
			Expect.result = XtGeometryNo;
		}
		else
		{
			Expect.result = XtGeometryAlmost;
		}

		Proposed.request_mode = CWWidth | CWHeight;
		Proposed.width = Preferred.width - 1;
		Proposed.height = Preferred.height - 1;
		GlobalResult &= QueryGeometry(Form, &Proposed, &Expect, &desired);
	}
}
static void CompareFormPart(Widget W, XmFormPart *Expected)
{
XmFormPart *f = &((XmFormWidget)W)->form;

  	printf("XmFormPart - %s\n", XtName(W));
  	printf("\thorizontal_spacing %i (%i) %s\n",
  		f->horizontal_spacing,
  		Expected->horizontal_spacing,
  		(f->horizontal_spacing == Expected->horizontal_spacing) ? "OK" : "BAD");
  		GlobalResult &= f->horizontal_spacing == Expected->horizontal_spacing;
  	printf("\tvertical_spacing %i (%i) %s\n",
  		f->vertical_spacing,
  		Expected->vertical_spacing,
  		(f->vertical_spacing == Expected->vertical_spacing) ? "OK" : "BAD");
  		GlobalResult &= f->vertical_spacing == Expected->vertical_spacing;
  	printf("\tfraction_base %i (%i) %s\n",
  		f->fraction_base,
  		Expected->fraction_base,
  		(f->fraction_base == Expected->fraction_base) ? "OK" : "BAD");
  		GlobalResult &= f->fraction_base == Expected->fraction_base;
  	printf("\trubber_positioning %i (%i) %s\n",
  		f->rubber_positioning,
  		Expected->rubber_positioning,
  		(f->rubber_positioning == Expected->rubber_positioning) ? "OK" : "BAD");
  		GlobalResult &= f->rubber_positioning == Expected->rubber_positioning;
  	printf("\tfirst_child 0x%08x (0x%08x) %s\n",
  		f->first_child,
  		Expected->first_child,
  		(f->first_child == Expected->first_child) ? "OK" : "BAD");
  		GlobalResult &= f->first_child == Expected->first_child;
  	printf("\tinitial_width %s %i (%s %i) %s\n",
  		XdbBoolean2String(f->initial_width),f->initial_width,
  		XdbBoolean2String(Expected->initial_width),Expected->initial_width,
  		(f->initial_width == Expected->initial_width) ? "OK" : "BAD");
  		GlobalResult &= f->initial_width == Expected->initial_width;
  	printf("\tinitial_height %s %i (%s %i) %s\n",
  		XdbBoolean2String(f->initial_height),f->initial_height,
  		XdbBoolean2String(Expected->initial_height),Expected->initial_height,
  		(f->initial_height == Expected->initial_height) ? "OK" : "BAD");
  		GlobalResult &= f->initial_height == Expected->initial_height;
  	printf("\tprocessing_constraints %s (%s) %s\n",
  		XdbBoolean2String(f->processing_constraints),
  		XdbBoolean2String(Expected->processing_constraints),
  		(f->processing_constraints == Expected->processing_constraints) ? "OK" : "BAD");
  		GlobalResult &= f->processing_constraints == Expected->processing_constraints;
}

int
main(int argc, char **argv)
{
  Widget toplevel;
  Widget Form;
  Widget label;
  XtAppContext app;

  XtSetLanguageProc(NULL, NULL, NULL);

  toplevel = XtVaAppInitialize(&app, "test23", NULL, 0, &argc, argv, FallBack, NULL);

  printf("Create a Form\n");
  Form = XmCreateForm(toplevel, "TestWidget", NULL, 0);
  {
  XmFormPart Expected = { 0,
  			  0,
  			  100,
  			  False,
  			  NULL,
  			  11,
  			  54,
  			  False};

	  /*
	  CompareFormPart(Form, &Expected);
	  */
  }
  DoTests(Form);

  printf("\nCreate a label in the Form\n");
  label = XmCreateLabel(Form, "TestWidget", NULL, 0);
  {
  XmFormPart Expected = { 0,
  			  0,
  			  100,
  			  False,
  			  NULL,
  			  11,
  			  54,
  			  False};

	  /*
	  CompareFormPart(Form, &Expected);
	  */
  }
  DoTests(Form);

  printf("\nManage the label\n");
  XtManageChild(label);
  {
  XmFormPart Expected = { 0,
  			  0,
  			  100,
  			  False,
  			  NULL,
  			  11,
  			  54,
  			  False};
	  Expected.first_child = label;

	  /*
	  CompareFormPart(Form, &Expected);
	  */
  }
  DoTests(Form);

  printf("\nManage the Form\n");
  XtManageChild(Form);
  {
  XmFormPart Expected = { 0,
  			  0,
  			  100,
  			  False,
  			  NULL,
  			  11,
  			  54,
  			  False};
	  Expected.first_child = label;

	  /*
	  CompareFormPart(Form, &Expected);
	  */
  }
  DoTests(Form);

  printf("\nRealize the Shell\n");
  XtRealizeWidget(toplevel);
  {
  XmFormPart Expected = { 0,
  			  0,
  			  100,
  			  False,
  			  NULL,
  			  11,
  			  54,
  			  False};
	  Expected.first_child = label;

	  /*
	  CompareFormPart(Form, &Expected);
	  */
  }
  DoTests(Form);

  /*
  printf("%s\n",GlobalResult ? "All Passed" : "One or more Failed");
  */

  {
  static XtWidgetGeometry Expected[] = {
  	CWWidth | CWHeight,		0,	0,	66,	19,	0,0,0,	/* Form */
  	CWWidth | CWHeight | CWX | CWY,	0,	0,	64,	17,	0,0,0,	/* two */
};

  PrintDetails(toplevel, Expected);
  }
  printf("%s\n",GlobalResult ? "All Passed" : "One or more Failed");
      LessTifTestMainLoop(toplevel);

  exit(GlobalResult ? 0 : 1);
}
