#ifndef lint
static char *rcs="*** $Header: /mit/hst/src/main/RCS/Interface.c,v 2.6 90/08/28 17:05:52 tldavis Exp Locker: tldavis $";
#endif
/* 
 * Interface.c: Copyright 1990, Timothy L. Davis
 *
 * $Source: /mit/hst/src/main/RCS/Interface.c,v $
 * $Log:	Interface.c,v $
 *
 * This version revised 98/02/12 by G.B.Moody (1) to remove need for crypt
 *  (not available under Linux) and (2) to work around a bug in XtMalloc
 *
 * Revision 2.6  90/08/28  17:05:52  tldavis
 * minor bugs
 * 
 * Revision 2.5  90/08/28  15:57:09  tldavis
 * Removed need for IntrinsicP.h (to help lint).
 * 
 * Revision 2.4  90/08/28  14:51:27  tldavis
 * linted.
 * 
 * Revision 2.3  90/08/18  18:45:53  tldavis
 * Fixed sundry interface bugs, fixed up for resource file usage.
 * 
 */
#include <X11/Intrinsic.h> 
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Composite.h>
#include <X11/cursorfont.h>
#include "../sim/CVDefs.h"
#include "../plot/Plot.h"
#include "../form/PlotForm.h"
#include "../nl/NumberLine.h"
#include "../circuit/Circuit.h"
#include "../data/Parameter.h"
#include "../event/Event.h"
#include <stdio.h>
#ifdef SVR4
#include <string.h>
#else
#include <strings.h>
#endif
#include <signal.h>
#include <fcntl.h>

extern double  getval(); /* from eqns.c */
extern SIMULATION *presentsim(); /* from eqns.c */
extern char *CVLib; /* Main.c defines location of files */
extern void ReflexesOff(); /* from ../sim/reflex.c */
extern Boolean reflexesOn;
extern char *getenv();

extern Display *dpy;
extern Window root;
extern int screen;


/* Private Definitions. */

int patientActive = 0;
typedef struct {
    Widget buttonBox;
    Widget buttons[21];
    Widget patients;
    int simulating;
    int patientActive;
    int administrator;
} CVDataRec, *CVData;

/*FORWARD*/
static void Help(),  SimToggleOnOff(), SimParams(), NewPlot(), DeletePlot(), 
     PrintPlot(), Quit(), Patients(), ResetButton();
void ReflexButton(); /* from ../sim/reflex.c */
void ShowParameters();

static char *Buttons[] = {
  "New Plot",  "Set Parameter", "Parameter List", "Stop (running)",  
  "Baroreflex", "Patients", "Print", "Delete",  
  "Reset",  "Quit",  "Help",  NULL,
};
/* We refer to some buttons by index number below, so here they are: */
#define LISTBUTTON 2
#define STOPBUTTON 3
#define REFLEXBUTTON 4

static void (*ButtonProc[])() = {
  NewPlot,  SimParams, ShowParameters,  SimToggleOnOff,    
  ReflexButton, Patients, PrintPlot,  DeletePlot,  
  ResetButton,  Quit, Help,
};

/*PUBLIC*/
Widget DialogCreate(parent, desc, val)
     Widget parent;
     char *desc;
     char *val;
{
  Widget shell, dialog;
  Arg a[5];
  int i = 0;

  shell = XtCreatePopupShell("Popup", overrideShellWidgetClass,
			     parent, (Arg *)0, 0);
  XtSetArg(a[i], XtNlabel, desc);i++;
  XtSetArg(a[i], XtNvalue, val);i++;
  dialog = XtCreateManagedWidget("Dialog", dialogWidgetClass, shell, a, i);
  return dialog;
}
     
/*PUBLIC*/
void PlaceDialog(w, parent)
     Widget w, parent;
{
  int x, y;
  Window child;
  XEvent ev;
  Dimension width, height;
  Arg args[2];
  int i;

  XTranslateCoordinates(dpy, XtWindow(parent), root, 0, 0, &x, &y, &child);
  XtRealizeWidget(XtParent(w)); /* To get the widget's width/height set */
  i=0;
  XtSetArg(args[i], XtNwidth, &width);i++;
  XtSetArg(args[i], XtNheight, &height);i++;
  XtGetValues(w, args, i);
  if (x < 0) x = 0;
  if (x + width > XDisplayWidth(dpy, screen)) 
    x = XDisplayWidth(dpy, screen) - width;
  if (y < 0) y = 0;
  if (y + height > XDisplayHeight(dpy, screen)) 
    y = XDisplayHeight(dpy, screen) - height;
  XtMoveWidget(XtParent(w), x, y);
  XtPopup(XtParent(w), XtGrabNone);
  while (XCheckWindowEvent(dpy, XtWindow(parent), ButtonPressMask, &ev)) ;
}

