
/*-----------------------------------------------------------------------
-------------------------------------------------------------------------

   FILE:	SI_defs.c

   PURPOSE:	Global variables and array allocations and initializations.
		Drivers for 'heavy-duty' SI window management:
		   - Display squares
		   - Command buttons
		
   AUTHOR:	Tan Phan
   DATE:	Spring 1989

   USAGE:	This is one of the C source code.

   HISTORY:	Spring 1989	- Creation

   Copyright 1990-1991 North Carolina State University. All Rights Reserved.
   

-------------------------------------------------------------------------
------------------------------------------------------------------------*/

#include <X11/cursorfont.h>
#include "SI.h"


/*-----------------------------------------------------------------------
-------------------------------------------------------------------------
   Global variables definitions: 
------------------------------------------------------------------------*/

Font		SI_font1,
		SI_font2,
		SI_font3,
		SI_font4,
		SI_font5,
		SI_font6;
XFontStruct	*SI_font1_struct,
		*SI_font2_struct,
		*SI_font3_struct,
		*SI_font4_struct,
		*SI_font5_struct,
		*SI_font6_struct;

SI_mask		SI_window;
Display		*SI_display;
Window		SI_toplevel,
		SI_g1_window;
XSizeHints	SI_hint;
GC		SI_gc;
XEvent		SI_event;
Cursor		SI_cursor,
		SI_CB_cursor,
		SI_ptr_cursor;
Pixmap		SI_bgrd1,
		SI_bgrd2,
		SI_bgrd3,
		SI_bgrd4,
		SI_bgrd5,
		SI_bgrd6;

int		SI_CB_token;
int		SI_TraceDumpOn;
int		SI_expose_event;
char		SI_simulator_name[30+1];
FILE		*SI_TD_ofp;


int		SI_bar01,
			SI_bar01_x0,SI_bar01_y0,
			SI_bar01_x1,SI_bar01_y1,
		SI_bar12,
			SI_bar12_x0,SI_bar12_y0,
			SI_bar12_x1,SI_bar12_y1,
		SI_bar234,
			SI_bar234_x0,SI_bar234_y0,
			SI_bar234_x1,SI_bar234_y1,
		SI_bar34,
			SI_bar34_x0,SI_bar34_y0,
			SI_bar34_x1,SI_bar34_y1,
		SI_bar345,
			SI_bar345_x0,SI_bar345_y0,
			SI_bar345_x1,SI_bar345_y1,
		SI_bardscb,
			SI_bardscb_x0,SI_bardscb_y0,
			SI_bardscb_x1,SI_bardscb_y1,
		SI_bar32,
			SI_bar32_x0,SI_bar32_y0,
			SI_bar32_x1,SI_bar32_y1,
		SI_bar51,
			SI_bar51_x0,SI_bar51_y0,
			SI_bar51_x1,SI_bar51_y1;

int		SI_high_x,
		SI_high_y;

int		SI_g1_width,
		SI_g1_height;

int		SI_ds1_top_free,SI_ds1_left_free,
		SI_ds1_right_free,SI_ds1_bottom_free,
		SI_ds1_spacing,SI_ds1_width,SI_ds1_height,
		SI_ds1_txt_offset,
		SI_ds1_org_x,SI_ds1_org_y,
		
   		SI_ds2_top_free,SI_ds2_left_free,
		SI_ds2_right_free,SI_ds2_bottom_free,
		SI_ds2_spacing,SI_ds2_width,SI_ds2_height,
		SI_ds2_txt_offset,
		SI_ds2_org_x,SI_ds2_org_y,
		
   		SI_ds3_top_free,SI_ds3_left_free,
		SI_ds3_right_free,SI_ds3_bottom_free,
		SI_ds3_spacing,SI_ds3_width,SI_ds3_height,
		SI_ds3_txt_offset,
		SI_ds3_org_x,SI_ds3_org_y,
		
   		SI_ds4_top_free,SI_ds4_left_free,
		SI_ds4_right_free,SI_ds4_bottom_free,
		SI_ds4_spacing,SI_ds4_width,SI_ds4_height,
		SI_ds4_txt_offset,
		SI_ds4_org_x,SI_ds4_org_y,
		
   		SI_ds5_top_free,SI_ds5_left_free,
		SI_ds5_right_free,SI_ds5_bottom_free,
		SI_ds5_spacing,SI_ds5_width,SI_ds5_height,
		SI_ds5_txt_offset,
		SI_ds5_org_x,SI_ds5_org_y,
		
   		SI_cb1_top_free,SI_cb1_left_free,
		SI_cb1_right_free,SI_cb1_bottom_free,
		SI_cb1_spacing,SI_cb1_width,SI_cb1_height,
		SI_cb1_txt_offset,
		SI_cb1_org_x,SI_cb1_org_y,
		
   		SI_cb2_top_free,SI_cb2_left_free,
		SI_cb2_right_free,SI_cb2_bottom_free,
		SI_cb2_spacing,SI_cb2_width,SI_cb2_height,
		SI_cb2_txt_offset,
		SI_cb2_org_x,SI_cb2_org_y,
		
   		SI_cb3_top_free,SI_cb3_left_free,
		SI_cb3_right_free,SI_cb3_bottom_free,
		SI_cb3_spacing,SI_cb3_width,SI_cb3_height,
		SI_cb3_txt_offset,
		SI_cb3_org_x,SI_cb3_org_y;


/*-----------------------------------------------------------------------
   Pixmaps data:
------------------------------------------------------------------------*/
#define SI_bitmap1_width 8
#define SI_bitmap1_height 8
#define SI_bitmap1_x_hot 3
#define SI_bitmap1_y_hot 4
static char SI_bitmap1_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

#define SI_bitmap2_width 8
#define SI_bitmap2_height 8
#define SI_bitmap2_x_hot 3
#define SI_bitmap2_y_hot 3
static char SI_bitmap2_bits[] = {
   0x6d, 0xdb, 0xb6, 0x6d, 0xdb, 0xb6, 0x6d, 0xdb};

