/*
 * Baroreflex extensions to eqns.c in the Cardiovascular Simulator.
 * Timothy Davis, 7/30/89
 * Based loosely on the DeBoer beat-to-beat model for 
 * baroreceptor control of heart rate, contractility, 
 * and peripheral resistance, with added control of venous blood volume.
 *
 * $Source: /var/tldavis/src/sim/RCS/reflex.c,v $
 * $Log:	reflex.c,v $
 * Revision 2.5  91/02/04  16:43:51  tldavis
 * Updated arterial pressure setpoint to 98 mm Hg.
 * 
 * Revision 2.4  90/08/28  14:46:31  tldavis
 * linted.
 * 
 * Revision 2.3  90/08/18  18:40:31  tldavis
 * New location of CVDefs,
 * also bugifixes to X interface sections, ref. to Interface.c for
 * dialog boxes.
 * 
 * Revision 2.2  90/08/10  10:58:08  dot
 * moved Xaw header files to X11/Xaw for R4
 * 
 * Revision 2.1  90/08/07  16:07:26  tldavis
 * Removed unused variables.
 * 
 * Revision 2.0  90/08/06  18:02:54  tldavis
 * Final X11R3 version.
 * 
 * Revision 1.6  90/05/31  16:27:06  tldavis
 * Pre-ACIS checkin.
 * 
 */
#include "CVDefs.h"
#include <math.h>

#ifndef NO_X_WINDOWS
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>
#include "../nl/NumberLine.h"
#include "../main/Interface.h" /* DialogCreate(),PlaceDialog(),KillDialog() */

/*PUBLIC*/ Boolean reflexesOn = 0;
#else
/*PUBLIC*/ void SimFlush()
{
; /*NOOP*/
}
typedef char Boolean;
#define True 1
#define False 0

/*PUBLIC*/ Boolean reflexesOn = 1;
#endif


/* The following "signal" variables are used in eqns.c */
/*PUBLIC*/
double sigHR = NHR, sigR = NRA, sigV = NVV0, sigCl = NCLSYS, sigCr = NCRSYS; 
extern double hr, Ra, Vv0, Clsys, Crsys, Ca; /* from eqns.c */

#define SETPOINT 98 /* Set as close as possible to maintaining homeostasis. */
static Boolean hrActive = True, cActive = True, rActive = True, vActive = True;
static double alphaGain = 9, betaGain = 9, paraGain = 9, aSetpoint = SETPOINT;
static double alphaTone = 0, betaTone = 0, paraTone = 0; /* baseline */

/*****************************************************************************
 * Signal history manipulation routines:
 * save the last 30 seconds in 40 ms increments for 
 * computing time-delayed nervous response signals.
 *****************************************************************************/

#define Sgran (0.5) /* 500 millisecond granularity in signal history */
#define Slength (60) /* for 60 * 0.5 = 30 seconds of data. */

static double  Shist[Slength]; /* queue representing arterial b.p. */
static int top=0; /* head of the queue */

/* Enqueue a blood pressure value */
static void saveS(signal) 
     double signal;
{
  top = (top + Slength - 1) % Slength; /* wraparound modulus arithmetic */
  Shist[top] =  signal;
}

static void scaleSignal(scale)
double scale;
{
  register int i = 0;
  for (i = 0; i < Slength; i++)
    Shist[i] *= scale;
}

#ifdef NOTDEF
static void translateSignal(shift)
double shift;
{
  register int i = 0;
  double max = 18*atan(100000.0);
  double min = 18*atan(-100000.0);

  for (i = 0; i < Slength; i++) {
    Shist[i] += shift;
    if (Shist[i] > max) Shist[i] = max;
    if (Shist[i] < min) Shist[i] = min;
  }
}
#endif

/* Compute weighted sum of past pressures */
static double sumResponse(coeffs, start, end) 
     double coeffs[]; /*Coefficients are in reverse (most recent 1st) order*/
     int start, end;/* to optimize in case of short response characteristics */
{
  double sum = 0.0;  int i;
  for (i = start; i < end; i++) 
    sum += coeffs[i] * Shist[(top + i) % Slength]; /* more modulus math */
  return sum;
}