static Widget UserSelectWidget()
{
  XEvent ev;
  XButtonEvent *bptr = (XButtonEvent *) &ev;
  Widget widget;
  static Cursor cursor = (Cursor)NULL;
  if (!cursor) cursor = XCreateFontCursor(dpy,XC_cross);
  if (XGrabPointer(dpy, XDefaultRootWindow(dpy), True, 
		   ButtonPressMask|ButtonReleaseMask,
		   GrabModeAsync, GrabModeAsync, None, 
		   cursor, CurrentTime) == GrabSuccess) {
    XMaskEvent(dpy, (unsigned long) ButtonPressMask, &ev);
    XMaskEvent(dpy, (unsigned long) ButtonReleaseMask, &ev);
    XUngrabPointer(dpy, CurrentTime);
    /* find the shell widget that is an ancestor of this window */
    widget = XtWindowToWidget(dpy, bptr->window);
    if (widget) 
      while (!XtIsSubclass(widget, shellWidgetClass))
	widget = XtParent(widget); /* every non-shell widget has a parent */
    return widget;
  } else return (Widget)0;
}

/* these 2 publics are kludges to update ShowParam (KLUDGED to EVENT.C)*/
Widget paramWidget = NULL;
caddr_t paramWinData = NULL;

/*ARGSUSED*/
static void NumberLineCallback(w, client, call)
Widget w;
caddr_t client, call;
{
  double present;
  int place, type, done;

  NumberLineGetValue(w, &present, &done);
  place = ((int)client) / 100;
  type =  ((int)client) - place*100;

#ifdef DEBUG
  printf("Number Line Callback: present = %lf\n", present);
#endif
   if (done && w) { 
    XtUnmapWidget(XtParent(w));
    NumberLineCancelType(XtParent(w));
    XtDestroyWidget(XtParent(w));
  } else
    SendToSim(place, type, present);
}

/*ARGSUSED*/
static void dummyHandler(w, client, event)
     Widget w; caddr_t client; XEvent *event;
{ ; /*nothing*/
}

static Widget CreateIndepWidget(name, class, shellRet, args, argCount)
     char *name;
     WidgetClass class;
     Widget *shellRet; /*RETURN*/
     ArgList args;
     int argCount;
{
  Widget w, shell;
  Arg largs[10];
  int i = 0;
  XtSetArg(largs[i], XtNallowShellResize, True);i++;
  XtSetArg(largs[i], XtNiconName, name);i++;
#ifdef XAW_BC
  shell = XtCreateApplicationShell(name,topLevelShellWidgetClass, largs, i);
#else /* ! XAW_BC */
  shell = XtAppCreateShell(NULL,"CVsim",topLevelShellWidgetClass,dpy,largs,i);
#endif
  w     = XtCreateManagedWidget(name, class, shell, args, argCount);
  XtAddEventHandler(shell, ButtonPressMask | ButtonReleaseMask, False, 
		    dummyHandler, (caddr_t)0);
  XtRealizeWidget(shell);
  if (shellRet) *shellRet = shell;
  return(w);
}

/*ARGSUSED*//*PUBLIC*/
void KillDialog(w, client, call)
Widget w;
caddr_t client, call;
{
  XEvent ev;
  if (client) {
    XtUnmapWidget(XtParent((Widget) client));
    XtDestroyWidget(XtParent((Widget) client));
  }
  while (XCheckWindowEvent(dpy, XtWindow(w), ButtonPressMask, &ev)) ;
}

/*
 *
 * Button Action Function Definitions (private)
 *
 */

/*ARGSUSED*/
static void ClearSema(w, client, call)
Widget w;
caddr_t client, call;
{
  int *sema_ptr = (int *) client;
  (*sema_ptr)++;
}