#define SI_bitmap3_width 8
#define SI_bitmap3_height 8
#define SI_bitmap3_x_hot -1
#define SI_bitmap3_y_hot -1
static char SI_bitmap3_bits[] = {
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

#define SI_bitmap4_width 8
#define SI_bitmap4_height 8
#define SI_bitmap4_x_hot 4
#define SI_bitmap4_y_hot 3
static char SI_bitmap4_bits[] = {
   0xb6, 0xdb, 0x6d, 0xb6, 0xdb, 0x6d, 0xb6, 0xdb};

#define SI_bitmap5_width 8
#define SI_bitmap5_height 8
#define SI_bitmap5_x_hot 3
#define SI_bitmap5_y_hot 3
static char SI_bitmap5_bits[] = {
   0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55};

#define SI_bitmap6_width 8
#define SI_bitmap6_height 8
#define SI_bitmap6_x_hot 3
#define SI_bitmap6_y_hot 3
static char SI_bitmap6_bits[] = {
   0x99, 0xff, 0x66, 0xff, 0x99, 0xff, 0x66, 0xff};


/*-----------------------------------------------------------------------
-------------------------------------------------------------------------
   SI_str_equal:

   Compare two strings for equality.
------------------------------------------------------------------------*/
int SI_str_equal(str1,str2)
char			*str1,
			*str2;
{  int			i;

   for (i=0; str1[i]==str2[i] && str1[i]!='\0'; i++);
   if (str1[i]==str2[i])
      return (true);
   else
      return(false);
}


/*-----------------------------------------------------------------------
   SI_ri:

   Read data and init each DS and CB.
------------------------------------------------------------------------*/
void SI_ri(ifp,square)
FILE			*ifp;
DS			*square;
{  CB			*ptr;
   int		tvlen,
		ii;
   char		tdefined[MAXB_LEN+1],
		tformat[MAXB_LEN+1],
		tstate[MAXB_LEN+1],
		tname[MAXB_LEN+1];

   switch (square->type)
   {  case SI_TDS1:
	 square->vlen = SI_LDS1;
      case SI_TDS2:
	 square->vlen = SI_LDS2;
      case SI_TDS3:
	 square->vlen = SI_LDS3;
      case SI_TDS4:
	 square->vlen = SI_LDS4;
      case SI_TDS5:
	 square->vlen = SI_LDS5;

         fscanf(ifp,"%s %s %d %s %s", tdefined, tformat, &tvlen, 
					tstate, tname);
	 if (SI_str_equal(tdefined,"defined"))
            square->defined = true;
	 else if (SI_str_equal(tdefined,"undefined"))
            square->defined = false;
	 else
	 {  printf("SI(warning):Illegal DS definition keyword: %s.\n",
				tdefined);
	    printf("           :Assume definition keyword 'undefined'.\n");
            square->defined = false;
	 };

	 if (SI_str_equal(tformat,"hex"))
            square->format = SI_FHEX;
	 else if (SI_str_equal(tformat,"dec"))
            square->format = SI_FDEC;
	 else if (SI_str_equal(tformat,"oct"))
            square->format = SI_FOCT;
	 else if (SI_str_equal(tformat,"bin"))
            square->format = SI_FBIN;
	 else if (SI_str_equal(tformat,"chr"))
            square->format = SI_FCHR;
	 else
	 {  printf("SI(warning):Illegal DS format keyword: %s.\n",tformat);
	    printf("           :Assume format keyword 'hex'.\n");
            square->format = SI_FHEX;
	 };

	 if (tvlen<square->vlen)
            square->vlen = tvlen;

         for (ii=0; ii<strlen(tname); ii++)
            square->name[ii] = tname[ii];
         square->name[ii] = '\0';
         square->addr_value = NULL;
	 for (ii=0; ii<MAXN_LEN+1; ii++)
	    square->oldval[ii] = '?';

         if (SI_str_equal(tstate,"active"))
            square->attr.state = SI_SACTIVE;
         else if (SI_str_equal(tstate,"inactive"))
            square->attr.state = SI_SINACTIVE;
	 else
	 {  printf("SI(warning):Illegal DS state keyword: %s.\n",tstate);
	    printf("           :Assume state keyword 'inactive'.\n");
            square->attr.state = SI_SINACTIVE;
	 };
	 break;

      case SI_TCB1:
      case SI_TCB2:
      case SI_TCB3:
	 ptr = (CB *)square;
         fscanf(ifp,"%s %s %s", tdefined, tstate, tname);

	 if (SI_str_equal(tdefined,"defined"))
            ptr->defined = true;
	 else if (SI_str_equal(tdefined,"undefined"))
            ptr->defined = false;
	 else
	 {  printf("SI(warning):Illegal CB definition keyword: %s.\n",
				tdefined);
	    printf("           :Assume definition keyword 'undefined'.\n");
            ptr->defined = false;
	 };

         for (ii=0; ii<strlen(tname); ii++)
            ptr->name[ii] = tname[ii];
         ptr->name[ii] = '\0';

         if (SI_str_equal(tstate,"active"))
            ptr->attr.state = SI_SACTIVE;
         else if (SI_str_equal(tstate,"inactive"))
            ptr->attr.state = SI_SINACTIVE;
	 else
	 {  printf("SI(warning):Illegal CB state keyword: %s.\n",tstate);
	    printf("           :Assume state keyword 'inactive'.\n");
            ptr->attr.state = SI_SINACTIVE;
	 };
	 break;
   };
}


/*-----------------------------------------------------------------------
   SI_read_data:

   Read setup data from file SI_data.  The data composes of DS and CB 
   attributes and the region bars attributes.

   The routine also initializes the fields in the DS and CB.
------------------------------------------------------------------------*/
int SI_read_data()
{  FILE		*ifp;
   int		i;

   
   /* Open data to init the SI window:					*/
   ifp = fopen(SI_FNAME,"r");
   if (ifp==NULL)
      return (false);

   /* Get the simulator name:						*/
   fscanf(ifp,"%s",SI_simulator_name);

   /* Init DS1:								*/
   for (i=0; i<40; i++)
   {  SI_window.DS1[i].type = SI_TDS1;
      SI_ri(ifp,&SI_window.DS1[i]);
   };

   /* Init DS2:								*/
   for (i=0; i<16; i++)
   {  SI_window.DS2[i].type = SI_TDS2;
      SI_ri(ifp,&SI_window.DS2[i]);
   };

   /* Init DS3:								*/
   for (i=0; i<4; i++)
   {  SI_window.DS3[i].type = SI_TDS3;
      SI_ri(ifp,&SI_window.DS3[i]);
   };

   /* Init DS4:								*/
   for (i=0; i<4; i++)
   {  SI_window.DS4[i].type = SI_TDS4;
      SI_ri(ifp,&SI_window.DS4[i]);
   };

   /* Init DS5:								*/
   for (i=0; i<8; i++)
   {  SI_window.DS5[i].type = SI_TDS5;
      SI_ri(ifp,&SI_window.DS5[i]);
   };

   /* Init CB1:								*/
   for (i=0; i<16; i++)
   {  SI_window.CB1[i].type = SI_TCB1;
      SI_ri(ifp,&SI_window.CB1[i]);
   };

   /* Init CB2:								*/
   for (i=0; i<4; i++)
   {  SI_window.CB2[i].type = SI_TCB2;
      SI_ri(ifp,&SI_window.CB2[i]);
   };

   /* Init CB3:								*/
   for (i=0; i<4; i++)
   {  SI_window.CB3[i].type = SI_TCB3;
      SI_ri(ifp,&SI_window.CB3[i]);
   };

   /* Load default window mask which inludes DS and CB sized as well	*/
   /* as regions separators widths and spacing:				*/
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_bar01,&SI_bar12,&SI_bar234,&SI_bar34,&SI_bar345,
		&SI_bar51,&SI_bardscb,&SI_bar32);

   /* Load DS parameters:						*/
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_ds1_top_free,&SI_ds1_left_free,&SI_ds1_right_free,
		&SI_ds1_bottom_free,
		&SI_ds1_spacing,&SI_ds1_width,&SI_ds1_height,
		&SI_ds1_txt_offset);
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_ds2_top_free,&SI_ds2_left_free,&SI_ds2_right_free,
		&SI_ds2_bottom_free,
		&SI_ds2_spacing,&SI_ds2_width,&SI_ds2_height,
		&SI_ds2_txt_offset);
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_ds3_top_free,&SI_ds3_left_free,&SI_ds3_right_free,
		&SI_ds3_bottom_free,
		&SI_ds3_spacing,&SI_ds3_width,&SI_ds3_height,
		&SI_ds3_txt_offset);
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_ds4_top_free,&SI_ds4_left_free,&SI_ds4_right_free,
		&SI_ds4_bottom_free,
		&SI_ds4_spacing,&SI_ds4_width,&SI_ds4_height,
		&SI_ds4_txt_offset);
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_ds5_top_free,&SI_ds5_left_free,&SI_ds5_right_free,
		&SI_ds5_bottom_free,
		&SI_ds5_spacing,&SI_ds5_width,&SI_ds5_height,
		&SI_ds5_txt_offset);

   /* Load CB parameters:						*/
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_cb1_top_free,&SI_cb1_left_free,&SI_cb1_right_free,
		&SI_cb1_bottom_free,
		&SI_cb1_spacing,&SI_cb1_width,&SI_cb1_height,
		&SI_cb1_txt_offset);
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_cb2_top_free,&SI_cb2_left_free,&SI_cb2_right_free,
		&SI_cb2_bottom_free,
		&SI_cb2_spacing,&SI_cb2_width,&SI_cb2_height,
		&SI_cb2_txt_offset);
   fscanf(ifp,"%d %d %d %d %d %d %d %d",
		&SI_cb3_top_free,&SI_cb3_left_free,&SI_cb3_right_free,
		&SI_cb3_bottom_free,
		&SI_cb3_spacing,&SI_cb3_width,&SI_cb3_height,
		&SI_cb3_txt_offset);

   fclose(ifp);
   return (true);
}


/*-----------------------------------------------------------------------
   SI_read_font:

   Open the display and read in the fonts.
------------------------------------------------------------------------*/
int SI_read_font()
{

   /* Open the display for SI:						*/
   SI_display = XOpenDisplay("");
   if (SI_display==NULL)
      return (false);

   /* Load fonts:							*/
   SI_font1_struct = XLoadQueryFont(SI_display,SI_NFONT1);
   SI_font2_struct = XLoadQueryFont(SI_display,SI_NFONT2);
   SI_font3_struct = XLoadQueryFont(SI_display,SI_NFONT3);
   SI_font4_struct = XLoadQueryFont(SI_display,SI_NFONT4);
   SI_font5_struct = XLoadQueryFont(SI_display,SI_NFONT5);
   SI_font6_struct = XLoadQueryFont(SI_display,SI_NFONT6);
   SI_font1 = SI_font1_struct->fid;
   SI_font2 = SI_font2_struct->fid;
   SI_font3 = SI_font3_struct->fid;
   SI_font4 = SI_font4_struct->fid;
   SI_font5 = SI_font5_struct->fid;
   SI_font6 = SI_font6_struct->fid;
   return (true);
}


/*-----------------------------------------------------------------------
   SI_create_DS_child:

   Create the child windows for DS and CB.
------------------------------------------------------------------------*/
void SI_create_DS_child(square,width,height,bw)
DS			*square;
int			width,height,
			bw;
{  int			x,y;
   unsigned long	valuemask;


   switch (square->type)
   {  /* Create child windows for DS:					*/
      case SI_TDS1:
      case SI_TDS2:
      case SI_TDS3:
      case SI_TDS4:
      case SI_TDS5:
         x = square->attr.x;
         y = square->attr.y;
         square->attr.dsw1 = XCreateSimpleWindow(SI_display,
					SI_toplevel,x,y,
					width,height,bw,0,1);
         valuemask = ButtonPressMask | KeyPressMask;
         XSelectInput(SI_display,square->attr.dsw1,valuemask);
         XDefineCursor(SI_display,square->attr.dsw1,SI_cursor);
         XMapWindow(SI_display,square->attr.dsw1);

         /* Create the child window for displaying DS value:		*/
         if (square->type!=SI_TDS5)
         {  square->attr.dsw2 = XCreateSimpleWindow(SI_display,
					SI_toplevel,x,y + height/2,
					width,height/2,bw,0,1);
            valuemask = ButtonPressMask | KeyPressMask;
            XSelectInput(SI_display,square->attr.dsw2,valuemask);
	    XDefineCursor(SI_display,square->attr.dsw2,SI_ptr_cursor);
	    XMapWindow(SI_display,square->attr.dsw2);
         };
         break;
   }
}