/* Prepare a list of coeffs to match given triangle ramp parameters. */
static void mkRamp(coeffs, start, peak, end, area)
     double *coeffs; /* pointer to coeffs buffer*/
     double area;    /* total sumResponse  for unity b.p. signal */
     double start, peak, end; /* ramp timing in seconds(to convert to index)*/
{
  int i;
  double sum = 0.0;
  start /= Sgran; peak /= Sgran; end /= Sgran; /* Convert to index */

  for (i = start; i < peak; i++) 
    sum += coeffs[i] = (i-((int)start))/(peak-start);
  for (i = peak; i < end; i++) 
    sum += coeffs[i] = (((int)end) - i)/(end - peak);
  for (i = start; i < end; i++)
    coeffs[i] *= area/sum; /* normalizing to required total sum 
			      (analogous to area in continuous time) */
}

/*****************************************************************************
 * aCoeff is to be a list of timing coefficients for alpha-sympathetic control.
 * bCoeff is coefficients for beta-sympathetic control.
 * pCoeff contains parasympathetic timing information.
 *****************************************************************************/

static double aCoeff[Slength], bCoeff[Slength], pCoeff[Slength];
static int aStart, aEnd, bStart, bEnd, pStart, pEnd;

/*PUBLIC*/ /* used in Event.c */
void setupCoeffs() /* Here we define the shapes of coefficient arrays */
{
  scaleSignal(0.0); /*zero out everything*/
  mkRamp(aCoeff, 2.0, 5.0, 30.0, 1.0); 
  aStart = 2.0 / Sgran; aEnd = 30.0 / Sgran;
  mkRamp(bCoeff, 2.0, 5.0, 30.0, 1.0); 
  bStart = 2.0 / Sgran; bEnd = 30.0 / Sgran;
  mkRamp(pCoeff, 0.0, 0.5, 1.0, 1.0); 
  pStart = 0.0 / Sgran; pEnd = 1.0 / Sgran;
}

/*****************************************************************************
 * reflex arc definitions:
 *
 *****************************************************************************/

/* Reflex arc replacement when reflexes are off */
static void NoReflex()
{
  sigHR = hr;
  sigCl = Clsys;
  sigCr = Crsys;
  sigR  = Ra;
  sigV  = Vv0;
}

/* Reflex arc calculations, performed at ~2 times per beat granularity */
static void Reflexes()
{
  double i, r, v, p; /* DeBoer's lower-case deviation variables */
  double alphaResp, betaResp, paraResp, I;
  static double rho = 0.2   / 0.5088; /* Max Cl deviation / Max i */
  static double nu  = 750.0 / 0.5088; /* Max V0 deviation / Max i */

  /* Calculate current levels of autonomic reflex activity based on past ABP*/
  alphaResp = alphaGain * sumResponse(aCoeff, aStart, aEnd) * 0.001;
  betaResp  = betaGain  * sumResponse(bCoeff, bStart, bEnd) * 0.001;
  paraResp  = paraGain  * sumResponse(pCoeff, pStart, pEnd) * 0.001;

  /* Interbeat interval (small-signal model) from DeBoer */
  i = (hrActive ? betaResp + paraResp : 0.0) - betaTone + paraTone;
      /* HR determined by both symp. and parasymp. responses */

  /* Systolic capacitance linear feedback, scaled to change Clsys and Crsys/3
   * by a maximum of 0.2 mmHg/ml.  This conforms to Guyton's assertion that
   * contractility can double with exercise, and stays anove simulation bound
   * of 0.2 for Clsys.
   */
  p = rho * ((cActive ? betaResp : 0.0) - betaTone)*2; 
      /* Clsys and Crsys/3 deviations */

  /* Peripheral resistance (small-signal model) from DeBoer */
  r = - ((rActive ? alphaResp : 0.0) - alphaTone)*2 / Ca;

  /* Venous zero-pressure volume (reflecting venous tone) feedback scaled for
   * a maximum of 500cc deviation from reference.  This comes from Guyton,
   * who says venous pooling can vary between 600cc and 2600cc from tonus.
   */
  v = nu * ((vActive ? alphaResp : 0.0) - alphaTone)*2; 

  /* Add either feedback signal deviation or pure tonus data 
   * to controlled variables.
   */
  I = 60./hr +  i;
  sigHR = (I < 0.25) ? 60/0.25 : 60./I;   /* max HR signal of 240 */
  if (sigHR > 250) sigHR = 250.0;
  if (sigHR < 0) sigHR = 0.0;
  sigCl = Clsys + p;   if (sigCl < 0.2) sigCl = 0.2;
  sigCr = Crsys + 3*p; if (sigCr < 0.6) sigCr = 0.2;
  sigR  = Ra + r;      if (sigR  < 0.1) sigR  = 0.1;
  sigV  = Vv0+ v;      if (sigV  < 0.0) sigV  = 0.0;
}

