/* 3270 screen title widget */

#include <string.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include "Title3270P.h"
#define ISPACE 20

static Dimension defHeight = ~0; /* Value for height if it hasn't been set */
static Pixel defColor = ~0;	/* Value for color that hasn't been set */

static void Setbord();

#define offset(field) XtOffset(Title3270Widget, title3270.field)

static XtResource resources[] = {
  {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
     offset(foreground), XtRString, "XtDefaultForeground"},
  {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
     offset(font), XtRString, "XtDefaultFont"},
  {XtNtitle, XtCTitle, XtRString, sizeof(String),
     offset(title), XtRString, NULL},
  {XtNcursorColor, XtCCursorColor, XtRPixel, sizeof(Pixel),
     offset(cursorColor), XtRPixel, (caddr_t) &defColor},
  {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
     offset(cursor), XtRString, "top_left_arrow"},
  {XtNinserting, XtCBoolean, XtRBoolean, sizeof(Boolean),
     offset(inserting), XtRImmediate, (caddr_t) False},
  {XtNsystem, XtCBoolean, XtRBoolean, sizeof(Boolean),
     offset(system), XtRImmediate, (caddr_t) True},
  {XtNaplkeyb, XtCAplkeyb, XtRBoolean, sizeof(Boolean),
     offset(aplkeyb), XtRImmediate, (caddr_t) False},
  {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
     offset(iwidth), XtRImmediate, (caddr_t) 4},
  {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
     offset(iheight), XtRImmediate, (caddr_t) 2},
  {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
     XtOffset(Title3270Widget, core.border_width), XtRCallProc,
     (caddr_t) Setbord},
  {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
     XtOffset(Title3270Widget, core.height), XtRDimension,
     (caddr_t) &defHeight},
};

static void Initialize(), Realize(), Destroy(), Resize(), Redisplay();
static Boolean SetValues();
static void makegc(), setsize(), setpos();

Title3270ClassRec title3270ClassRec = {
  /* Core fields */
  { /* superclass		*/	(WidgetClass) &widgetClassRec,
    /* class_name		*/	"Title3270",
    /* widget_size		*/	sizeof(Title3270Rec),
    /* class_initialize		*/	NULL,
    /* class_part_initialize	*/	NULL,
    /* class_inited		*/	FALSE,
    /* initialize	  	*/	Initialize,
    /* initialize_hook		*/	NULL,
    /* realize			*/	Realize,
    /* actions			*/	NULL,
    /* num_actions		*/	0,
    /* resources		*/	resources,
    /* num_resources		*/	XtNumber(resources),
    /* xrm_class		*/	NULLQUARK,
    /* compress_motion		*/	TRUE,
    /* compress_exposure	*/	TRUE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest		*/	FALSE,
    /* destroy			*/	Destroy,
    /* resize			*/	Resize,
    /* expose			*/	Redisplay,
    /* set_values		*/	SetValues,
    /* 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		*/	NULL,
    /* display_accelerator      */      XtInheritDisplayAccelerator,
    /* extension                */      NULL,
  },
  /* Title3270 fields */
  { /* empty			*/	0 }
};

WidgetClass title3270WidgetClass = (WidgetClass) &title3270ClassRec;



/* Routine to dynamically set the border width */
/*ARGSUSED*/ static void Setbord(widget, closure, value)
     Widget widget;
     int closure;
     XrmValue *value;
{
  static Dimension val_zero = 0, val_one = 1;

  /* On monochrome displays, set the width to one so that the title is
     separated from the text.  */

  value->size = sizeof(Dimension);
  value->addr = (CellsOfScreen(XtScreen(widget)) > 2 ?
		 (caddr_t) &val_zero : (caddr_t) &val_one);
}



/*** Title3270 class procedures ***/