/*-----------------------------------------------------------------------
   SI_create_CB_child:

   Create the child windows for CB.
------------------------------------------------------------------------*/
void SI_create_CB_child(square,width,height,bw)
CB			*square;
int			width,height,
			bw;
{  int			x,y;
   unsigned long	valuemask;


   switch (square->type)
   {  /* Create the CB as child windows:				*/
      case SI_TCB1:
      case SI_TCB2:
      case SI_TCB3:
            x = square->attr.x;
	    y = square->attr.y;
            square->attr.cbw = XCreateSimpleWindow(SI_display,
					SI_toplevel,x,y,
					width,height,bw,0,1);
            valuemask = EnterWindowMask | LeaveWindowMask | ButtonPressMask;
            XSelectInput(SI_display,square->attr.cbw,valuemask);
	    XDefineCursor(SI_display,square->attr.cbw,SI_CB_cursor);
	    XMapWindow(SI_display,square->attr.cbw);
	    break;
   }
}


/*-----------------------------------------------------------------------
   SI_create_window:

   Call X server and set up the actual SI window, the DS child windows,
   and the CB child windows.
------------------------------------------------------------------------*/
void SI_create_window()
{  unsigned long	valuemask;
   XGCValues		values;

   int			i,j,
			x,y;
   int			pm_w,
			pm_h,
			pm_x,
			pm_y,
			perr;

   /* Create the SI window:						*/
      SI_hint.x = 50;
      SI_hint.y = 90;
      SI_hint.width = SI_high_x;
      SI_hint.height = SI_high_y;
      SI_hint.min_width = SI_high_x;
      SI_hint.min_height = SI_high_y;
      SI_hint.max_width = SI_high_x;
      SI_hint.max_height = SI_high_y;
      SI_hint.flags = PPosition | PSize | PMinSize | PMaxSize;

   SI_toplevel = XCreateSimpleWindow(SI_display,
			DefaultRootWindow(SI_display),SI_hint.x,SI_hint.y,
			SI_hint.width,SI_hint.height,7,0,1);

   XSetStandardProperties(SI_display,SI_toplevel,SI_simulator_name,
			  SI_ICON_NAME,None,0,0,&SI_hint);

   SI_cursor = XCreateFontCursor(SI_display,XC_man);
   SI_CB_cursor = XCreateFontCursor(SI_display,XC_hand1);
   SI_ptr_cursor = XCreateFontCursor(SI_display,XC_center_ptr);
   XDefineCursor(SI_display,SI_toplevel,SI_cursor);

   /* Load pixmaps:							*/
   SI_bgrd1 = XCreatePixmapFromBitmapData(SI_display, SI_toplevel,
                SI_bitmap1_bits, SI_bitmap1_width, SI_bitmap1_height,
                1, 0, XDisplayPlanes(SI_display, 0));
   SI_bgrd2 = XCreatePixmapFromBitmapData(SI_display, SI_toplevel,
                SI_bitmap2_bits, SI_bitmap2_width, SI_bitmap2_height,
                1, 0, XDisplayPlanes(SI_display, 0));
   SI_bgrd3 = XCreatePixmapFromBitmapData(SI_display, SI_toplevel,
                SI_bitmap3_bits, SI_bitmap3_width, SI_bitmap3_height,
                1, 0, XDisplayPlanes(SI_display, 0));
   SI_bgrd4 = XCreatePixmapFromBitmapData(SI_display, SI_toplevel,
                SI_bitmap4_bits, SI_bitmap4_width, SI_bitmap4_height,
                1, 0, XDisplayPlanes(SI_display, 0));
   SI_bgrd5 = XCreatePixmapFromBitmapData(SI_display, SI_toplevel,
                SI_bitmap5_bits, SI_bitmap5_width, SI_bitmap5_height,
                1, 0, XDisplayPlanes(SI_display, 0));
   SI_bgrd6 = XCreatePixmapFromBitmapData(SI_display, SI_toplevel,
                SI_bitmap6_bits, SI_bitmap6_width, SI_bitmap6_height,
                1, 0, XDisplayPlanes(SI_display, 0));

      valuemask = GCCapStyle | GCJoinStyle | GCLineWidth;
      values.cap_style = CapButt;
      values.join_style = JoinMiter;
      values.line_width = 1;
   SI_gc = XCreateGC(SI_display,SI_toplevel,valuemask,&values);

      valuemask = ExposureMask | ButtonPressMask;
   XSelectInput(SI_display,SI_toplevel,valuemask);
   XSetWindowBackgroundPixmap(SI_display,SI_toplevel,SI_bgrd6);
   XMapWindow(SI_display,SI_toplevel);

   /* Draw the g1 area:							*/
   SI_g1_window = XCreateSimpleWindow(SI_display,
			SI_toplevel,0,0,
			SI_g1_width,SI_g1_height,0,0,1);
   XSetWindowBackgroundPixmap(SI_display,SI_g1_window,SI_bgrd5);
   valuemask = ButtonPressMask | KeyPressMask | ExposureMask;
   XSelectInput(SI_display,SI_g1_window,valuemask);
   XMapWindow(SI_display,SI_g1_window);


   /* Create child windows for DS:					*/
   /* Draw region DS1:							*/
   for (i=0; i<40; i++)
      if (SI_window.DS1[i].defined)
	 SI_create_DS_child(&SI_window.DS1[i],
				SI_ds1_width,SI_ds1_height,SI_WDS1);

   /* Draw region DS2:							*/
   for (i=0; i<16; i++)
      if (SI_window.DS2[i].defined)
	 SI_create_DS_child(&SI_window.DS2[i],
				SI_ds2_width,SI_ds2_height,SI_WDS2);

   /* Draw region DS3:							*/
   for (i=0; i<4; i++)
      if (SI_window.DS3[i].defined)
	 SI_create_DS_child(&SI_window.DS3[i],
				SI_ds3_width,SI_ds3_height,SI_WDS3);

   /* Draw region DS4:							*/
   for (i=0; i<4; i++)
      if (SI_window.DS4[i].defined)
	 SI_create_DS_child(&SI_window.DS4[i],
				SI_ds4_width,SI_ds4_height,SI_WDS4);

   /* Draw region DS5:							*/
   for (i=0; i<8; i++)
      if (SI_window.DS5[i].defined)
	 SI_create_DS_child(&SI_window.DS5[i],
				SI_ds5_width,SI_ds5_height,SI_WDS5);


   /* Create the CB as child windows:					*/
   /* For CB1:								*/
   for (i=0; i<16; i++)
      if (SI_window.CB1[i].defined)
	 SI_create_CB_child(&SI_window.CB1[i],
				SI_cb1_width,SI_cb1_height,SI_WCB1);

   /* For CB2:								*/
   for (i=0; i<4; i++)
      if (SI_window.CB2[i].defined)
	 SI_create_CB_child(&SI_window.CB2[i],
				SI_cb2_width,SI_cb2_height,SI_WCB2);

   /* For CB3:								*/
   for (i=0; i<4; i++)
      if (SI_window.CB3[i].defined)
	 SI_create_CB_child(&SI_window.CB3[i],
				SI_cb3_width,SI_cb3_height,SI_WCB3);
}