/* The following simply updates the baroreflex on demand for the benefit of 
 * setval() in eqns.c which needs an up-to-date system.
 */
/*PUBLIC*/ void calcReflexes()
{
  if (reflexesOn)
    Reflexes();
  else
    NoReflex();
}

/* SANODE tickles the s-a node to determine if a new beat should occur.  It
 * does this by integrating a heart rate signal until 
 * average_HR*This_interval >= 1.0.
 * It also tickles the baroreflex every 40 milliseconds.
 */
/*PUBLIC*/
void sanode(x, dt)  
     double x[];
     double dt;
{
  static double cum_hr = 0.0, cum_t = 0.0;
  static double cum_t2 , cum_abp = 0.0; /* for 40ms abp average */
  static int abp_n = 0, n = 0;
  
  cum_t2 += dt;
  abp_n++;
  cum_abp += x[1];
  if (cum_t2 > Sgran) { 
    /* save signal for the last 40 milliseconds */
    double s; /* instantaneous baroreceptor (ascending nerve) signal */
    s = 18*atan((cum_abp/abp_n - aSetpoint)/18);  /* from DeBoer */
    saveS(s); /* enqueue this average pressure */
    cum_t2 -= Sgran; abp_n = 0; cum_abp = 0; /*start next interval avging*/
    if (reflexesOn)  Reflexes(); 
    else             NoReflex();
  } 

  cum_hr += sigHR;
  cum_t  += dt;
  n++;
  /* 
   * Wait until area under the hr signal vs. time curve reaches 1.00,
   * then start the next beat, as long as we have passed the absolute
   * refractory period of 1/5 of a  beat length since systole.
   * Setting cum_t to -0.1 gives a 0.1 sec P-R conduction delay.
   */
  if ((cum_t*cum_hr/n >= 60.0) && (x[9] > TBLSEGS * 1.2)) {
    /* start a new beat */
    x[9] = 0.0; /* reset tblc index, which starts a beat. */
    cum_hr = 0.0; cum_t = 0.0; n = 0; /* reset summation "IPFM" integral */
    btconst(); /* reset simulation constants for next beat */

#ifdef DEBUG
    if (reflexesOn) 
      printf("signal:%4d, hr:%6.3d, R:%6.3f, Cl:%6.3f, Cr:%6.3f, Vv0:%6.0f\n", 
	     (int) Shist[top], (int) sigHR, (float) sigR, (float) sigCl,
	     (float) sigCr, (float) sigV);
#endif
  }
}

#ifndef NO_X_WINDOWS
/**************************************************************************
 *
 * User interface to Baroreflex feedback system.
 *
 **************************************************************************/

static Widget hrButton, cButton, rButton, vButton, modButton, 
  reflexActiveButton;
extern Display *dpy;
extern Window root;
extern int screen;

extern int Stopped; /* from Event.c */
extern void StopSimulator(), ResumeSimulator();

Boolean Paused = False;

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

/*ARGSUSED*/
static void UseDataCallback(w, client, call)
Widget w;
caddr_t client, call;
{
  Arg args[2];
  XEvent ev;

  while (XCheckWindowEvent(dpy, XtWindow(w), ButtonPressMask, &ev)) ;

  XtSetArg(args[0],XtNlabel,reflexesOn?"Reflexes are ON":"Reflexes are OFF");
  XtSetValues(reflexActiveButton, args, 1);
  if (reflexesOn)   XtSetArg(args[0], XtNsensitive, True);
  else              XtSetArg(args[0], XtNsensitive, False);
  
  XtSetValues(hrButton, args, 1);  
  XtSetValues(cButton, args, 1);  
  XtSetValues(rButton, args, 1);
  XtSetValues(vButton, args, 1);
  XtSetValues(modButton, args, 1);
}  

