
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/Misc.h>

#include <X11/Xaw/XawInit.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/ViewportP.h>

#include <X11/Xtw/FrameP.h>

static XtResource frameResources[] = 
{
  {XtNlabel, XtCLabel, XtRString, sizeof(String),
     XtOffset(FrameWidget, frame.title), XtRString, (char *) NULL},  
  {XtNplace, XtCPlace, XtRPlaceType, sizeof(XtwPlaceType),
     XtOffset(FrameWidget, frame.com_place), XtRString, "Bottom"}, 
};


static void ClassInitialize();
static void Initialize();
static void InsertChild();

FrameClassRec frameClassRec = {
  { /* core_class fields */
    /* superclass         */    (WidgetClass) &formClassRec,
    /* class_name         */    "Frame",
    /* widget_size        */    sizeof(FrameRec),
    /* class_initialize   */    ClassInitialize,
    /* class_part init    */    NULL,
    /* class_inited       */    FALSE,
    /* initialize         */    Initialize,
    /* initialize_hook    */    NULL,
    /* realize            */    XtInheritRealize,
    /* actions            */    NULL,
    /* num_actions        */    0,
    /* resources          */    frameResources,
    /* num_resources      */    XtNumber(frameResources),
    /* xrm_class          */    NULLQUARK,
    /* compress_motion    */    TRUE,
    /* compress_exposure  */    TRUE,
    /* compress_enterleave*/    TRUE,
    /* visible_interest   */    FALSE,
    /* destroy            */    NULL,
    /* resize             */    XtInheritResize,
    /* expose             */    XtInheritExpose,
    /* set_values         */    NULL,
    /* set_values_hook    */    NULL,
    /* set_values_almost  */    XtInheritSetValuesAlmost,
    /* get_values_hook    */    NULL,
    /* accept_focus       */    NULL,
    /* version            */    XtVersion,
    /* callback_private   */    NULL,
    /* tm_table           */    NULL,
    /* query_geometry     */	XtInheritQueryGeometry,
    /* display_accelerator*/	XtInheritDisplayAccelerator,
    /* extension          */	NULL
  },
  { /* composite_class fields */
    /* geometry_manager   */   XtInheritGeometryManager,
    /* change_managed     */   XtInheritChangeManaged,
    /* insert_child       */   InsertChild,
    /* delete_child       */   XtInheritDeleteChild,
    /* extension          */   NULL
  },
  { /* constraint_class fields */
    /* subresourses       */   NULL,
    /* subresource_count  */   0,
    /* constraint_size    */   sizeof(FrameConstraintsRec),
    /* initialize         */   NULL,
    /* destroy            */   NULL,
    /* set_values         */   NULL,
    /* extension          */   NULL
  },
  { /* form_class fields */
    /* layout             */   XtInheritLayout
  },
  { /* frame_class fields */
    /* empty              */   0
  }
};

WidgetClass frameWidgetClass = (WidgetClass) &frameClassRec;
static int pregnant = 0;

static void 
ClassInitialize()
{
  XawInitializeWidgetSet();
  XtwInitializePlaceCvt();
  XtAddConverter(XtRString, XtRPlaceType, XtwCvtStringToPlaceType, NULL, 0);
}