/*-----------------------------------------------------------------------
   SI_calc_mask:

   Calc everything needed to draw the SI window.
------------------------------------------------------------------------*/
void SI_calc_mask()
{  int			SI_ds1_total_x,SI_ds1_total_y,
			SI_ds2_total_x,SI_ds2_total_y,
			SI_ds3_total_x,SI_ds3_total_y,
			SI_ds4_total_x,SI_ds4_total_y,
			SI_ds5_total_x,SI_ds5_total_y,
			SI_cb1_total_x,SI_cb1_total_y,
			SI_cb2_total_x,SI_cb2_total_y,
			SI_cb3_total_x,SI_cb3_total_y,

			SI_ds34_total_x,SI_ds34_total_y,

			SI_thigh_x,SI_thigh_y;

   int			i,j,
			txt_width;
			

   /* Calc region DS1:							*/
   SI_ds1_org_x = SI_ds1_left_free;
   SI_ds1_org_y = SI_bar01 + SI_ds1_top_free;
   SI_ds1_total_x = SI_ds1_left_free + 8*(2*SI_ds1_spacing + SI_ds1_width) +
		SI_ds1_right_free;
   SI_ds1_total_y = SI_ds1_top_free + 5*(2*SI_ds1_spacing + SI_ds1_height) +
		SI_ds1_bottom_free;
   SI_high_x = SI_ds1_total_x;
   SI_high_y = SI_ds1_total_y;

   /* Define the positions of the DS1 in the SI window:			*/
   for (i=0; i<5; i++)
      for (j=0; j<8; j++)
      {  SI_window.DS1[i*8+j].attr.x = SI_ds1_org_x + 
				j*(2*SI_ds1_spacing + SI_ds1_width);
	 SI_window.DS1[i*8+j].attr.y = SI_ds1_org_y +
				i*(2*SI_ds1_spacing + SI_ds1_height);

	 /* Center the text:						*/
	 txt_width = XTextWidth(SI_font1_struct,
			SI_window.DS1[i*8+j].name,
			strlen(SI_window.DS1[i*8+j].name));
	 SI_window.DS1[i*8+j].center = (SI_ds1_width - txt_width)/2;
      };

   /* Here, we can calc the source of the top bar:			*/
   SI_bar01_x0 = 0;
   SI_bar01_y0 = 0;
   SI_bar01_y1 = 0;

   /* Here, we can calc the source of bar 12:				*/
   SI_bar12_x0 = 0;
   SI_bar12_y0 = SI_high_y;
   SI_bar12_y1 = SI_high_y;

   /* Calc region DS2:							*/
   SI_ds2_org_x = SI_ds2_left_free;
   SI_ds2_org_y = SI_high_y + SI_bar12 + SI_ds2_top_free;
   SI_ds2_total_x = SI_ds2_left_free + 16*(2*SI_ds2_spacing + SI_ds2_width) +
		    SI_ds2_right_free;
   SI_ds2_total_y = SI_ds2_top_free + (2*SI_ds2_spacing + SI_ds2_height) +
		    SI_ds2_bottom_free;
   if (SI_ds2_total_x>SI_high_x)
      SI_high_x = SI_ds2_total_x;
   SI_high_y = SI_high_y + SI_bar12 + SI_ds2_total_y;

   /* Define the positions of the DS2 in the SI window:			*/
   for (j=0; j<16; j++)
   {  SI_window.DS2[j].attr.x = SI_ds2_org_x + 
				j*(2*SI_ds2_spacing + SI_ds2_width);
      SI_window.DS2[j].attr.y = SI_ds2_org_y;

      /* Center the text:						*/
      txt_width = XTextWidth(SI_font1_struct,SI_window.DS2[j].name,
				strlen(SI_window.DS2[j].name));
      SI_window.DS2[j].center = (SI_ds2_width - txt_width)/2;
   };

   /* Here, we can calc the source of bar 234:				*/
   SI_bar234_x0 = 0;
   SI_bar234_y0 = SI_high_y;
   SI_bar234_y1 = SI_high_y;

   /* Calc region DS3:							*/
   SI_ds3_org_x = SI_ds3_left_free;
   SI_ds3_org_y = SI_high_y + SI_bar234 + SI_ds3_top_free;
   SI_ds3_total_x = SI_ds3_left_free + 4*(2*SI_ds3_spacing + SI_ds3_width) +
		    SI_ds3_right_free;
   SI_ds3_total_y = SI_ds3_top_free + (2*SI_ds3_spacing + SI_ds3_height) +
		    SI_ds3_bottom_free;

   /* Define the positions for the DS3 in the SI window:		*/
   for (j=0; j<4; j++)
   {  SI_window.DS3[j].attr.x = SI_ds3_org_x +
				j*(2*SI_ds3_spacing + SI_ds3_width);
      SI_window.DS3[j].attr.y = SI_ds3_org_y;

      /* Center the text:						*/
      txt_width = XTextWidth(SI_font1_struct,SI_window.DS3[j].name,
				strlen(SI_window.DS3[j].name));
      SI_window.DS3[j].center = (SI_ds3_width - txt_width)/2;
   };

   /* Here, we can calc the source of bar 34:				*/
   SI_bar34_x0 = SI_ds3_total_x;
   SI_bar34_y0 = SI_high_y;
   SI_bar34_x1 = SI_ds3_total_x;

   /* Calc region DS4:							*/
   SI_ds4_org_x = SI_ds3_total_x + SI_bar34 + SI_ds4_left_free;
   SI_ds4_org_y = SI_high_y + SI_bar234 + SI_ds4_top_free;
   SI_ds4_total_x = SI_ds4_left_free + 4*(2*SI_ds4_spacing + SI_ds4_width) +
		    SI_ds4_right_free;
   SI_ds4_total_y = SI_ds4_top_free + (2*SI_ds4_spacing + SI_ds4_height) +
		    SI_ds4_bottom_free;

   SI_ds34_total_x = SI_ds3_total_x + SI_bar34 + SI_ds4_total_x;
   if (SI_ds3_total_y>SI_ds4_total_y)
      SI_ds34_total_y = SI_ds3_total_y;
   else
      SI_ds34_total_y = SI_ds4_total_y;

   if (SI_ds34_total_x>SI_high_x)
      SI_high_x = SI_ds34_total_x;
   SI_high_y = SI_high_y + SI_bar234 + SI_ds34_total_y;

   /* Define the positions for the DS4 in the SI window:		*/
   for (j=0; j<4; j++)
   {  SI_window.DS4[j].attr.x = SI_ds4_org_x +
				j*(2*SI_ds4_spacing + SI_ds4_width);
      SI_window.DS4[j].attr.y = SI_ds4_org_y;

      /* Center the text:						*/
      txt_width = XTextWidth(SI_font1_struct,SI_window.DS4[j].name,
				strlen(SI_window.DS4[j].name));
      SI_window.DS4[j].center = (SI_ds4_width - txt_width)/2;
   };

   /* Here, we can calc the destination for bar 34:			*/
   SI_bar34_y1 = SI_high_y;

   /* Here, we can calc the source of bar 345:				*/
   SI_bar345_x0 = 0;
   SI_bar345_y0 = SI_high_y;
   SI_bar345_y1 = SI_high_y;

   /* Calc region DS5:							*/
   SI_ds5_org_x = SI_ds5_left_free;
   SI_ds5_org_y = SI_high_y + SI_bar345 + SI_ds5_top_free;
   SI_ds5_total_x = SI_ds5_left_free + 8*(2*SI_ds5_spacing + SI_ds5_width) +
		    SI_ds5_right_free;
   SI_ds5_total_y = SI_ds5_top_free + (2*SI_ds5_spacing + SI_ds5_height) +
		    SI_ds5_bottom_free;

   if (SI_ds5_total_x>SI_high_x)
      SI_high_x = SI_ds5_total_x;
   SI_high_y = SI_high_y + SI_bar345 + SI_ds5_total_y;

   /* Can now define the g1 area width:					*/
   SI_g1_width = SI_high_x - SI_bardscb/2;

   /* Define the positions of the DS5 in the SI window:			*/
   for (j=0; j<8; j++)
   {  SI_window.DS5[j].attr.x = SI_ds5_org_x + 
				j*(2*SI_ds5_spacing + SI_ds5_width);
      SI_window.DS5[j].attr.y = SI_ds5_org_y;

      /* Center the text:						*/
      txt_width = XTextWidth(SI_font1_struct,SI_window.DS5[j].name,
				strlen(SI_window.DS5[j].name));
      SI_window.DS5[j].center = (SI_ds5_width - txt_width)/2;
   };

   /* Here, we can calc the destination bar 12, bar 234, and bar 345:	*/
   SI_bar12_x1 = SI_high_x;
   SI_bar234_x1 = SI_high_x;
   SI_bar345_x1 = SI_high_x;

   /* Here, we can set the position of the vertical bar that separates	*/
   /* the DS from the CB:						*/
   SI_bardscb_x0 = SI_high_x;
   SI_bardscb_y0 = 0; 
   SI_bardscb_x1 = SI_high_x;

   /* Calc region CB3:							*/
   SI_cb3_org_x = SI_high_x + SI_bardscb + SI_cb3_left_free;
   SI_cb3_org_y = SI_bar01 + SI_cb3_top_free;
   SI_cb3_total_x = SI_cb3_left_free + (2*SI_cb3_spacing + SI_cb3_width) +
		    SI_cb3_right_free;
   SI_cb3_total_y = SI_cb3_top_free + 4*(2*SI_cb3_spacing + SI_cb3_height) +
		    SI_cb3_bottom_free;

   SI_thigh_x = SI_cb3_total_x;
   SI_thigh_y = SI_cb3_total_y;

   /* Define the positions for the CB3 in the SI window:		*/
   for (i=0; i<4; i++)
   {  SI_window.CB3[i].attr.x = SI_cb3_org_x;
      SI_window.CB3[i].attr.y = SI_cb3_org_y +
				i*(2*SI_cb3_spacing + SI_cb3_height);

      /* Center the text:						*/
      txt_width = XTextWidth(SI_font2_struct,SI_window.CB3[i].name,
				strlen(SI_window.CB3[i].name));
      SI_window.CB3[i].center = (SI_cb3_width - txt_width)/2;
   };

   /* Here, we can calc the source for bar 32:				*/
   SI_bar32_x0 = SI_high_x;
   SI_bar32_y0 = SI_thigh_y;
   SI_bar32_y1 = SI_thigh_y;

   /* Calc region CB2:							*/
   SI_cb2_org_x = SI_high_x + SI_bardscb + SI_cb2_left_free;
   SI_cb2_org_y = SI_thigh_y + SI_bar32 + SI_cb2_top_free;
   SI_cb2_total_x = SI_cb2_left_free + (2*SI_cb2_spacing + SI_cb2_width) +
		    SI_cb2_right_free;
   SI_cb2_total_y = SI_cb2_top_free + 4*(2*SI_cb2_spacing + SI_cb2_height) +
		    SI_cb2_bottom_free;

   if (SI_cb2_total_x>SI_thigh_x)
      SI_thigh_x = SI_cb2_total_x;
   SI_thigh_y = SI_thigh_y + SI_bar32 + SI_cb2_total_y;


   SI_high_x = SI_high_x + SI_bardscb + SI_thigh_x;
   if (SI_thigh_y>SI_high_y)
      SI_high_y = SI_thigh_y;

   /* Can now define the g1 area height:				*/
   SI_g1_height = SI_high_y - SI_bar51/2;

   /* Define the positions for the CB2 in the SI window:		*/
   for (i=0; i<4; i++)
   {  SI_window.CB2[i].attr.x = SI_cb2_org_x;
      SI_window.CB2[i].attr.y = SI_cb2_org_y +
				i*(2*SI_cb2_spacing + SI_cb2_height);

      /* Center the text:						*/
      txt_width = XTextWidth(SI_font2_struct,SI_window.CB2[i].name,
				strlen(SI_window.CB2[i].name));
      SI_window.CB2[i].center = (SI_cb2_width - txt_width)/2;
   };

   /* Here, we can calc the destination of the bar separating DS and CB:*/
   SI_bardscb_y1 = SI_high_y;

   /* Here, we can calc the source of bar 51:				*/
   SI_bar51_x0 = 0;
   SI_bar51_y0 = SI_high_y;
   SI_bar51_y1 = SI_high_y;

   /* Calc region CB1:							*/
   SI_cb1_org_x = SI_cb1_left_free;
   SI_cb1_org_y = SI_high_y + SI_bar51 + SI_cb1_top_free;
   SI_cb1_total_x = SI_cb1_left_free + 8*(2*SI_cb1_spacing + SI_cb1_width) +
		    SI_cb1_right_free;
   SI_cb1_total_y = SI_cb1_top_free + 2*(2*SI_cb1_spacing + SI_cb1_height) +
		    SI_cb1_bottom_free;

   /* Here, the overall size of the SI window is determined:		*/
   /* The width is SI_high_x and the height is SI_high_y:		*/
   if (SI_cb1_total_x>SI_high_x)
      SI_high_x = SI_cb1_total_x;
   SI_high_y = SI_high_y + SI_bar51 + SI_cb1_total_y;

   /* Define the positions of the CB1 in the SI window:			*/
   for (i=0; i<2; i++)
      for (j=0; j<8; j++)
      {  SI_window.CB1[i*8+j].attr.x = SI_cb1_org_x + 
				j*(2*SI_cb1_spacing + SI_cb1_width);
         SI_window.CB1[i*8+j].attr.y = SI_cb1_org_y +
				i*(2*SI_cb1_spacing + SI_cb1_height);

	 /* Center the text:						*/
	 txt_width = XTextWidth(SI_font2_struct,
			SI_window.CB1[i*8+j].name,
			strlen(SI_window.CB1[i*8+j].name));
	 SI_window.CB1[i*8+j].center = (SI_cb1_width - txt_width)/2;
      };

   /* Here, we can calc the destination of the top bar, bar 51, bar 32:*/
   SI_bar01_x1 = SI_high_x;
   SI_bar51_x1 = SI_high_x;
   SI_bar32_x1 = SI_high_x;
}