/*ARGSUSED*/
static void RestCallback(w, client, call)
Widget w;
caddr_t client, call;
{
  scaleSignal(0.0); /* zero-out past signal */
  UseDataCallback(w, client, call);
}

static void getReflexToggle(w, client, call)
     Widget w;
     caddr_t client, call;
{

  static int modal_sema = 1;
  XEvent ev;

  if (!client) {
    reflexesOn = !reflexesOn;
    if (reflexesOn) {
      /* Determine if we want to start from rest state or use current data. */
      if (modal_sema) {
	Widget dialog, rest, usedata;

	modal_sema--;
	Paused = !Stopped;
	if (Paused) StopSimulator();

	dialog = DialogCreate(w, "Choose initial reflex response", (char *)0);

	usedata = XtCreateManagedWidget("Use current data",commandWidgetClass,
					dialog,(Arg *)NULL, 0);
	XtAddCallback(usedata, XtNcallback, UseDataCallback, (caddr_t) 0);
	XtAddCallback(usedata, XtNcallback, ClearSema,  (caddr_t) &modal_sema);
	XtAddCallback(usedata, XtNcallback, KillDialog, (caddr_t) dialog);
	rest = XtCreateManagedWidget("Reset to rest conditions", 
				     commandWidgetClass,
				     dialog, (Arg *)NULL, 0);
	XtAddCallback(rest,  XtNcallback, RestCallback, (caddr_t) 0);
	XtAddCallback(rest,  XtNcallback, ClearSema,  (caddr_t) &modal_sema);
	XtAddCallback(rest,  XtNcallback, KillDialog, (caddr_t)dialog);
	PlaceDialog(dialog, w);
      }
      while (XCheckWindowEvent(dpy, XtWindow(w), ButtonPressMask, &ev)) ;
    } else UseDataCallback(w, client, call);
  } else UseDataCallback(w, client, call);
}

static void getLimbToggle(w, client, call)
     Widget w;
     caddr_t client, call;
{
  Arg args[3];
  Boolean *limb = (Boolean *) client;
  if (!call) *limb = ! *limb;
  XtSetArg(args[0],XtNlabel,*limb?"ACTIVE":"inactive");
  XtSetValues(w, args, 1);
}

/*ARGSUSED*/
static void sympCallback(w, client, call)
     Widget w;
     caddr_t client, call;
{
  double present, *presentPtr = (double *) client;
  int done;
  NumberLineGetValue(w, &present, &done);
#ifdef DEBUG
  printf("Symp. Callback: present = %lf\n", present);
#endif
  *presentPtr = present;
}

#ifdef NOTDEF
/* THIS ISN'T CURRENTLY USED:  nonphysiologic all-time setpoint change.
/*
 * setpointChange() callback implements a nonphysiologic setpoint change for
 * all time, changing the history of the baroreceptor to
 * pretend the setpoint was this all along.
 * I consider this nonphysiologic and thus unintuitive.
 */
/*ARGSUSED*/
static void setpointChange(w, client, call)
     Widget w;
     caddr_t client, call;
{
  static double previous = SETPOINT;
  double present;
  int done;
  NumberLineGetValue(w, &present, &done);
  /* Change the all signal from the baroreceptor to center on the 
     NEW setpoint */
  translateSignal(previous - present);
  previous = present;
}
#endif

/*ARGSUSED*/
static void destroyNotify(w, client, call)
     Widget w;
     caddr_t client, call;
{
  *((Boolean *)client) = False;
}

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