/* ARGSUSED */
static void 
Initialize(request, new)
     Widget request;
     Widget new;
{
  FrameWidget fw = (FrameWidget) new;
  Arg arglist[12];
  Cardinal num_args = 0;
  Widget w;

  fw->frame.child = (Widget) NULL;
  pregnant = 0;

  if(fw->frame.title)
    {
      num_args = 0;
      XtSetArg(arglist[num_args], XtNborderWidth, 0);            num_args++;
      XtSetArg(arglist[num_args], XtNleft, XtChainLeft);         num_args++;
      XtSetArg(arglist[num_args], XtNright, XtChainLeft);        num_args++;
      XtSetArg(arglist[num_args], XtNtop, XtChainTop);           num_args++;
      XtSetArg(arglist[num_args], XtNbottom, XtChainTop);        num_args++;
      XtSetArg(arglist[num_args], XtNlabel, fw->frame.title);    num_args++;
      fw->frame.label = XtCreateManagedWidget("title", labelWidgetClass,
					      new, 
					      arglist, num_args);
    }

  if((fw->frame.com_place == XtwLeft) || (fw->frame.com_place == XtwTop))
    {
      num_args = 0;
      XtSetArg(arglist[num_args], XtNborderWidth, 0);            num_args++;
      if(fw->frame.title)
	XtSetArg(arglist[num_args], XtNfromVert, 
		 fw->frame.label);                               num_args++;
      fw->frame.com_box = XtCreateManagedWidget("commandBox", formWidgetClass,
						new, 
						arglist, num_args);
    }

  num_args = 0;
  XtSetArg(arglist[num_args], XtNleft, XtChainLeft);             num_args++;
  XtSetArg(arglist[num_args], XtNright, XtChainRight);           num_args++;
  XtSetArg(arglist[num_args], XtNtop, XtChainTop);               num_args++;
  XtSetArg(arglist[num_args], XtNbottom, XtChainBottom);         num_args++;
  XtSetArg(arglist[num_args], XtNuseBottom, True);               num_args++;
  XtSetArg(arglist[num_args], XtNuseRight, True);                num_args++;
  fw->frame.view = XtCreateManagedWidget("viewport", viewportWidgetClass,
					 new, arglist, num_args); 
 
  /*
   * This is unfortunate but I don't want to deal with
   * reordering later.
   */

  if((fw->frame.com_place == XtwRight) || (fw->frame.com_place == XtwBottom))
    {
      num_args = 0;
      XtSetArg(arglist[num_args], XtNborderWidth, 0);            num_args++;
      XtSetArg(arglist[num_args], XtNhorizDistance, 0);          num_args++;
      fw->frame.com_box = XtCreateManagedWidget("commandBox", formWidgetClass,
						new,
						arglist, num_args);
    }

  num_args = 0;
  switch(fw->frame.com_place)
    {
    case XtwBottom:
      if(fw->frame.title)
	{
	  XtSetArg(arglist[num_args], XtNfromVert, 
		   fw->frame.label);                             num_args++;
	  XtSetValues(fw->frame.view, arglist, num_args);
	}

      XtSetArg(arglist[num_args], XtNfromVert, fw->frame.view);  num_args++;
      XtSetArg(arglist[num_args], XtNtop, XtChainBottom);        num_args++;
      XtSetArg(arglist[num_args], XtNbottom, XtChainBottom);     num_args++;
      XtSetArg(arglist[num_args], XtNleft, XtChainLeft);         num_args++;
      XtSetArg(arglist[num_args], XtNright, XtChainLeft);        num_args++;
      XtSetValues(fw->frame.com_box, arglist, num_args);
      break;


    case XtwRight:
      if(fw->frame.title)
	{
	  XtSetArg(arglist[num_args], XtNfromVert, 
		   fw->frame.label);                             num_args++; 
	  XtSetValues(fw->frame.view, arglist, num_args);
	}

      XtSetArg(arglist[num_args], XtNfromHoriz, fw->frame.view); num_args++;
      if(fw->frame.title)
	XtSetArg(arglist[num_args], XtNfromVert, 
		 fw->frame.label);                               num_args++;
      XtSetArg(arglist[num_args], XtNtop, XtChainTop);           num_args++;
      XtSetArg(arglist[num_args], XtNbottom, XtChainBottom);     num_args++;
      XtSetArg(arglist[num_args], XtNleft, XtChainRight);        num_args++;
      XtSetArg(arglist[num_args], XtNright, XtChainRight);       num_args++;
      XtSetValues(fw->frame.com_box, arglist, num_args);
      break;


    case XtwTop:
      XtSetArg(arglist[num_args], XtNfromVert, 
	       fw->frame.com_box);                               num_args++;
      if(fw->frame.title)
	{
	  XtSetArg(arglist[num_args], XtNfromVert, 
		   fw->frame.label);                             num_args++;
	}
      XtSetValues(fw->frame.view, arglist, num_args);

      num_args = 0;
      if(fw->frame.title)
	XtSetArg(arglist[num_args], XtNfromVert, 
		 fw->frame.label);                               num_args++;
      XtSetArg(arglist[num_args], XtNtop, XtChainTop);           num_args++;
      XtSetArg(arglist[num_args], XtNbottom, XtChainTop);        num_args++;
      XtSetArg(arglist[num_args], XtNleft, XtChainLeft);         num_args++;
      XtSetArg(arglist[num_args], XtNright, XtChainLeft);        num_args++;
      XtSetValues(fw->frame.com_box, arglist, num_args);
      break;


    case XtwLeft:
      XtSetArg(arglist[num_args], XtNfromHoriz, 
	       fw->frame.com_box);                               num_args++;
      if(fw->frame.title)
	{
	  XtSetArg(arglist[num_args], XtNfromVert, 
		   fw->frame.label);                             num_args++;
	}
      XtSetValues(fw->frame.view, arglist, num_args);

      num_args = 0;
      if(fw->frame.title)
	XtSetArg(arglist[num_args], XtNfromVert, 
		 fw->frame.label);                               num_args++;
      XtSetArg(arglist[num_args], XtNtop, XtChainTop);           num_args++;
      XtSetArg(arglist[num_args], XtNbottom, XtChainBottom);     num_args++;
      XtSetArg(arglist[num_args], XtNleft, XtChainLeft);         num_args++;
      XtSetArg(arglist[num_args], XtNright, XtChainLeft);        num_args++;
      XtSetValues(fw->frame.com_box, arglist, num_args);
      break;
    }
  pregnant = 1;
}