/*ARGSUSED*/
static void Help(widget, client, call)
Widget widget;
caddr_t client, call;
{
  Widget shell;
  Arg args[10];
  int i = 0;
  char buf[256];

  if (CVLib) (void) sprintf(buf, "%s/help.txt", (char *) CVLib);
  else       (void) strcpy(buf, "/usr/local/lib/cvsim/help.txt");


#ifdef XAW_BC
  XtSetArg(args[i], XtNwidth, 700);i++;
  XtSetArg(args[i], XtNheight, 570);i++;
  XtSetArg(args[i], XtNsensitive, False);i++;
  shell = XtCreateApplicationShell("Help", topLevelShellWidgetClass,
				   (ArgList)0, 0);
  XtSetArg(args[i], XtNfile, buf);i++;
  XtSetArg(args[i], XtNiconName, "Help");i++;
  XtCreateManagedWidget("Help", asciiDiskWidgetClass, shell, args, i);
#else /* ! XAW_BC */
  XtSetArg(args[i], XtNiconName, "Help");i++;
  shell = XtAppCreateShell(NULL,"CVsim",topLevelShellWidgetClass,
			   dpy,args, i);

  XtSetArg (args[i], XtNtype, XawAsciiFile); i++;
  XtSetArg (args[i], XtNstring, buf); i++;
  XtSetArg(args[i], XtNwidth, 700);i++;
  XtSetArg(args[i], XtNheight, 570);i++;
  XtSetArg(args[i], XtNsensitive, False);i++;
  XtCreateManagedWidget("Help", asciiTextWidgetClass, shell, args, i);
#endif
  XtAddEventHandler(shell, ButtonPressMask | ButtonReleaseMask, False, 
		    dummyHandler, (caddr_t)0);
  XtRealizeWidget(shell);
  XSetIconName(dpy, XtWindow(shell), "Help with Cardiovascular Simulator");
}

/*should be static but event.c kludge*/
/*ARGSUSED*/
void ShowParameters(w, client, call)
Widget w;
caddr_t client, call;
{

  CVData data = (CVData) client;
  Arg args[10];
  int i = 0;
  SIMULATION *present, *normal, s;
  char *formatted = NULL;
  XEvent ev;
#ifndef XAW_BC
  XFontStruct *paramFont;
#endif

  if (data->patientActive) {
    if (paramWidget) {
      if (XtParent(paramWidget)) XtDestroyWidget(XtParent(paramWidget));
      else XtDestroyWidget(paramWidget);
      paramWidget = NULL;
    }
    return; /* Don't look at patient parameters */
  }
  present = presentsim(&s);
  normal = getsimulation(NORMAL);
  formatted = FormatParams(present, normal);
  i=0;
  XtSetArg(args[i],XtNstring, formatted);i++;
#ifdef XAW_BC
  XtSetArg(args[i],XtNeditType,XttextEdit);i++;
#else /* ! XAW_BC */
  XtSetArg(args[i],XtNeditType,XawtextEdit);i++;
  paramFont = XLoadQueryFont (dpy, "Fixed");
  XtSetArg(args[i], XtNfont, paramFont); i++;
#endif
  XtSetArg(args[i],XtNborderWidth, 2);i++;
  if (!paramWidget) {
    Widget shell;
#ifdef XAW_BC
    paramWidget = CreateIndepWidget("Parameters", asciiStringWidgetClass, 
				    &shell, args, i);
#else /* ! XAW_BC */
    paramWidget = CreateIndepWidget("Parameters", asciiTextWidgetClass, 
				    &shell, args, i);
#endif
    paramWinData = (caddr_t) data;
    XtResizeWidget(shell, 400, 250, 2);
  } else {
    Widget shell = XtParent(paramWidget);
    XtDestroyWidget(paramWidget);
#ifdef XAW_BC
    paramWidget = XtCreateManagedWidget("Parameters", asciiStringWidgetClass, 
					shell, args, i);
    replaceText(paramWidget, formatted);
#else /* ! XAW_BC */
    paramWidget = XtCreateManagedWidget("Parameters", asciiTextWidgetClass, 
					shell, args, i);
#endif
    paramWinData = (caddr_t) data;
  }
  if (w) while (XCheckWindowEvent(dpy, XtWindow(w), ButtonPressMask, &ev)) ;
}

#ifdef NOTDEFYET
char *FormatVariables(present)
SIMULATION *present;
{
  return("Not yet ready, sorry.\n");
}

static void Summary(widget, client, call)
Widget widget;
caddr_t client, call;
{

  static Widget varWidget = NULL;
  CVData data = (CVData) client;
  Arg args[10];
  int i = 0;
  SIMULATION *present, s;
  char *formatted = NULL;
  XEvent ev;
#ifndef XAW_BC
  XFontStruct *paramFont;
#endif

  present = presentsim(&s);
  formatted = FormatVariables(present);i++;
  i=0;
  XtSetArg(args[i],XtNstring, formatted);i++;
#ifdef XAW_BC
  XtSetArg(args[i],XtNeditType,XttextEdit);i++;
#else /* ! XAW_BC */
  XtSetArg(args[i],XtNeditType,XawtextEdit);i++;
  paramFont = XLoadQueryFont (dpy, "Fixed"); 
  XtSetArg (args[i], XtNfont, paramFont); i++;
#endif
  XtSetArg(args[i],XtNborderWidth, 2);i++;
  if (!varWidget) {
    Widget shell;
#ifdef XAW_BC
    varWidget = CreateIndepWidget("Parameters", asciiStringWidgetClass, 
				    &shell, args, i);
#else /* ! XAW_BC */
    varWidget = CreateIndepWidget("Parameters", asciiTextWidgetClass, 
				    &shell, args, i);
#endif
    XtResizeWidget(shell, 400, 250, 2); 
  } else {
    replaceText(varWidget, formatted);
  }
  if (widget) 
    while (XCheckWindowEvent(dpy, XtWindow(widget), ButtonPressMask, &ev)) ;

}
#endif