/*ARGSUSED*/
static void modReflexCallback(w, client, call)
     Widget w;
     caddr_t client, call;
{
  Arg args[20];
  int i, j;
  static Widget shell, form, titleLabel, alphaNl, betaNl, paraNl, setpointNl,
                atNl, btNl, ptNl;
  static double smin = 0, pmin = 0, smax = 20, pmax = 20, sdef = 9, pdef = 9;
  static double tmin = -1, tmax = 1, tdef = 0;
  static double amin = 0, amax = 200, adef = 90;
  static Boolean Exists = False;

  if (Exists) return;
  else Exists = True;
  i=0;
  XtSetArg(args[i], XtNallowShellResize, True);i++;
  XtSetArg(args[i], XtNiconName, "Baroreceptor Reflex Parameters");i++;
#ifdef XAW_BC
  shell = XtCreateApplicationShell("baroreceptor_parameters",
				   topLevelShellWidgetClass, args, i);
#else
  shell = XtAppCreateShell(NULL,"CVsim", topLevelShellWidgetClass,dpy,args,i);
#endif
  XtAddCallback(shell, XtNdestroyCallback, destroyNotify, (caddr_t)&Exists);
  XtAddEventHandler(shell, ButtonPressMask | ButtonReleaseMask, False, 
		    dummyHandler, (caddr_t)0);
  form = XtCreateManagedWidget("Baroreceptor Reflex", formWidgetClass, 
			       shell, (Arg *)0, 0);
  i=0;
  XtSetArg(args[i], XtNvertDistance, 4);i++;
  XtSetArg(args[i], XtNresizable, True);i++;
  j = i;
  XtSetArg(args[i], XtNborderWidth, 0);i++;
  titleLabel = XtCreateManagedWidget("BARORECEPTOR REFLEX PARAMETERS", 
				     labelWidgetClass, form, args, i);
  XtSetArg(args[j], XtNwidth, 200);j++;
  i=j;
  XtSetArg(args[i], XtNfromVert, titleLabel);i++;
  XtSetArg(args[i], XtNlabel, "ABP Setpoint (mmHg)");i++;
  XtSetArg(args[i], XtNminimum, &amin);i++;
  XtSetArg(args[i], XtNmaximum, &amax);i++;
  XtSetArg(args[i], XtNpresent, &aSetpoint);i++;
  XtSetArg(args[i], XtNdefault, &adef);i++;
  XtSetArg(args[i], XtNprevious, &aSetpoint);i++;
  setpointNl = XtCreateManagedWidget("numberLine", numberLineWidgetClass,
				     form, args, i);
  XtAddCallback(setpointNl, XtNcallback, sympCallback,(caddr_t) &aSetpoint);
#ifdef NOTDEF
/* Nonphysiologic "total" setpoint changes. */
  XtAddCallback(setpointNl, XtNcallback, setpointChange, (caddr_t) &aSetpoint);
#endif
  /* Left side */
  i=j;
  XtSetArg(args[i], XtNfromVert, setpointNl);i++;
  XtSetArg(args[i], XtNlabel, "Periph. Sympathetic Tone");i++;
  XtSetArg(args[i], XtNminimum, &tmin);i++;
  XtSetArg(args[i], XtNmaximum, &tmax);i++;
  XtSetArg(args[i], XtNpresent, &alphaTone);i++;
  XtSetArg(args[i], XtNdefault, &tdef);i++;
  XtSetArg(args[i], XtNprevious, &alphaTone);i++;
  atNl = XtCreateManagedWidget("numberLine", numberLineWidgetClass,
			       form, args, i);
  XtAddCallback(atNl, XtNcallback, sympCallback,(caddr_t) &alphaTone);
  i=j;
  XtSetArg(args[i], XtNfromVert, atNl);i++;
  XtSetArg(args[i], XtNlabel, "Heart Sympathetic Tone");i++;
  XtSetArg(args[i], XtNminimum, &tmin);i++;
  XtSetArg(args[i], XtNmaximum, &tmax);i++;
  XtSetArg(args[i], XtNpresent, &betaTone);i++;
  XtSetArg(args[i], XtNdefault, &tdef);i++;
  XtSetArg(args[i], XtNprevious, &betaTone);i++;
  btNl = XtCreateManagedWidget("numberLine", numberLineWidgetClass,
				 form, args, i);
  XtAddCallback(btNl, XtNcallback, sympCallback,(caddr_t) &betaTone);
   i=j;
  XtSetArg(args[i], XtNfromVert, btNl);i++;
  XtSetArg(args[i], XtNlabel, "Parasympathetic Tone");i++;
  XtSetArg(args[i], XtNminimum, &tmin);i++;
  XtSetArg(args[i], XtNmaximum, &tmax);i++;
  XtSetArg(args[i], XtNpresent, &paraTone);i++;
  XtSetArg(args[i], XtNdefault, &tdef);i++;
  XtSetArg(args[i], XtNprevious, &paraTone);i++;
  ptNl = XtCreateManagedWidget("numberLine", numberLineWidgetClass,
				 form, args, i);
  XtAddCallback(ptNl, XtNcallback, sympCallback,(caddr_t) &paraTone);
 /* right side */
  i=j;
  XtSetArg(args[i], XtNfromVert, setpointNl);i++;
  XtSetArg(args[i], XtNfromHoriz, setpointNl);i++;
  XtSetArg(args[i], XtNlabel, "Periph. Sympathetic Gain");i++;
  XtSetArg(args[i], XtNminimum, &smin);i++;
  XtSetArg(args[i], XtNmaximum, &smax);i++;
  XtSetArg(args[i], XtNpresent, &alphaGain);i++;
  XtSetArg(args[i], XtNdefault, &sdef);i++;
  XtSetArg(args[i], XtNprevious, &alphaGain);i++;
  alphaNl = XtCreateManagedWidget("numberLine", numberLineWidgetClass,
				 form, args, i);
  XtAddCallback(alphaNl, XtNcallback, sympCallback,(caddr_t) &alphaGain);
  i=j;
  XtSetArg(args[i], XtNfromVert, alphaNl);i++;
  XtSetArg(args[i], XtNfromHoriz, setpointNl);i++;
  XtSetArg(args[i], XtNlabel, "Heart Sympathetic Gain");i++;
  XtSetArg(args[i], XtNminimum, &smin);i++;
  XtSetArg(args[i], XtNmaximum, &smax);i++;
  XtSetArg(args[i], XtNpresent, &betaGain);i++;
  XtSetArg(args[i], XtNdefault, &sdef);i++;
  XtSetArg(args[i], XtNprevious, &betaGain);i++;
  betaNl = XtCreateManagedWidget("numberLine", numberLineWidgetClass,
				 form, args, i);
  XtAddCallback(betaNl, XtNcallback, sympCallback,(caddr_t) &betaGain);
   i=j;
  XtSetArg(args[i], XtNfromVert, betaNl);i++;
  XtSetArg(args[i], XtNlabel, "Parasympathetic Gain");i++;
  XtSetArg(args[i], XtNfromHoriz, setpointNl);i++;
  XtSetArg(args[i], XtNminimum, &pmin);i++;
  XtSetArg(args[i], XtNmaximum, &pmax);i++;
  XtSetArg(args[i], XtNpresent, &paraGain);i++;
  XtSetArg(args[i], XtNdefault, &pdef);i++;
  XtSetArg(args[i], XtNprevious, &paraGain);i++;
  paraNl = XtCreateManagedWidget("numberLine", numberLineWidgetClass,
				 form, args, i);
  XtAddCallback(paraNl, XtNcallback, sympCallback,(caddr_t) &paraGain);

  XtRealizeWidget(shell);
  XtPopup(shell, XtGrabNone);
  XtMapWidget(shell);
}