/*ARGSUSED*/ static void Initialize(request, new)
     Widget request, new;
{
  Title3270Widget tw = (Title3270Widget) new;

  /* Copy the title string to a safe place */
  if (tw->title3270.title)
    tw->title3270.title = strcpy(XtMalloc(strlen(tw->title3270.title) + 1),
				 tw->title3270.title);

  /* If cursor color wasn't specified, set to foreground color */
  if (tw->title3270.cursorColor == defColor)
    tw->title3270.cursorColor = tw->title3270.foreground;

  /* Create a graphics context */
  makegc(tw);

  /* Initialize size and position */
  setsize(tw);
  if (!tw->core.width)
    tw->core.width = tw->title3270.twidth + tw->title3270.swidth +
      tw->title3270.kwidth + tw->title3270.awidth +
      4 * ISPACE + 2 * tw->title3270.iwidth;
  if (tw->core.height == defHeight)
    tw->core.height = tw->title3270.txtheight + 2 * tw->title3270.iheight;
  setpos(tw);
}


static void Realize(w, value_mask, attributes)
     Widget w;
     Mask *value_mask;
     XSetWindowAttributes *attributes;
{
  Title3270Widget tw = (Title3270Widget) w;
  XColor fcolor, bcolor;

  /* Create the window */
  attributes->cursor = tw->title3270.cursor;
  attributes->bit_gravity = CenterGravity;
  *value_mask |= CWCursor | CWBitGravity;
  
  /* A height of zero means don't display a title bar */
  if (tw->core.height)
    XtCreateWindow(w, InputOutput, (Visual *) CopyFromParent,
		   *value_mask, attributes);

  /* Set cursor color to the proper value */
  fcolor.pixel = tw->title3270.cursorColor;
  XQueryColor(XtDisplay(w), tw->core.colormap, &fcolor);
  bcolor.pixel = tw->core.background_pixel;
  XQueryColor(XtDisplay(w), tw->core.colormap, &bcolor);
  XRecolorCursor(XtDisplay(w), tw->title3270.cursor, &fcolor, &bcolor);
}


/*ARGSUSED*/ static void Redisplay(w, event, region)
    Widget w;
    XEvent *event;
    Region region;
{
  Title3270Widget tw = (Title3270Widget) w;

  XClearWindow(XtDisplay(w), XtWindow(w));
  XDrawString(XtDisplay(w), XtWindow(w), tw->title3270.gc,
	      tw->title3270.tx, tw->title3270.ty,
	      tw->title3270.title, strlen(tw->title3270.title));

  if (tw->title3270.inserting && tw->title3270.ax < tw->core.width)
    XDrawString(XtDisplay(w), XtWindow(w), tw->title3270.gc,
		tw->title3270.ax, tw->title3270.ay, "^", 1);

  if (tw->title3270.system && tw->title3270.sx < tw->core.width)
    XDrawString(XtDisplay(w), XtWindow(w), tw->title3270.gc,
		tw->title3270.sx, tw->title3270.sy, "X System", 8);

  if (tw->title3270.aplkeyb && tw->title3270.kx < tw->core.width)
    XDrawString(XtDisplay(w), XtWindow(w), tw->title3270.gc,
                tw->title3270.kx, tw->title3270.ky, "APL", 3);
}


static void Destroy(w)
    Widget w;
{
  Title3270Widget tw = (Title3270Widget) w;
  if (tw->title3270.title) XtFree(tw->title3270.title);
  XtDestroyGC(tw->title3270.gc);
}


static void Resize(w)
    Widget w;
{
  Title3270Widget tw = (Title3270Widget) w;
  setpos(tw);
}