/*ARGSUSED*/
static void ExitProgram(w, client, call)
Widget w;
caddr_t client, call;
{
#ifdef DEBUG
  printf("Exiting.\n");
#endif
  printf("Thank you for using the Cardiovascular Simulator.  Bye!\n\n");
  exit((int) client); /* now let this process die with the given value */
}

/*ARGSUSED*/
static void Quit(widget, client, call)
Widget widget;
caddr_t client, call;
{
  Widget w, yes, no;
  static int modal_sema = 1;

  if (modal_sema) {
    modal_sema--;
    w = DialogCreate(widget, "Are you sure?", (char *)NULL);
    yes = XtCreateManagedWidget("Quit", commandWidgetClass, w,
				(Arg *)NULL, 0);
    XtAddCallback(yes, XtNcallback, ExitProgram, (caddr_t) 0);
    XtAddCallback(yes, XtNcallback, ClearSema,  (caddr_t) &modal_sema);
    no = XtCreateManagedWidget("Continue", commandWidgetClass, w,
			       (Arg *)NULL,0);
    XtAddCallback(no,  XtNcallback, KillDialog, (caddr_t) w);
    XtAddCallback(no,  XtNcallback, ClearSema,  (caddr_t) &modal_sema);
    PlaceDialog(w, widget);
  }
}

static Widget toggleDialogBox = NULL;
/*ARGSUSED*/
static void StartTrans(w, client, call)
Widget w;
caddr_t client, call;
{
  CVData data = (CVData) client;
  Arg args[2];
  XEvent ev;

  ResumeSimulator();
  XtSetArg(args[0], XtNlabel, "Stop (running)");
  XtSetValues(data->buttons[STOPBUTTON], args, 1);
  data->simulating = !data->simulating;
  KillDialog(toggleDialogBox,(caddr_t)toggleDialogBox, (caddr_t)NULL);
  toggleDialogBox = NULL;
  while (XCheckWindowEvent(dpy, XtWindow(w), ButtonPressMask, &ev)) ;
}  

/*ARGSUSED*/
static void StartSteady(w, client, call)
Widget w;
caddr_t client, call;
{
  CVData data = (CVData) client;
  Arg args[2];
  SIMULATION p;
  XEvent ev;

  ResetSimulator(presentsim(&p));
  XtSetArg(args[0], XtNlabel, "Stop (running)");
  XtSetValues(data->buttons[STOPBUTTON], args, 1);
  data->simulating = !data->simulating;
  KillDialog(toggleDialogBox,(caddr_t)toggleDialogBox, (caddr_t)NULL);
  toggleDialogBox = NULL;
  while (XCheckWindowEvent(dpy, XtWindow(w), ButtonPressMask, &ev)) ;
}  

/*ARGSUSED*/
static void SimToggleOnOff(widget, client, call)
Widget widget;
caddr_t client, call;
{
  CVData data = (CVData) client;
  XEvent ev;

  if (!toggleDialogBox) {
    if (data->simulating) {
      Arg args[1];
      StopSimulator();
      XtSetArg(args[0], XtNlabel, "Resume (stopped)");
      XtSetValues(data->buttons[STOPBUTTON], args, 1);
      data->simulating = !data->simulating;
    } else {
      Widget w, no, yes;

      w = DialogCreate(widget, "Reestablish Steady State?",(char *)NULL);
      toggleDialogBox = w;
      no = XtCreateManagedWidget("TRANSIENT", commandWidgetClass, w, 
				 (Arg *)NULL, 0);
      yes =XtCreateManagedWidget("STEADY STATE", commandWidgetClass, w, 
				 (Arg *)NULL, 0);
      if (reflexesOn)   {
	Arg args[2]; 
	XtSetArg(args[0], XtNsensitive, False);
	XtSetValues(yes, args, 1);
      }
      XtAddCallback(no, XtNcallback, StartTrans, (caddr_t)data);
      XtAddCallback(yes, XtNcallback, StartSteady, (caddr_t)data);
      PlaceDialog(w, widget);
    }
  }
  while (XCheckWindowEvent(dpy, XtWindow(widget), ButtonPressMask, &ev)) ;
}