/*PUBLIC*/
void ReflexesOff()
{
  if (reflexActiveButton)
  getReflexToggle((Widget)reflexActiveButton,(caddr_t)!reflexesOn, (caddr_t)0);
}

/*ARGSUSED*/
/*PUBLIC*/
void ReflexButton(widget, client, call)
Widget widget;
caddr_t client, call;
{
  static Widget titleLabel, hrLabel, cLabel, rLabel, vLabel, 
                form, shell;

  Arg args[20];
  int i, j;
  static Boolean Exists = False;

  if (Exists) return;
  else Exists = True;

  i=0;
  XtSetArg(args[i], XtNallowShellResize, True);i++;
  XtSetArg(args[i], XtNiconName, "Baroreceptor Reflex Control");i++;
#ifdef XAW_BC
  shell = XtCreateApplicationShell("baroreceptor_control"
				   topLevelShellWidgetClass, args, i);
#else
  shell = XtAppCreateShell(NULL,"CVsim",topLevelShellWidgetClass,dpy,args,i);
#endif
  XtAddCallback(shell, XtNdestroyCallback, destroyNotify, (caddr_t)&Exists);
  XtAddEventHandler(shell, ButtonPressMask | ButtonReleaseMask, False, 
		    dummyHandler, (caddr_t)0);
  form = XtCreateManagedWidget("Baroreceptor Reflex", formWidgetClass, 
			       shell, (Arg *)0, 0);
  i=0;
  XtSetArg(args[i], XtNtop, XtChainTop);i++;
  XtSetArg(args[i], XtNbottom, XtChainTop);i++;
  XtSetArg(args[i], XtNleft, XtChainLeft);i++;
  XtSetArg(args[i], XtNright, XtChainLeft);i++;
  XtSetArg(args[i], XtNvertDistance, 8);i++;
  XtSetArg(args[i], XtNresizable, True);i++;
  j = i;
  XtSetArg(args[i], XtNborderWidth, 0);i++;
  titleLabel = XtCreateManagedWidget("BARORECEPTOR REFLEX CONTROL", 
				     labelWidgetClass, form, args, i);
  i=j;
  XtSetArg(args[i], XtNfromHoriz, titleLabel); i++;
  XtSetArg(args[i], XtNborderWidth, 3); i++;
  reflexActiveButton = XtCreateManagedWidget("ReflexesActiveButton", 
				   commandWidgetClass, form, args, i);
  XtAddCallback(reflexActiveButton,XtNcallback, getReflexToggle, (caddr_t)0);
  
  i=j;
  XtSetArg(args[i], XtNfromVert, titleLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 0);i++;
  hrLabel = XtCreateManagedWidget("Heart Rate feedback:", labelWidgetClass,
				  form, args, i);
  i=j;
  XtSetArg(args[i], XtNfromVert, titleLabel);i++;
  XtSetArg(args[i], XtNfromHoriz, titleLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 3);
  hrButton = XtCreateManagedWidget("hrButton", commandWidgetClass,
				   form, args, i);
  XtAddCallback(hrButton, XtNcallback, getLimbToggle, (caddr_t) &hrActive);
  i=j;
  XtSetArg(args[i], XtNfromVert, hrLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 0);i++;
  cLabel = XtCreateManagedWidget("Contractility feedback:", labelWidgetClass,
				 form, args, i);
  i=j;
  XtSetArg(args[i], XtNfromVert, hrLabel);i++;
  XtSetArg(args[i], XtNfromHoriz, titleLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 3);
  cButton = XtCreateManagedWidget("cButton",commandWidgetClass,form,args, i);
  XtAddCallback(cButton, XtNcallback, getLimbToggle, (caddr_t) &cActive);
  i=j;
  XtSetArg(args[i], XtNfromVert, cLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 0);i++;
  rLabel=XtCreateManagedWidget("Art. Resistance feedback:",labelWidgetClass,
			       form, args, i);
  i=j;
  XtSetArg(args[i], XtNfromVert, cLabel);i++;
  XtSetArg(args[i], XtNfromHoriz, rLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 3);
  rButton = XtCreateManagedWidget("rButton",commandWidgetClass,form,args,i);
  XtAddCallback(rButton, XtNcallback, getLimbToggle, (caddr_t) &rActive);
  i=j;
  XtSetArg(args[i], XtNfromVert, rLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 0);i++;
  vLabel = XtCreateManagedWidget("Venous tone feedback:", labelWidgetClass,
				 form, args, i);
  i=j;
  XtSetArg(args[i], XtNfromVert, rLabel);i++;
  XtSetArg(args[i], XtNfromHoriz, rLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 3);
  vButton = XtCreateManagedWidget("vButton",commandWidgetClass,form,args,i);
  XtAddCallback(vButton, XtNcallback, getLimbToggle, (caddr_t) &vActive);

  i=j;
  XtSetArg(args[i], XtNfromVert, vLabel);i++;
  XtSetArg(args[i], XtNborderWidth, 3);
  modButton = XtCreateManagedWidget("Modify Reflex Parameters",
				    commandWidgetClass, form, args, i);
  XtAddCallback(modButton, XtNcallback, modReflexCallback, (caddr_t)0);

  XtRealizeWidget(shell);
  XtPopup(shell, XtGrabNone);
  XtMapWidget(shell);

  getReflexToggle((Widget)reflexActiveButton, (caddr_t)1, (caddr_t)0);
  getLimbToggle(hrButton, (caddr_t)&hrActive, (caddr_t)1);
  getLimbToggle(cButton, (caddr_t)&cActive, (caddr_t)1);
  getLimbToggle(rButton, (caddr_t)&rActive, (caddr_t)1);
  getLimbToggle(vButton, (caddr_t)&vActive, (caddr_t)1);
}

#endif
/*** end of Reflex Interface *********************************************/