static void 
InsertChild(w)
     register Widget w;
{
  FrameWidget fw = (FrameWidget) XtParent(w);
  Arg arglist[5];
  Cardinal num_args = 0;

  if(!pregnant)
    {
      (*((FormWidgetClass) &formClassRec)->composite_class.insert_child)(w);
      return;
    }

  /*
   * set the viewport form to be the parent
   */

  w->core.parent = fw->frame.view;
  (*((FormWidgetClass) &formClassRec)->composite_class.insert_child)(w);
  return;

/*
  w->core.parent = fw->frame.com_box;
  (*((FormWidgetClass) &formClassRec)->composite_class.insert_child)(w);

  if(cousin)
    {
      switch(fw->frame.com_place)
	{
	case XtwLeft:
	case XtwRight:
	  XtSetArg(arglist[num_args], XtNfromVert, cousin);      num_args++;
	  break;
	case XtwTop:
	case XtwBottom:
	  XtSetArg(arglist[num_args], XtNfromHoriz, cousin);     num_args++;
	  break;
	}
    }

  return;
*/
}
 


Widget
XtwAddFrameCommand(name, class, fw, args, num_args)
     char *name;
     WidgetClass class;
     FrameWidget fw;
     Arg *args;
     Cardinal num_args;
{
  Widget w;
  Arg arg;

  w = XtCreateManagedWidget(name, class, fw->frame.com_box, args, num_args);
  
  if(fw->frame.command)
    {
      switch(fw->frame.com_place)
	{
	case XtwLeft:
	case XtwRight:
	  XtSetArg(arg, XtNfromVert, fw->frame.command);
	  break;
	case XtwTop:
	case XtwBottom:
	  XtSetArg(arg, XtNfromHoriz, fw->frame.command);
	  break;
	}
      XtSetValues(w, &arg, 1);
    }
  fw->frame.command = w;
  return(w);
}