/*-----------------------------------------------------------------------
   SI_draw_regions:

   Draw the lines that separate the different regions.
------------------------------------------------------------------------*/
void SI_draw_regions()
{

   /* Draw the top bar (bar 01):					*/
   XSetLineAttributes(SI_display,SI_gc,SI_bar01,
			LineSolid,CapButt,JoinMiter);
   XDrawLine(SI_display,SI_toplevel,SI_gc,
			SI_bar01_x0,SI_bar01_y0,
			SI_bar01_x1,SI_bar01_y1);

   /* Draw bar 12:							*/
   XSetLineAttributes(SI_display,SI_gc,SI_bar12,
			LineSolid,CapButt,JoinMiter);
   XDrawLine(SI_display,SI_g1_window,SI_gc,
			SI_bar12_x0,SI_bar12_y0,
			SI_bar12_x1,SI_bar12_y1);

   /* Draw bar 234:							*/
   XSetLineAttributes(SI_display,SI_gc,SI_bar234,
			LineSolid,CapButt,JoinMiter);
   XDrawLine(SI_display,SI_g1_window,SI_gc,
			SI_bar234_x0,SI_bar234_y0,
			SI_bar234_x1,SI_bar234_y1);

   /* Draw bar 34:							*/
   XSetLineAttributes(SI_display,SI_gc,SI_bar34,
			LineSolid,CapButt,JoinMiter);
   XDrawLine(SI_display,SI_g1_window,SI_gc,
			SI_bar34_x0,SI_bar34_y0,
			SI_bar34_x1,SI_bar34_y1);

   /* Draw bar 345:							*/
   XSetLineAttributes(SI_display,SI_gc,SI_bar345,
			LineSolid,CapButt,JoinMiter);
   XDrawLine(SI_display,SI_g1_window,SI_gc,
			SI_bar345_x0,SI_bar345_y0,
			SI_bar345_x1,SI_bar345_y1);

   /* Draw bar 51:							*/
   XSetLineAttributes(SI_display,SI_gc,SI_bar51,
			LineSolid,CapButt,JoinMiter);
   XDrawLine(SI_display,SI_toplevel,SI_gc,
			SI_bar51_x0,SI_bar51_y0,
			SI_bar51_x1,SI_bar51_y1);

   /* Draw bar dscb:							*/
   XSetLineAttributes(SI_display,SI_gc,SI_bardscb,
			LineSolid,CapButt,JoinMiter);
   XDrawLine(SI_display,SI_toplevel,SI_gc,
			SI_bardscb_x0,SI_bardscb_y0,
			SI_bardscb_x1,SI_bardscb_y1);

   /* Draw bar 32:							*/
   XSetLineAttributes(SI_display,SI_gc,SI_bar32,
			LineSolid,CapButt,JoinMiter);
   XDrawLine(SI_display,SI_toplevel,SI_gc,
			SI_bar32_x0,SI_bar32_y0,
			SI_bar32_x1,SI_bar32_y1);
}


/*-----------------------------------------------------------------------
   SI_draw_text:

   Draw the given name of a DS or CB.
------------------------------------------------------------------------*/
void SI_draw_text(square,txt_offset)
DS			*square;
int			txt_offset;
{  int			dlen;
   CB			*ptr;

   switch (square->type)
   {  case SI_TDS1:
      case SI_TDS2:
      case SI_TDS3:
      case SI_TDS4:
      case SI_TDS5:
	 XClearWindow(SI_display,square->attr.dsw1);
   	 dlen = strlen(square->name);
   	 XSetFont(SI_display,SI_gc,SI_font1);
   	 XDrawString(SI_display,square->attr.dsw1,SI_gc,
		     square->center,txt_offset,square->name,dlen);
	 break;

      case SI_TCB1:
      case SI_TCB2:
      case SI_TCB3:
	 ptr = (CB *)square;
	 XClearWindow(SI_display,ptr->attr.cbw);
   	 dlen = strlen(ptr->name);
   	 XSetFont(SI_display,SI_gc,SI_font2);
   	 XDrawImageString(SI_display,ptr->attr.cbw,SI_gc,
		     ptr->center,txt_offset,ptr->name,dlen);
	 break;
   };
   
}


/*-----------------------------------------------------------------------
   SI_change_state:

   Change the DS and CB on the window according to the new state.
------------------------------------------------------------------------*/
void SI_change_state(square)
DS		*square;
{  CB		*ptr;
   int		txt_offset;

   switch (square->type)
   {  case SI_TDS5:
	 if (square->attr.state==SI_SINACTIVE)
	    {  XSetWindowBackgroundPixmap(SI_display,square->attr.dsw1,
				SI_bgrd5);
	       SI_draw_text(square,SI_ds5_txt_offset);
	    }
	 else
	    {  XSetWindowBackgroundPixmap(SI_display,square->attr.dsw1,
				SI_bgrd3);
	       SI_draw_text(square,SI_ds5_txt_offset);
	       XSetLineAttributes(SI_display,SI_gc,SI_WCB1,LineSolid,CapButt,
			       JoinMiter);
	       XDrawRectangle(SI_display,square->attr.dsw1,SI_gc,
				SI_WCB1,SI_WCB1,
				SI_ds5_width-2*SI_WCB1,
				SI_ds5_height-2*SI_WCB1);
	    };
	 break;

      /* For command buttons:						*/
      case SI_TCB1:
	 txt_offset = SI_cb1_txt_offset;
      case SI_TCB2:
	 txt_offset = SI_cb2_txt_offset;
      case SI_TCB3:
	 txt_offset = SI_cb3_txt_offset;

	 ptr = (CB *)square;
	 if (ptr->attr.state==SI_SACTIVE)
	    {  XSetWindowBackgroundPixmap(SI_display,ptr->attr.cbw,
				SI_bgrd3);
	       XSetWindowBorderPixmap(SI_display,ptr->attr.cbw,SI_bgrd1);
   	       XDefineCursor(SI_display,ptr->attr.cbw,SI_CB_cursor);
	       SI_draw_text(ptr,txt_offset);
	    }
	 else
	    {  XSetWindowBackgroundPixmap(SI_display,ptr->attr.cbw,
				SI_bgrd2);
	       XSetWindowBorderPixmap(SI_display,ptr->attr.cbw,SI_bgrd3);
   	       XDefineCursor(SI_display,ptr->attr.cbw,SI_cursor);
	       SI_draw_text(ptr,txt_offset);
	    };
	 break;
   };
}