/*ARGSUSED*/
static void SimParams(w, client, call)
Widget w;
caddr_t client, call;
{
  CVData data = (CVData) client;
  Widget widget, shell;
  Arg args[10];
  int i = 0, j = 0;
  int place, type;
  VarData *vd;
  double junk[9];
  double present;
  char buf[128];
  XEvent ev;
  Arg largs[10];

  modify_parameters(0, &place, &type);
  if (place < 0 || type < 0) return; /* No choice made, abort */
  vd = get_vardata(place, type);
  present = getval(junk, place, type); /* place, type for indep. var */
  
  if (!data->patientActive)
    (void) sprintf(buf, "%s (%s)", vd->name, vd->units);
  else
    (void) sprintf(buf, "%s (%% of original)", vd->name, vd->units);
  i=0;
  XtSetArg(args[i], XtNlabel, strcpy(XtMalloc(sizeof(buf)), buf));i++;
  XtSetArg(args[i], XtNminimum, &vd->min);i++;
  XtSetArg(args[i], XtNmaximum, &vd->max);i++;
  XtSetArg(args[i], XtNpresent, &present);i++;
  XtSetArg(args[i], XtNdefault, &vd->normal);i++;
  XtSetArg(args[i], XtNprevious, &present);i++;
  if (data->patientActive) {
    XtSetArg(args[i], XtNpercentage, 1);i++;
  } else {
    XtSetArg(args[i], XtNpercentage, 0);i++;
  }

  j = 0;
  XtSetArg(largs[j], XtNallowShellResize, True);j++;
  XtSetArg(largs[j], XtNiconName, vd->name);j++;
#ifdef XAW_BC
  shell = XtCreateApplicationShell(vd->name, topLevelShellWidgetClass,
				   largs, j);
#else /* ! XAW_BC */
  shell = XtAppCreateShell(NULL,"CVsim",topLevelShellWidgetClass,dpy,largs,j);
#endif
  widget = XtCreateManagedWidget(vd->name, numberLineWidgetClass,
				 shell, args, i);
  XtAddEventHandler(shell, ButtonPressMask | ButtonReleaseMask, False, 
		    dummyHandler, (caddr_t)0);
  if (NumberLineCheckType(place,type)) {
    /* disallow 2 numberlines of same place&type */
    NumberLineCancelType(shell);
    XtDestroyWidget(shell);
    return;
  }
  XtRealizeWidget(shell);
  (void) NumberLineEnroll(shell, place, type);
  XSetIconName(dpy, XtWindow(shell), vd->name);
  XtAddCallback(widget, XtNcallback, NumberLineCallback,
		(caddr_t)(place*100 + type));
  while (XCheckWindowEvent(dpy, XtWindow(w), ButtonPressMask, &ev)) ;
}

/*
 * The following procedures deal with the form for 
 * creating new plots.
 */


/*ARGSUSED*/
static void MakePlot(w, args, argCount)
Widget w;
ArgList args;
int argCount;
{
  Widget widget, shell;
  XEvent ev;

  widget = CreateIndepWidget("Plot",plotWidgetClass,&shell, args, argCount);
  if (widget) AddDataWidget(widget, (XtCallbackProc)0, PlotData);
  while (XCheckWindowEvent(dpy, XtWindow(w), ButtonPressMask, &ev)) ;
}

/*ARGSUSED*/
static void NewPlot(widget, client, call)
Widget widget;
caddr_t client, call;
{
  Widget menu;
  XEvent ev;
  if(menu = MakePlotMenu(widget, MakePlot, 500, 5, 
			 (AxisData *)NULL, (AxisData *)NULL, 
			 (AxisData *)NULL, (AxisData *)NULL))
    XtPopup(menu, XtGrabExclusive);
  while (XCheckWindowEvent(dpy, XtWindow(widget), ButtonPressMask, &ev)) ;
}

/*PUBLIC*/ Widget BUTTON_BOX;
static Widget HxShell;

/*
 * Generic widget deleter
 */
/*ARGSUSED*/
static void DeletePlot(widget, client, call)
  Widget widget;
  caddr_t client, call;
{
  Widget wid;
  XEvent ev;

  wid = UserSelectWidget();
  if (wid && BUTTON_BOX && wid != XtParent(BUTTON_BOX)) {
    DeleteDataWidget(wid);
    NumberLineCancelType(wid);
    XtUnmapWidget(wid);
    XtDestroyWidget(wid);
    if (paramWidget && (wid == XtParent(paramWidget))) paramWidget = NULL;
    if (HxShell && (wid == HxShell || wid == XtParent(HxShell)))HxShell = NULL;
  }
  while (XCheckWindowEvent(dpy, XtWindow(widget), ButtonPressMask, &ev)) ;
}