/*ARGSUSED*/ static Boolean SetValues(current, request, new)
     Widget current, request, new;
{
  Title3270Widget curtw = (Title3270Widget) current;
  Title3270Widget newtw = (Title3270Widget) new;
  Boolean redisplay;

  redisplay = False;

  /* Check for color change */
  if (curtw->title3270.foreground != newtw->title3270.foreground)
    {
      XtDestroyGC(curtw->title3270.gc);
      makegc(newtw);
      redisplay = True;
    }

  /* Check for font change */
  if (curtw->title3270.font != newtw->title3270.font)
    {
      XtDestroyGC(curtw->title3270.gc);
      makegc(newtw);
      setsize(newtw);
      setpos(newtw);
      redisplay = True;
    }
      
  /* Check for title string change */
  if (curtw->title3270.title != newtw->title3270.title) 
    {
      if (curtw->title3270.title) XtFree(curtw->title3270.title);
      newtw->title3270.title =
	strcpy(XtMalloc(strlen(newtw->title3270.title) + 1),
	       newtw->title3270.title);
      setsize(newtw);
      setpos(newtw);
      redisplay = True;
    }

  /* Check for cursor color change */
  if (curtw->title3270.cursorColor != newtw->title3270.cursorColor)
    {
      XColor fcolor, bcolor;

      fcolor.pixel = newtw->title3270.cursorColor;
      XQueryColor(XtDisplay(new), newtw->core.colormap, &fcolor);
      bcolor.pixel = newtw->core.background_pixel;
      XQueryColor(XtDisplay(new), newtw->core.colormap, &bcolor);
      XRecolorCursor(XtDisplay(new), newtw->title3270.cursor, &fcolor,
		     &bcolor);
    }

  /* Check for cursor change */
  if (curtw->title3270.cursor != newtw->title3270.cursor)
    XDefineCursor(XtDisplay(new), XtWindow(new), newtw->title3270.cursor);

  /* Check for internal width change */
  if (curtw->title3270.iwidth != newtw->title3270.iwidth ||
      curtw->title3270.iheight != newtw->title3270.iheight)
    {
      setpos(newtw);
      redisplay = True;
    }
  
  /* Check for flag value change */
  if (curtw->title3270.inserting != newtw->title3270.inserting ||
      curtw->title3270.system != newtw->title3270.system ||
      curtw->title3270.aplkeyb != newtw->title3270.aplkeyb)
    redisplay = True;

  return redisplay;
}



/*** Subroutines ***/


#define t(field) tw->title3270.field


/* Create a new graphics context */
static void makegc(tw)
     Title3270Widget tw;
{
  XGCValues gcv;
  gcv.foreground = t(foreground);
  gcv.font = t(font)->fid;
  t(gc) = XtGetGC((Widget) tw, GCForeground | GCFont, &gcv);
}


/* Compute size of the text fields */
static void setsize(tw)
     Title3270Widget tw;
{
  t(txtheight) = t(font)->max_bounds.ascent + t(font)->max_bounds.descent;
  t(twidth) = t(title) ? XTextWidth(t(font), t(title), strlen(t(title))) : 1;
  t(awidth) = XTextWidth(t(font), "^", 1);
  t(swidth) = XTextWidth(t(font), "X System", 8);
  t(kwidth) = XTextWidth(t(font), "APL", 3);
}


/* Compute starting positions of the text fields */
static void setpos(tw)
     Title3270Widget tw;
{
  t(tx) = (tw->core.width - t(twidth)) / 2;
  if (t(tx) < 0) t(tx) = 0;

  t(ty) = (tw->core.height - t(txtheight)) / 2;
  if (t(ty) < 0) t(ty) = 0;
  t(ty) += t(font)->max_bounds.ascent;

  t(ax) = tw->core.width - t(iwidth) - ISPACE - t(awidth);
  if (t(ax) < t(tx) + t(twidth) + ISPACE) t(ax) = tw->core.width;

  t(ay) = t(ty);

  t(sx) = t(ax) - ISPACE - t(swidth);
  if (t(sx) < t(tx) + t(twidth) + ISPACE) t(sx) = tw->core.width;

  t(sy) = t(ty);

  t(kx) = t(sx) - ISPACE - t(kwidth);
  if (t(kx) < t(tx) + t(twidth) + ISPACE) t(kx) = tw->core.width;
 
  t(ky) = t(ty);
}