/*-----------------------------------------------------------------------
   SI_draw_name:

   This routine draws the names of the DS and CB.
------------------------------------------------------------------------*/
void SI_draw_name()
{  int			i,j;

   /* Draw region DS1:							*/
   for (i=0; i<40; i++)
      if (SI_window.DS1[i].defined)
	 SI_draw_text(&SI_window.DS1[i],SI_ds1_txt_offset);

   /* Draw region DS2:							*/
   for (i=0; i<16; i++)
      if (SI_window.DS2[i].defined)
	 SI_draw_text(&SI_window.DS2[i],SI_ds2_txt_offset);

   /* Draw region DS3:							*/
   for (i=0; i<4; i++)
      if (SI_window.DS3[i].defined)
	 SI_draw_text(&SI_window.DS3[i],SI_ds3_txt_offset);

   /* Draw region DS4:							*/
   for (i=0; i<4; i++)
      if (SI_window.DS4[i].defined)
	 SI_draw_text(&SI_window.DS4[i],SI_ds4_txt_offset);

   /* Draw region DS5:							*/
   for (i=0; i<8; i++)
      if (SI_window.DS5[i].defined)
	 SI_change_state(&SI_window.DS5[i]);


   /* Draw region CB1:							*/
   for (i=0; i<16; i++)
      if (SI_window.CB1[i].defined)
	 SI_change_state(&SI_window.CB1[i]);

   /* Draw region CB2:							*/
   for (i=0; i<4; i++)
      if (SI_window.CB2[i].defined)
	 SI_change_state(&SI_window.CB2[i]);

   /* Draw region CB3:							*/
   for (i=0; i<4; i++)
      if (SI_window.CB3[i].defined)
	 SI_change_state(&SI_window.CB3[i]);
}


/*-----------------------------------------------------------------------
   SI_number2str:

   Convert a number to a string with a given base.
------------------------------------------------------------------------*/
void SI_number2str(intvalue,base,str,slen)
unsigned int		intvalue;
int			base,
			slen;
char			*str;
{  int			i;
   char			digit;

	 str[slen] = '\0';
	 for (i=0; i<slen; i++)
	 {  digit = intvalue - (intvalue/base)*base;
	    if (base==16 && digit>9)
	       digit = digit - 10 + 'a';
	    else
	       digit = digit + '0';
	    str[slen-1-i] = digit;
	    intvalue = intvalue/base;
	 };
}


/*-----------------------------------------------------------------------
   SI_convert:

   Convert the binary value to string in the specified format.
   If the value is a string, just copy it to the new string area.
------------------------------------------------------------------------*/
void SI_convert(square,str)
DS		*square;
char		*str;
{  unsigned long	intvalue;
   char			digit;
   char			*src;
   int			slen;
   int			i,
			base;

   switch (square->format)
   {  case SI_FHEX:
	 base = 16;
	 break;
      case SI_FDEC:
	 base = 10;
	 break;
      case SI_FOCT:
	 base = 8;
	 break;
      case SI_FBIN:
	 base = 2;
	 break;
   };


   slen = square->vlen;
   switch (square->format)
   {  case SI_FHEX:
      case SI_FDEC:
      case SI_FOCT:
      case SI_FBIN:
	 intvalue = *(square->addr_value);
         SI_number2str(intvalue,base,str,slen);
	 break;

      case SI_FCHR:
	 src = (char *)square->addr_value;
	 for (i=0; i<slen && src[i]!='\0'; i++)
	    str[i] = src[i];
	 str[i] = '\0';
	 break;
   };
}


/*-----------------------------------------------------------------------
   SI_print_DS_value:

   Print the value of DS on the SI window.
------------------------------------------------------------------------*/
void SI_print_DS_value(square,width,txt_offset)
DS		*square;
int		width,
		txt_offset;
{  int		dlen,
      		center,
		txt_width;
   char		prtstr[MAXN_LEN+1];


   /* Clear value window and set up font:				*/
   XSetFont(SI_display,SI_gc,SI_font3);

   /* Convert value to string:						*/
   SI_convert(square,prtstr);

   /* Calc the starting x position for text centering:			*/
   dlen = strlen(prtstr);
   txt_width = XTextWidth(SI_font3_struct,prtstr,dlen);
   center = (width - txt_width)/2;
   XDrawImageString(SI_display,square->attr.dsw2,SI_gc,
	    			   center,txt_offset,prtstr,dlen);
}


/*-----------------------------------------------------------------------
   SI_same_as_old:

   Check if the current value is the same as the old value.
   If the window is being redrawn due to an expose event, force the
   new value assignment and return false.
------------------------------------------------------------------------*/
int SI_same_as_old(square)
DS			*square;
{  unsigned int		*ptr,
			oldvalue,
			newvalue;
   char			*oldstr,
			*newstr;
   int			i;


   switch (square->format)
   {  case SI_FHEX:
      case SI_FDEC:
      case SI_FOCT:
      case SI_FBIN:
	 ptr = (unsigned int *)square->oldval;
	 oldvalue = *ptr;
	 newvalue = *((unsigned int *)square->addr_value);
	 if (oldvalue==newvalue && !SI_expose_event)
	    return (true);
	 else
	 {  *(ptr) = newvalue;
	    return (false);
	 };
	 break;

      case SI_FCHR:
	 newstr = (char *)square->addr_value;
	 oldstr = square->oldval;
	 for (i=0; oldstr[i]==newstr[i] && oldstr[i]!='\0'; i++);

	 if (oldstr[i]==newstr[i] && !SI_expose_event)
	    return (true);
	 else
	 {  for (i=0; newstr[i]!='\0'; i++)
	       oldstr[i] = newstr[i];
	    oldstr[i] = '\0';
	    return (false);
	 };
	 break;
   };
}


/*-----------------------------------------------------------------------
   SI_update_window:

   Update the DS values on the SI window.  
   To save processing time, SI only 'really' updates the values that
   have been changed.

   The user should call this routine every time the SI window needs
   updating.

   This routine also generate a trace dump if the trace dump is on.
------------------------------------------------------------------------*/
void SI_update_window(dump)
int			dump;		/* 1==dump to file		*/
{  int			i,j,ii;
   void			SI_do_dump();


   /* Update DS1 region:						*/
   for (i=0; i<5; i++)
      for (j=0; j<8; j++)
      {  ii = i*8 + j;
	 if (SI_window.DS1[ii].defined)
	    if (!SI_same_as_old(&SI_window.DS1[ii]))
	       SI_print_DS_value(&SI_window.DS1[ii],
				SI_ds1_width,SI_ds1_txt_offset);
      };

   /* Update DS2 region:						*/
   for (i=0; i<16; i++)
      if (SI_window.DS2[i].defined)
	 if (!SI_same_as_old(&SI_window.DS2[i]))
	    SI_print_DS_value(&SI_window.DS2[i],
				SI_ds2_width,SI_ds2_txt_offset);

   /* Update DS3 region:						*/
   for (i=0; i<4; i++)
      if (SI_window.DS3[i].defined)
	 if (!SI_same_as_old(&SI_window.DS3[i]))
	    SI_print_DS_value(&SI_window.DS3[i],
				SI_ds3_width,SI_ds3_txt_offset);

   /* Update DS4 region:						*/
   for (i=0; i<4; i++)
      if (SI_window.DS4[i].defined)
	 if (!SI_same_as_old(&SI_window.DS4[i]))
	    SI_print_DS_value(&SI_window.DS4[i],
				SI_ds4_width,SI_ds4_txt_offset);

   /* If trace dump is on, dump the current DS values into file:	*/
   if (SI_TraceDumpOn && dump)
      SI_do_dump();
}


/*-----------------------------------------------------------------------
   SI_draw_window:

   Draw the entire SI window.  This includes the defined DS and CB.
------------------------------------------------------------------------*/
void SI_draw_window()
{

   SI_draw_regions();
   SI_draw_name();
   SI_update_window(0);
}


/*-----------------------------------------------------------------------
   SI_edit_DS_expose:
------------------------------------------------------------------------*/
void SI_edit_DS_expose()
{

	if (SI_event.xexpose.count==0 && 
	    (SI_event.xexpose.window==SI_toplevel ||
	     SI_event.xexpose.window==SI_g1_window))
	{  SI_expose_event = true;
	   SI_draw_window();
	   SI_expose_event = false;
	};
   
}