#ifdef NOTDEFYET
struct pixlist {
  Pixmap pixmap;
  struct pixlist *nest;
} ;

static void Save(widget, client, call)
     Widget widget;
     caddr_t client, call;
{
  Widget wid;

  wid = UserSelectWidget();
  if (wid && BUTTON_BOX && wid != XtParent(BUTTON_BOX)) {
    
  }
}
#endif

/*ARGSUSED*/
static void PrintPlot(widget, client, call)
Widget widget;
caddr_t client, call;
{
  char *printCmd;
  XEvent ev;
  int s;

  printCmd = getenv("CVPRINT");
  if (!printCmd || strlen(printCmd) < 2)
    printCmd = "xdpr";
  if (s=system(printCmd)) 
    fprintf(stderr, "%s: exit status %d",printCmd, s);
  while (XCheckWindowEvent(dpy, XtWindow(widget), ButtonPressMask, &ev)) ;
}

static Widget resetWidget;

/*ARGSUSED*/
static void ResetAction(widget, client, call)
Widget widget;
caddr_t client, call;
{
  CVData data = (CVData) client;
  char buf[1024];
  XEvent ev;
  
  (void) strcpy(buf, CVLib);
  (void) strcat(buf, "/parameter.db");
  LoadParameterData(buf);
  ReflexesOff();
  if (data->patientActive)
    NumberLineDestroyAll();
  else
    NumberLineResetAll();
  if (paramWidget)
    ShowParameters(paramWidget, (caddr_t) paramWinData, (caddr_t)0);
  if (HxShell) XtDestroyWidget(HxShell); HxShell = 0;
  ResetSimulator(setsimulation());
  if (!data->simulating) StopSimulator();
  data->patientActive=0;
  patientActive = 0;
  {
    Arg args[2]; /* MAKE PARAMETER LIST BUTTON SENSITIVE */
    XtSetArg(args[0], XtNsensitive, True);
    XtSetValues((Widget) data->buttons[LISTBUTTON], args, 1);
  }
  KillDialog(resetWidget, (caddr_t)resetWidget, (caddr_t)NULL);
  while (XCheckWindowEvent(dpy, XtWindow(widget), ButtonPressMask, &ev)) ;
}

/*ARGSUSED*/
static void ResetButton(widget, client, call)
Widget widget;
caddr_t client, call;
{
  CVData data = (CVData) client;
  Widget w, reset, cancel;

  resetWidget = w = 
    DialogCreate(widget,"This will reset the system.",(char *)NULL);
  reset = XtCreateManagedWidget("Reset", commandWidgetClass,w, (Arg *)0,0);
  cancel= XtCreateManagedWidget("Cancel", commandWidgetClass,w, (Arg *)0,0);
  XtAddCallback(reset, XtNcallback, ResetAction, (caddr_t)data);
  XtAddCallback(cancel, XtNcallback, KillDialog, (caddr_t)w);
  PlaceDialog(w, widget);
}

static void ShowHx(history)
char *history;
{
#ifdef XAW_BC
  Arg args[5];
#else
  Arg args[10];
  XFontStruct *historyFont;
#endif
  int i=0;

  /* Show only 1 history at a time. */
  if (HxShell) XtDestroyWidget(HxShell); HxShell = (Widget) 0;
  XtSetArg(args[i], XtNstring, history);i++;
  XtSetArg(args[i], XtNsensitive, False);i++;
#ifdef XAW_BC
  XtSetArg(args[i], XtNtextOptions, resizeHeight | resizeWidth);i++;
  CreateIndepWidget("History", asciiStringWidgetClass, &HxShell, args, i);
#else /* ! XAW_BC */
  /* 
   * The history popup was not resizing to accommodate the text -
   * hence the gross width and height resources.  Probably should be
   * fixed someday. dlb 8/10/90
  */
  historyFont = XLoadQueryFont (dpy, "Fixed");
  XtSetArg(args[i], XtNtype, XawAsciiString); i++;
  XtSetArg(args[i], XtNuseStringInPlace, True); i++;
  XtSetArg (args[i], XtNlength, strlen(history)); i++;
  XtSetArg(args[i], XtNresize, XtEtextResizeBoth);i++; 
  XtSetArg(args[i], XtNfont, historyFont); i++;
  XtSetArg(args[i], XtNwidth, 500); i++;
  XtSetArg(args[i], XtNheight, 225); i++;
  CreateIndepWidget("History", asciiTextWidgetClass, &HxShell, args, i);
#endif
}