/*-----------------------------------------------------------------------
   SI_edit_DS:

   Edit the value of a selected DS.
------------------------------------------------------------------------*/
void SI_edit_DS(square)
DS			*square;
{  int			slen,width,txt_offset;
   int			base;
   unsigned int		intvalue;
   char			str[MAXB_LEN+1];
   char			*src;
   int			esc;
   int                  same;                   /* dummy                */


   slen = square->vlen;

   switch (square->format)
   {  case SI_FHEX:
	 base = 16;
	 break;
      case SI_FDEC:
	 base = 10;
	 break;
      case SI_FOCT:
	 base = 8;
	 break;
      case SI_FBIN:
	 base = 2;
	 break;
   };

   switch (square->type)
   {  case SI_TDS1:
	 width = SI_ds1_width;
	 txt_offset = SI_ds1_txt_offset;
	 break;
      case SI_TDS2:
	 width = SI_ds2_width;
	 txt_offset = SI_ds2_txt_offset;
	 break;
      case SI_TDS3:
	 width = SI_ds3_width;
	 txt_offset = SI_ds3_txt_offset;
	 break;
      case SI_TDS4:
	 width = SI_ds4_width;
	 txt_offset = SI_ds4_txt_offset;
	 break;
   };

   switch (square->format)
   {  case SI_FHEX:
      case SI_FDEC:
      case SI_FOCT:
      case SI_FBIN:
	 intvalue = *(square->addr_value);
         SI_number2str(intvalue,base,str,slen);
	 esc = SI_edit_string(square->attr.dsw2,width,txt_offset,
			SI_font3_struct,
			SI_bgrd3,str,slen,0,square->addr_value,base,
			SI_edit_DS_expose,false);
         same = SI_same_as_old(square);         /* Update oldval[]      */
	 SI_print_DS_value(square,width,txt_offset);
	 break;

      case SI_FCHR:
	 src = (char *)square->addr_value;
	 esc = SI_edit_string(square->attr.dsw2,width,txt_offset,
			SI_font3_struct,
			SI_bgrd3,src,slen,1,square->addr_value,base,
			SI_edit_DS_expose,false);
         same = SI_same_as_old(square);         /* Update oldval[]      */
	 SI_print_DS_value(square,width,txt_offset);
	 break;
   };
}


/*-----------------------------------------------------------------------
   SI_do_change_DS:

   Change the value of a DS.
   Check for button pressed on one of the DS and allow the user to alter
   the content.

   If button pressed in one of the DS, function returns true.
------------------------------------------------------------------------*/
int SI_do_change_DS()
{  int			i,j,ii;
   Window		child;

   
   child = SI_event.xbutton.window;

   /* Scan thru all the DS for the one:					*/
   /* For DS1 region:							*/
   for (i=0; i<5; i++)
      for (j=0; j<8; j++)
      {  ii = i*8 + j;
	 if (SI_window.DS1[ii].defined && 
	    			 child==SI_window.DS1[ii].attr.dsw2)
	 {  SI_edit_DS(&SI_window.DS1[ii]);
	    return(true);
	 };
      };

   /* For DS2 region:							*/
   for (i=0; i<16; i++)
	 if (SI_window.DS2[i].defined && 
	    			 child==SI_window.DS2[i].attr.dsw2)
	 {  SI_edit_DS(&SI_window.DS2[i]);
	    return(true);
	 };

   /* For DS3 region:							*/
   for (i=0; i<4; i++)
	 if (SI_window.DS3[i].defined && 
	    			 child==SI_window.DS3[i].attr.dsw2)
	 {  SI_edit_DS(&SI_window.DS3[i]);
	    return(true);
	 };

   /* For DS4 region:							*/
   for (i=0; i<4; i++)
	 if (SI_window.DS4[i].defined && 
	    			 child==SI_window.DS4[i].attr.dsw2)
	 {  SI_edit_DS(&SI_window.DS4[i]);
	    return(true);
	 };

   return(false);
}


/*-----------------------------------------------------------------------
   SI_do_focus:

   Change the border of the CB if cursor enters or leaves.
------------------------------------------------------------------------*/
void SI_do_focus(enter)
int			enter;
{  Window		child;
   int			found;
   int			i;


   found = false;
   child = SI_event.xcrossing.window;

   /* Scan thru. all CB for the one:					*/
   /* Search CB1:							*/
   for (i=0; i<16 && !found; i++)
      if (SI_window.CB1[i].defined &&
	  SI_window.CB1[i].attr.state==SI_SACTIVE)
         if (child==SI_window.CB1[i].attr.cbw)
	 {  found = true;
	    if (enter)
	    {  XSetWindowBackgroundPixmap(SI_display,child,SI_bgrd4);
	       SI_draw_text(&SI_window.CB1[i],SI_cb1_txt_offset);
	    }
	    else
	    {  XSetWindowBackgroundPixmap(SI_display,child,SI_bgrd3);
	       SI_draw_text(&SI_window.CB1[i],SI_cb1_txt_offset);
	    };
	 };

   /* Search CB2:							*/
   for (i=0; i<4 && !found; i++)
      if (SI_window.CB2[i].defined &&
	  SI_window.CB2[i].attr.state==SI_SACTIVE)
         if (child==SI_window.CB2[i].attr.cbw)
	 {  found = true;
	    if (enter)
	    {  XSetWindowBackgroundPixmap(SI_display,child,SI_bgrd4);
	       SI_draw_text(&SI_window.CB2[i],SI_cb2_txt_offset);
	    }
	    else
	    {  XSetWindowBackgroundPixmap(SI_display,child,SI_bgrd3);
	       SI_draw_text(&SI_window.CB2[i],SI_cb2_txt_offset);
	    };
	 };

   /* Search CB3:							*/
   for (i=0; i<4 && !found; i++)
      if (SI_window.CB3[i].defined && 
	  SI_window.CB3[i].attr.state==SI_SACTIVE)
  	 if (child==SI_window.CB3[i].attr.cbw)
  	 {  found = true;
	    if (enter)
	    {  XSetWindowBackgroundPixmap(SI_display,child,SI_bgrd4);
	       SI_draw_text(&SI_window.CB3[i],SI_cb3_txt_offset);
	    }
	    else
	    {  XSetWindowBackgroundPixmap(SI_display,child,SI_bgrd3);
	       SI_draw_text(&SI_window.CB3[i],SI_cb3_txt_offset);
	    };
	 }
}


/*-----------------------------------------------------------------------
   SI_do_button:

   Check if one of the command button has been 'pressed.'
   If so, return the corresponding token for the CB.  The tokens for CB1
   range from 0 to 15 (row major order) and the tokens for CB2 range
   from 16 to 19 (top to bottom).

   If none of the CB were pressed, return -1;
------------------------------------------------------------------------*/
int SI_do_button()
{  int			i;
   Window		child;


   child = SI_event.xbutton.window;
   /* Scan thru. all CB for the one:					*/
   /* Search CB1:							*/
   for (i=0; i<16; i++)
      if (SI_window.CB1[i].defined)
         if (child==SI_window.CB1[i].attr.cbw)
	    if (SI_window.CB1[i].attr.state==SI_SACTIVE)
	       return (i);
	    else
	       return (-1);

   /* Search CB2:							*/
   for (i=0; i<4; i++)
      if (SI_window.CB2[i].defined)
         if (child==SI_window.CB2[i].attr.cbw)
	    if (SI_window.CB2[i].attr.state==SI_SACTIVE)
	       return (16 + i);
	    else
	       return (-1);

   /* CB3 are reserved for SI internal functions.  Thus they are not
      processed here.							*/
   return (-1);
}
   

/*-----------------------------------------------------------------------
   SI_bin2str:

   Convert a binary number to a binary string.
   This routine only converts the least significant 10 bits.
------------------------------------------------------------------------*/
void SI_bin2str(value,str)
int		value;
char		*str;
{  int		bit;

   for (bit=0; bit<10; bit++)
   {  if ((value&1)==1)
         str[9-bit] = '1';
      else
         str[9-bit] = '0';
      value = value >> 1;
   };
   str[10] = '\0';
}

   
/*-----------------------------------------------------------------------
   SI_dump_space:

   Dump space to trace dump file.  The number of spaces equals the vlen
   field of the DS.
------------------------------------------------------------------------*/
void SI_dump_space(square)
DS			*square;
{  int			i;

   for (i=0; i<(square->vlen)+1; i++)
      fprintf(SI_TD_ofp," ");
}


/*-----------------------------------------------------------------------
   SI_dump_DS:

   Dump value of DS onto trace dump file.
------------------------------------------------------------------------*/
void SI_dump_DS(square)
DS		*square;
{  char			prtstr[MAXN_LEN+1];

   SI_convert(square,prtstr);
   fprintf(SI_TD_ofp,"%s ",prtstr);
}


/*-----------------------------------------------------------------------
   SI_dump_DS_mask:

   Print the DS mask to the trace dump file.
------------------------------------------------------------------------*/
void SI_dump_DS_mask()
{  int			i,j;


   /* Write the DS mask to the trace dump file:			*/
   /* Mask for the DS1 region:					*/
   for (i=0; i<5; i++)
   {  for (j=0; j<8; j++)
         if (SI_window.DS1[i*8+j].defined)
	    fprintf(SI_TD_ofp,"% 10s ",SI_window.DS1[i*8+j].name);
	 else
	    SI_dump_space(&SI_window.DS1[i*8+j]);
      fprintf(SI_TD_ofp,"\n");
   };

   /* Mask for the DS2 region:					*/
   for (i=0; i<16; i++)
      if (SI_window.DS2[i].defined)
	 fprintf(SI_TD_ofp,"% 3s ",SI_window.DS2[i].name);
      else
	 SI_dump_space(&SI_window.DS2[i]);
   fprintf(SI_TD_ofp,"\n");

   /* Mask for the DS3 region:					*/
   for (i=0; i<4; i++)
      if (SI_window.DS3[i].defined)
	 fprintf(SI_TD_ofp,"% 10s ",SI_window.DS3[i].name);
      else
	 SI_dump_space(&SI_window.DS3[i]);
   fprintf(SI_TD_ofp,"\n");

   /* Mask for the DS4 region:					*/
   for (i=0; i<4; i++)
      if (SI_window.DS4[i].defined)
	 fprintf(SI_TD_ofp,"% 10s ",SI_window.DS4[i].name);
      else
	 SI_dump_space(&SI_window.DS4[i]);
   fprintf(SI_TD_ofp,"\n");

   /* Print the instance separator:					*/
   fprintf(SI_TD_ofp,"-------------------------------------------------------------------------------\n");
}


/*-----------------------------------------------------------------------
   SI_do_dump:

   Dump the current content of the SI window onto the trace dump file.
   The start of the trace dump file contains the DS mask.
   The trace dump file is divided into instances separated by a line.
   Each time the user calls SI to update the SI window, an instance is
   produced.
   An instance is also produced when TakeSnapShot is pressed.
   An instance contains values of DS that correspond to the DS mask at
   the beginning of the trace dump file.
------------------------------------------------------------------------*/
void SI_do_dump()
{  int			i,j;


   /* Dump the DS1 region:						*/
   for (i=0; i<5; i++)
   {  for (j=0; j<8; j++)
         if (SI_window.DS1[i*8+j].defined)
	    SI_dump_DS(&SI_window.DS1[i*8+j]);
	 else
	    SI_dump_space(&SI_window.DS1[i*8+j]);
      fprintf(SI_TD_ofp,"\n");
   };

   /* Dump the DS2 region:						*/
   for (i=0; i<16; i++)
      if (SI_window.DS2[i].defined)
         SI_dump_DS(&SI_window.DS2[i]);
      else
	 SI_dump_space(&SI_window.DS2[i]);
   fprintf(SI_TD_ofp,"\n");

   /* Dump the DS3 region:						*/
   for (i=0; i<4; i++)
      if (SI_window.DS3[i].defined)
         SI_dump_DS(&SI_window.DS3[i]);
      else
	 SI_dump_space(&SI_window.DS3[i]);
   fprintf(SI_TD_ofp,"\n");

   /* Dump the DS4 region:						*/
   for (i=0; i<4; i++)
      if (SI_window.DS4[i].defined)
         SI_dump_DS(&SI_window.DS4[i]);
      else
	 SI_dump_space(&SI_window.DS4[i]);
   fprintf(SI_TD_ofp,"\n");

   /* Print the instance separator:					*/
   fprintf(SI_TD_ofp,"-------------------------------------------------------------------------------\n");
}


/*-----------------------------------------------------------------------
   SI_do_startTD:
------------------------------------------------------------------------*/
void SI_do_startTD()
{

   /* Do nothing if trace dump flag is on:				*/
   if (SI_TraceDumpOn)
      /* Do nothing 							*/
      ;
      
   /* Open dump file and make CB inactive:				*/
   else
   {  SI_TraceDumpOn = true;
      SI_TD_ofp = fopen(SI_DUMP_FNAME,"a");
      SI_window.CB3[0].attr.state = SI_SINACTIVE;
      SI_window.CB3[1].attr.state = SI_SACTIVE;
      SI_dump_DS_mask();
      SI_change_state(&SI_window.CB3[0]);
      SI_change_state(&SI_window.CB3[1]);
      SI_toggle_state_DS5(7);
   };
}


/*-----------------------------------------------------------------------
   SI_do_stopTD():
------------------------------------------------------------------------*/
void SI_do_stopTD()
{

   /* If trace dump file is opened, close it and make CB inactive:	*/
   if (SI_TraceDumpOn)
   {  SI_TraceDumpOn = false;
      fclose(SI_TD_ofp);
      SI_window.CB3[1].attr.state = SI_SINACTIVE;
      SI_window.CB3[0].attr.state = SI_SACTIVE;
      SI_change_state(&SI_window.CB3[1]);
      SI_change_state(&SI_window.CB3[0]);
      SI_toggle_state_DS5(7);
   } 

   /* Do nothing if file is already closed:				*/
   else
      /* Do nothing							*/
      ;	
}


/*-----------------------------------------------------------------------
   SI_do_snapshot:

   Dump the current content of SI window into the trace dump file.
------------------------------------------------------------------------*/
void SI_do_snapshot()
{

   /* Open trace dump file if it is not already opened:			*/
   if (!SI_TraceDumpOn)
      SI_TD_ofp = fopen(SI_DUMP_FNAME,"a");

   /* Dump current content of SI window into trace dump file:		*/
   SI_dump_DS_mask();
   SI_do_dump();

   /* If trace file was previously not opened, close the file:		*/
   if (!SI_TraceDumpOn)
      fclose(SI_TD_ofp);
}
      

/*-----------------------------------------------------------------------
   SI_do_purgeTD:

   Clear the trace dump file.  This action will throw away the current
   content of the trace dump file.
------------------------------------------------------------------------*/
void SI_do_purgeTD()
{

   /* If trace dump file is currently opened, close it:			*/
   if (SI_TraceDumpOn)
      fclose(SI_TD_ofp);

   /* Open file for write (new file):					*/
   SI_TD_ofp = fopen(SI_DUMP_FNAME,"w");

   /* If trace dump file was previously closed, close the file:		*/
   if (!SI_TraceDumpOn)
      fclose(SI_TD_ofp);
}


/*-----------------------------------------------------------------------
   SI_event_process:

   Do the SI event loop and return the command button token if any.
   In the user's event loop, this routine MUST be called at every pass.
------------------------------------------------------------------------*/
int SI_event_process()
{  int			done;
   int			nevent;

   
   /* SI event loop:							*/
   done = false;
   SI_CB_token = -1;

   while (!done) 
   {  /* If there are no event in the queue, set up a 'fake' event:	*/
      nevent = XEventsQueued(SI_display,QueuedAfterFlush);
      if (nevent==0)
	 SI_event.type = ColormapNotify;
      else
         XNextEvent(SI_display,&SI_event);

      switch(SI_event.type)
      {  case Expose:
		if (SI_event.xexpose.count==0)
		{  if (SI_event.xexpose.window==SI_toplevel ||
		       SI_event.xexpose.window==SI_g1_window)
		   {  SI_expose_event = true;
		      SI_draw_window();
		      SI_expose_event = false;
		   }
		   else if (SI_event.xexpose.window==SI_mw_toplevel)
		   {  if (SI_mw_mapped)
		      {  SI_mem_draw_com(false,true,true,true,true,false,
							false,true);
		         SI_mem_display(true);
		      };
		   };
		};
		break;

	 case MappingNotify:
		XRefreshKeyboardMapping(&SI_event);
		break;

	 case ButtonPress:

	     /* StartTraceDump button pressed:				*/
	     if (SI_event.xbutton.window==SI_window.CB3[0].attr.cbw &&
		 SI_window.CB3[0].attr.state==SI_SACTIVE)
		SI_do_startTD();

	     /* StopTraceDump button pressed:				*/
	     else if (SI_event.xbutton.window==SI_window.CB3[1].attr.cbw &&
		      SI_window.CB3[1].attr.state==SI_SACTIVE)
		SI_do_stopTD();

	     /* TakeSnapShot button pressed:				*/
	     else if (SI_event.xbutton.window==SI_window.CB3[2].attr.cbw)
		SI_do_snapshot();

	     /* PurgeTraceDump button pressed:				*/
	     else if (SI_event.xbutton.window==SI_window.CB3[3].attr.cbw)
		SI_do_purgeTD();

	     /* Must be the CB1 or the CB2:				*/
	     else
	     {
	        /* Check for CB:					*/
		SI_CB_token = SI_do_button();

	        /* If not one of the CB, check for DS:			*/
		if (SI_CB_token==-1)

		   /* If not one of the DS, do memory window:		*/
		   if (!SI_do_change_DS());
		      SI_mem_dm_dynamic();
		done = true;
	     };
	     break;

	 case EnterNotify:
		SI_do_focus(1);
		break;

	 case LeaveNotify:
		SI_do_focus(0);
		done = true;
		break;

	 default:
		done = true;
		break;
      };
   };
   return (SI_CB_token);
}


/*-----------------------------------------------------------------------
   SI_init:

   Set up the SI window.  This routine is only needed to be called once.
   Function returns false if error was encountered.
------------------------------------------------------------------------*/
int SI_init()
{  int			done;
   FILE                 *ofp;

   /* Foremost init:							*/
   SI_TraceDumpOn = false;

   /* Try to open the trace dump file:                                  */
   ofp = fopen(SI_DUMP_FNAME,"a");
   if (ofp==NULL)
      return (false);
   else
      fclose(ofp);


   /* Init the DS and CB:						*/
   if (!SI_read_data())
      return (false);

   /* Read in the fonts:						*/
   if (!SI_read_font())
      return (false);

   /* Calc. the mask SI window:						*/
   SI_calc_mask();

   /* Create the SI window based on the mask established by DS and CB:	*/
   SI_create_window();

   /* Map the user's variables to DS:					*/
   SI_map_address();

   return (true);
}