/*ARGSUSED*/
static void callbackPopdown(w, client, call)
Widget w;
caddr_t client, call;
{
  XtPopdown((Widget)client);
}

typedef struct {
  CVData data;
  char *path;
} PatientDataRec, *PatientData;

static char KEYWORD[80];

/*ARGSUSED*/
static void DoPatient(widget, client, call)
Widget widget;
caddr_t client, call;
{
  CVData data = ((PatientData) client)->data;
  char *path =  ((PatientData) client)->path;
  char *history;
  char buf[1024];
  XEvent ev;
  Widget parent = XtParent(widget);

  if (parent) callbackPopdown(widget, (caddr_t) XtParent(parent), call);
  (void) strcpy(buf, CVLib);
  (void) strcat(buf, "/parameter.db");
  LoadParameterData(buf);
  ReflexesOff();
#ifndef NOCRYPT							      /* GBM */
  (void) sprintf(buf, "crypt %s < %s > /tmp/pt.pcv01", KEYWORD, path);
  (void) system(buf);
  if ((history = LoadPatient("/tmp/pt.pcv01")) == NULL) {
    (void) unlink("/tmp/pt.pcv01");
    return; /* no such patient file */
  }
  (void) unlink("/tmp/pt.pcv01");
#else								      /* GBM */
  if ((history = LoadPatient(path)) == NULL) {		       	      /* GBM */
    return; /* no such patient file */			       	      /* GBM */
  }								      /* GBM */
#endif
  data->patientActive = 1;
  patientActive = 1;
  {
    Arg args[2]; /* MAKE PARAMETER LIST BUTTON INSENSITIVE */
    XtSetArg(args[0], XtNsensitive, False);
    XtSetValues((Widget) data->buttons[LISTBUTTON], args, 1);
  }
  ResetSimulator(setsimulation());
  NumberLineDestroyAll();
  if (paramWidget) {
    XtDestroyWidget(XtParent(paramWidget)); 
    paramWidget = NULL;
  }
 if (!data->simulating) StopSimulator();
#ifdef DEBUG
  printf("%s\n",history);
#endif
  ShowHx(history);
  XtPopdown(data->patients);
  while (XCheckWindowEvent(dpy, XtWindow(widget), ButtonPressMask, &ev)) ;
}

/*ARGSUSED*/
static void Patients(widget, client, call)
Widget widget;
caddr_t client, call;
{
  CVData data = (CVData) client;
  Widget button, cancel;
  static Widget box;
  int i;
  int fd, n=0;
  Arg args[10];
  char name[1024];
  static char pathname[20][80];					      /* GBM */
  PatientData patientData;

  if (!data->patients) {
    data->patients = XtCreatePopupShell("PatientsShell", 
					overrideShellWidgetClass,
					widget, (Arg *)NULL, 0);
    box = XtCreateManagedWidget("patientList", boxWidgetClass, 
				data->patients, (Arg *)NULL, 0);
    i=0;
    XtSetArg(args[i], XtNborderWidth, 0);i++;
    XtCreateManagedWidget("Patient Unknowns", labelWidgetClass, box, args, i);
    for (n=0; n<20; n++) {
      (void) sprintf(pathname[n],"%s/Patients/hist.%1d",CVLib,n);     /* GBM */
      if ((fd=open(pathname[n],O_RDONLY,0)) > 0) {		      /* GBM */
	(void) close(fd);
	i=0;
	(void) sprintf(name,"Case #%d",n);
#ifdef DEBUG
	printf("%s\n",name);
#endif
	XtSetArg(args[i], XtNlabel,
		 strcpy(XtMalloc(sizeof(char)*strlen(name)), name));i++;
	button =XtCreateManagedWidget("patient",commandWidgetClass,box,args,i);
	patientData = (PatientData) XtMalloc(sizeof(PatientDataRec));
	patientData->data = data;
	patientData->path = pathname[n];			      /* GBM */
	XtAddCallback(button, XtNcallback, DoPatient, (caddr_t)patientData);
      }
    }
    cancel = XtCreateManagedWidget("Cancel", commandWidgetClass, box, 
				   (Arg *)0,0);
    XtAddCallback(cancel, XtNcallback, callbackPopdown,(caddr_t)XtParent(box));
  }
  PlaceDialog(box, widget);
}

/*
 *
 * Public definitions.
 *
 */
static XContext nlContext = (XContext)NULL;

/*PUBLIC*/ /*ARGSUSED*/
Widget InterfaceCreate(parent, args, argCount)
Widget parent;			/* Window to put the form in. */
ArgList args;			/* Args to pass on to form (if any). */
int argCount;
{
  CVData data = (CVData) XtMalloc(sizeof(CVDataRec));
  register int i;

#ifndef NOCRYPT					   		      /* GBM */
  { /* snarf keyword for later crypt calls */
    FILE *kwfile;
    char buf[1024];
    
    (void) sprintf(buf, "crypt keyword < %s/Patients/kw.cr > /tmp/pt.pck01", 
		   CVLib);
    (void) system(buf);
    kwfile = fopen("/tmp/pt.pck01","r");
    (void) fgets(KEYWORD, 79, kwfile);
    (void) fclose(kwfile);
    (void) unlink("/tmp/pt.pck01");
    KEYWORD[strlen(KEYWORD)-1] = '\0'; /* nuke the stupid \n from fgets */
  }
#endif
  if (nlContext == (XContext)NULL) nlContext = XUniqueContext();
  { /* start with a help screen*/
    Widget w;
    Arg args[10];
    int i = 0;
    char buf[256];

    if (CVLib) (void) sprintf(buf, "%s/help.txt", (char *) CVLib);
    else       (void) strcpy(buf, "help.txt");

#ifdef XAW_BC
    w = XtCreateApplicationShell("Help", transientShellWidgetClass,
				 (ArgList)0, 0);
    XtSetArg(args[i], XtNfile, buf);i++;
    XtSetArg(args[i], XtNiconName, "Help");i++;
    XtCreateManagedWidget("Help", asciiDiskWidgetClass, w, args, i);
#else /* ! XAW_BC */
    XtSetArg(args[i], XtNiconName, "Help");i++;
    w = XtAppCreateShell(NULL,"CVsim",transientShellWidgetClass,
			 dpy,(Arg *)args,i);

    XtSetArg (args[i], XtNtype, XawAsciiFile); i++;
    XtSetArg (args[i], XtNstring, buf); i++;
    XtSetArg(args[i], XtNwidth, 700);i++;
    XtSetArg(args[i], XtNheight, 570);i++;
    XtSetArg(args[i], XtNsensitive, False);i++;
    XtCreateManagedWidget("Help", asciiTextWidgetClass, w, args, i);
#endif
    XtAddEventHandler(w, ButtonPressMask | ButtonReleaseMask, False, 
		      dummyHandler, (caddr_t)0);
    XtRealizeWidget(w);
    XSetIconName(dpy, XtWindow(w), "Help with Cardiovascular Simulator");
  }
  {
    Widget w;
    Arg largs[5];
    int i = 0;
    char *name = "Simulator Command Buttons";

    XtSetArg(largs[i], XtNiconName, name);i++;
#ifdef XAW_BC
    w = XtCreateApplicationShell(name,topLevelShellWidgetClass, largs, i);
#else /* ! XAW_BC */
    w = XtAppCreateShell(NULL,"CVsim",topLevelShellWidgetClass, dpy, largs, i);
#endif
    data->buttonBox = XtCreateManagedWidget("commandButtons", boxWidgetClass,w,
					    (Arg *)0,0);
    BUTTON_BOX = data->buttonBox; /* to be saved during spring cleaning */
    XtConfigureWidget(w, XDisplayWidth(dpy,XDefaultScreen(dpy))-240-100, 
		         10, 250, 125, 4);
    XtRealizeWidget(w);
    XSetIconName(dpy, XtWindow(w), "CV Simulator Buttons");
  }
  data->simulating = TRUE;
  data->patientActive = 0;
  patientActive = 0;
  data->administrator = 0;
  data->patients = NULL;
  for (i=0; Buttons[i]; i++) {
    static char *trans = "<BtnUp>: notify() unset() unhighlight() \n";
    Arg args[1];
    int count = 0;
    XtSetArg(args[0], XtNlabel, Buttons[i]);count++;
    data->buttons[i] =XtCreateManagedWidget("commandButton",
					    commandWidgetClass, 
					    data->buttonBox, args, count);
    XtOverrideTranslations(data->buttons[i], XtParseTranslationTable(trans));
    XtAddCallback(data->buttons[i], XtNcallback, ButtonProc[i], (caddr_t)data);
  }
#ifdef REFLEX_OFF
  {
    Arg args[2]; /* MAKE BARORECEPTOR BUTTON INSENSITIVE */
    XtSetArg(args[0], XtNsensitive, False);
    XtSetValues((Widget) data->buttons[REFLEXBUTTON], args, 1);
  }
#endif
  return ((Widget)0);
}





