static char MicroGui_id[] = "$Header: /usr/tiburon/unix/gui/tmacs/RCS/MicroGui.cc,v 1.10 1998/03/18 16:11:22 oreilly Exp $";

/*
$Log: MicroGui.cc,v $
Revision 1.10  1998/03/18 16:11:22  oreilly
*** empty log message ***

Revision 1.9  1998/02/23 16:14:03  oreilly
*** empty log message ***

Revision 1.8  1997/11/20 08:21:23  oreilly
*** empty log message ***

Revision 1.7  97/10/03  09:30:51  09:30:51  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.6  97/09/10  08:52:27  08:52:27  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.5  97/08/12  14:48:11  14:48:11  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.4  97/05/30  16:28:37  16:28:37  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.3  97/05/06  16:28:50  16:28:50  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.2  97/05/01  07:45:17  07:45:17  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.1  97/03/20  12:30:08  12:30:08  oreilly (Thomas C. O'Reilly)
Initial revision

*/
#include <stdlib.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/Separator.h>
#include <Xm/Frame.h>
#include <Xm/ToggleB.h>
#include <Vk/VkQuestionDialog.h>
#include <Vk/VkErrorDialog.h>
#include "TiburonApp.h"
#include "IbcCardInfo.h"
#include "gf_5vDm.h"
#include "MicroGui.h"
#include "Micro.h"
#include "thrusterDM.h"
#include "DmErrno.h"
#include "parseUtils.h"
#include "DataRates.h"

#define dprintf if (debug) fprintf


MicroH2OTempHeader::MicroH2OTempHeader(const char *name, Widget parent)
  : AlarmedTableHeader(name, parent, MicroH2OTempColumns)
{
  _columnLabels[NameColumn] = 
    XtVaCreateManagedWidget("microName", xmLabelWidgetClass,
			    _mgr->baseWidget(),
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNleftPosition, 0,
			    NULL);

  _mgr->attach(NameColumn, _columnLabels[NameColumn]);
  
  _columnLabels[TemperatureColumn] = 
    XtVaCreateManagedWidget("temperature", xmLabelWidgetClass, 
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(TemperatureColumn, _columnLabels[TemperatureColumn]);
  
  _columnLabels[HumidityColumn] = 
    XtVaCreateManagedWidget("humidity", xmLabelWidgetClass, 
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(HumidityColumn, _columnLabels[HumidityColumn]);
  
  _columnLabels[HousingWaterColumn] =
    XtVaCreateManagedWidget("housingWater", xmLabelWidgetClass, 
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(HousingWaterColumn, _columnLabels[HousingWaterColumn]);
  
  _columnLabels[JboxWaterColumn] =
    XtVaCreateManagedWidget("jboxWater", xmLabelWidgetClass,
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(JboxWaterColumn, _columnLabels[JboxWaterColumn]);
  
  _mgr->show();
}


MicroH2OTemp::MicroH2OTemp(const char *name, Widget parent)
  : AlarmedTableRow(name, parent, MicroH2OTempColumns)
{
  _temp = NULL;
  _humidity = NULL;
  _housingWater = _jboxWater = NULL;
}


MicroH2OTemp::~MicroH2OTemp()
{
  delete _temp;
  delete _humidity;
  delete _housingWater;
  delete _jboxWater;
}



void MicroH2OTemp::addCallbacks()
{
  if (_temp) 
  {
    _temp->addCallback(AlarmedText::alarmUpdateCallback, this,
		       (VkCallbackMethod )&MicroH2OTemp::alarmUpdate);
  }
  
  if (_humidity)
  {
    _humidity->addCallback(AlarmedText::alarmUpdateCallback, this,
			   (VkCallbackMethod )&MicroH2OTemp::alarmUpdate);
  }
      
  if (_housingWater)
  {
    _housingWater->addCallback(AlarmText::alarmUpdateCallback, this,
			       (VkCallbackMethod )&MicroH2OTemp::alarmUpdate);
  }
  
  if (_jboxWater)
  {
    _jboxWater->addCallback(AlarmText::alarmUpdateCallback, this,
			       (VkCallbackMethod )&MicroH2OTemp::alarmUpdate);
  }
  
}


Priority MicroH2OTemp::priority(int column)
{
  switch (column)
  {
    case TemperatureColumn:
    if (_temp)
      return _temp->priority();
    else
      return NoPriority;
    
    break;
    
    case HumidityColumn:
    if (_humidity)
      return _humidity->priority();
    else
      return NoPriority;

    break;
    
    case HousingWaterColumn:
    if (_housingWater)
      return _housingWater->priority();
    else
      return NoPriority;

    break;

    case JboxWaterColumn:
    if (_jboxWater)
      return _jboxWater->priority();
    else
      return NoPriority;
    
    default:
    return NoPriority;
  }
}


void MicroH2OTemp::alarmUpdate(VkCallbackObject *obj,
			       void *clientData,
			       void *callData)
{
  Boolean debug = False;
  int column = -1;
  
  if (_temp && (VkCallbackObject *)_temp == obj)
  {
    column = TemperatureColumn;
    dprintf(stderr, "callback from _temp\n");
  }
  else if (_humidity && (VkCallbackObject *)_humidity == obj)
  {
    column = HumidityColumn;
    dprintf(stderr, "callback from _humidity\n");
  }
  else if (_housingWater && (VkCallbackObject *)_housingWater == obj)
  {
    column = HousingWaterColumn;
    dprintf(stderr, "callback from _housingWater\n");
  }
  else if (_jboxWater && (VkCallbackObject *)_jboxWater == obj)
  {
    column = JboxWaterColumn;
    dprintf(stderr, "callback from _jboxWater\n");
  }
  
  callCallbacks(alarmUpdateCallback, (void *)column);
}


IbcH2OTemp::IbcH2OTemp(const char *name, Widget parent, Ibc *ibc,
		       int period)
  : MicroH2OTemp(name, parent)
{
  IbcDm *ibcDm = ibc->ibcDm;

  /* Find alarm items */
  SystemAlarms *alarms = ((TiburonApp *)theApplication)->systemAlarms;
  
  char alarmName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(alarmName, (const char *)ibcDm->dmPrefix());
  
  char *alarmNamePtr = alarmName + strlen(alarmName);

  strcpy(alarmNamePtr, HUMIDITY_ALARM_DM);
  Alarm *humidityAlarm;
  if ((humidityAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "DconH2OTemp::DconH2OTemp() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }
  
  strcpy(alarmNamePtr, GF_5V_TEMP_ALARM_DM);
  Alarm *tempAlarm;
  if ((tempAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "DconH2OTemp::DconH2OTemp() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }

  strcpy(alarmNamePtr, HOUSING_WATER_ALARM_DM);  
  Alarm *housingWaterAlarm;
  if ((housingWaterAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "DconH2OTemp::DconH2OTemp() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }

  Widget nameWidget =
    XtVaCreateManagedWidget(name, xmLabelWidgetClass, _row->baseWidget(),
			    NULL);			    

  _row->append(nameWidget);
  
  char format[100];
  
  _temp = 
    new AlarmedInt16Text("temperature", _row->baseWidget(), "%-3.0f C", 
			 ibcDm->gf5vDm->temp, 
			 period, tempAlarm, Dynamic); 

  _row->append(_temp);
  
  _humidity = 
    new AlarmedNat16Text("humidity", _row->baseWidget(), "%-3.0f %%", 
			 ibcDm->humidity, period, humidityAlarm, Dynamic); 

  _row->append(_humidity);
  
  _housingWater = 
    new AlarmText("housingWater", _row->baseWidget(), housingWaterAlarm, "%s");

  _row->append(_housingWater);
  
  // Put in a place-holder label for jbox water alarm
  _jboxWaterLabel = 
    XtVaCreateManagedWidget("notApplicable", xmLabelWidgetClass, 
			    _row->baseWidget(), 
			    NULL);

  _row->append(_jboxWaterLabel);

  _row->show();
}


IbcH2OTemp::~IbcH2OTemp()
{
}


DconH2OTemp::DconH2OTemp(const char *name, Widget parent, Ibc *ibc,
			 int period)
  : IbcH2OTemp(name, parent, ibc, period)
{
  IbcDm *ibcDm = ibc->ibcDm;
  
  /* Find alarm items */
  SystemAlarms *alarms = ((TiburonApp *)theApplication)->systemAlarms;
  
  char alarmName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(alarmName, (const char *)ibcDm->dmPrefix());
  
  char *alarmNamePtr = alarmName + strlen(alarmName);

  strcpy(alarmNamePtr, JBOX_WATER_ALARM_DM);  
  Alarm *alarm;
  if ((alarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "DconH2OTemp::DconH2OTemp() - couldn't find alarm \"%s\"",
	    alarmName);
    
    theErrorDialog->postAndWait(errorBuf);
  }

  // Remove place-holder label
  XtUnmanageChild(_jboxWaterLabel);
  
  _jboxWater = 
    new AlarmText("jboxWater", _row->baseWidget(), alarm, "%s");

  _row->attach(MicroH2OTempColumns - 1, _jboxWater);

  _row->show();
}


DconH2OTemp::~DconH2OTemp()
{
}


MicroGfHeader::MicroGfHeader(const char *name, Widget parent)
  : AlarmedTableHeader(name, parent, MicroGfColumns)
{
  _columnLabels[NameColumn] = 
    XtVaCreateManagedWidget("microName", xmLabelWidgetClass, 
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(NameColumn, _columnLabels[NameColumn]);
  
  _columnLabels[LocalGfColumn] =
    XtVaCreateManagedWidget("localGf", xmLabelWidgetClass, 
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(LocalGfColumn, _columnLabels[LocalGfColumn]);
  
  _columnLabels[ExternGfColumn] = 
    XtVaCreateManagedWidget("externGf", xmLabelWidgetClass, 
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(ExternGfColumn, _columnLabels[ExternGfColumn]);
  
  _mgr->show();
}


MicroGf::MicroGf(const char *name, Widget parent)
  : AlarmedTableRow(name, parent, MicroGfColumns)
{
  _localGf = _externGf = NULL;
}


Priority MicroGf::priority(int column)
{
  switch (column)
  {
    case LocalGfColumn:
    if (_localGf)
      return _localGf->priority();
    else
      return NoPriority;
    
    break;
    
    case ExternGfColumn:
    if (_externGf)
      return _externGf->priority();
    else
      return NoPriority;

    break;
    
    default:
    return NoPriority;
  }
}


MicroGf::~MicroGf()
{
  delete _localGf;
  delete _externGf;
}


void MicroGf::addCallbacks()
{
  if (_localGf) 
  {
    _localGf->addCallback(AlarmedText::alarmUpdateCallback, this,
			  (VkCallbackMethod )&MicroGf::alarmUpdate);
  }

  if (_externGf) 
  {
    _externGf->addCallback(AlarmedText::alarmUpdateCallback, this,
			   (VkCallbackMethod )&MicroGf::alarmUpdate);
  }
}



void MicroGf::alarmUpdate(VkCallbackObject *obj,
			  void *clientData,
			  void *callData)
{
  Boolean debug = False;
  int column = -1;
  
  if (_localGf && (VkCallbackObject *)_localGf == obj)
  {
    column = LocalGfColumn;
    dprintf(stderr, "callback from _localGf\n");
  }
  else if (_externGf && (VkCallbackObject *)_externGf == obj)
  {
    column = ExternGfColumn;
    dprintf(stderr, "callback from _externGf\n");
  }
  
  callCallbacks(alarmUpdateCallback, (void *)column);
}


MicroGf5vHeader::MicroGf5vHeader(const char *name, Widget parent)
  : AlarmedTableHeader(name, parent, MicroGf5vColumns)
{
  _columnLabels[NameColumn] = 
    XtVaCreateManagedWidget("microName", xmLabelWidgetClass, 
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(NameColumn, _columnLabels[NameColumn]);

  int column = Chan0Column;
  
  for (int chan = 0; chan < N_GF5V_CHANNELS; chan++)
  {
    char widgetName[100];
    sprintf(widgetName, "chan%d", chan);
    
    _columnLabels[column] =
      XtVaCreateManagedWidget(widgetName, xmLabelWidgetClass, 
			      _mgr->baseWidget(),
			      NULL);

    _mgr->attach(column, _columnLabels[column]);
    column++;
  }

  _columnLabels[OffsetColumn] = 
    XtVaCreateManagedWidget("offset", xmLabelWidgetClass, _mgr->baseWidget(),
			    NULL);

  _mgr->attach(OffsetColumn, _columnLabels[OffsetColumn]);
  
  _columnLabels[VicorVoltageColumn] = 
    XtVaCreateManagedWidget("vicorVolt", xmLabelWidgetClass, 
			    _mgr->baseWidget(),
			    NULL);

  _mgr->attach(VicorVoltageColumn, _columnLabels[VicorVoltageColumn]);
  
  _mgr->show();
}


MicroGf5v::MicroGf5v(const char *name, Widget parent)
  : AlarmedTableRow(name, parent, MicroGf5vColumns)
{
  for (int chan = 0; chan < N_GF5V_CHANNELS; chan++)
    _current[chan] = NULL;
  
  _offset = NULL;
  _vicorVoltage = NULL;
}


MicroGf5v::~MicroGf5v()
{
  for (int chan = 0; chan < N_GF5V_CHANNELS; chan++)
    delete _current[chan];
  
  delete _offset;
  delete _vicorVoltage;
}


Priority MicroGf5v::priority(int column)
{
  switch (column)
  {
    case Chan0Column:
    if (_current[0])
      return _current[0]->priority();
    else
      return NoPriority;

    break;

    case Chan1Column:
    if (_current[1])
      return _current[1]->priority();
    else
      return NoPriority;

    break;    

    case Chan2Column:
    if (_current[2])
      return _current[2]->priority();
    else
      return NoPriority;

    break;

    case Chan3Column:
    if (_current[3])
      return _current[3]->priority();
    else
      return NoPriority;

    break;

    case OffsetColumn:
    if (_offset)
      return _offset->priority();
    else
      return NoPriority;
    break;

    case VicorVoltageColumn:
    if (_vicorVoltage)
      return _vicorVoltage->priority();
    else
      return NoPriority;
    
    break;

    default:
    return NoPriority;
  }
}


void MicroGf5v::addCallbacks()
{
  for (int chan = 0; chan < N_GF5V_CHANNELS; chan++)
  {
    if (_current[chan])
      _current[chan]->addCallback(AlarmedText::alarmUpdateCallback, this,
				  (VkCallbackMethod )&MicroGf5v::alarmUpdate);
  }      

  if (_offset)
    _offset->addCallback(AlarmedText::alarmUpdateCallback, this,
			 (VkCallbackMethod )&MicroGf5v::alarmUpdate);

  if (_vicorVoltage)
    _vicorVoltage->addCallback(AlarmedText::alarmUpdateCallback, this,
			       (VkCallbackMethod )&MicroGf5v::alarmUpdate);
  
}


void MicroGf5v::alarmUpdate(VkCallbackObject *obj,
			    void *clientData,
			    void *callData)
{
  Boolean debug = False;

  int column = -1;
  Boolean found = False;
  
  for (int chan = 0; chan < N_GF5V_CHANNELS; chan++)
  {
    if (_current[chan] && (VkCallbackObject *)_current[chan] == obj)
    {
      dprintf(stderr, "callback from _current[%d]\n", chan);
      found = True;
      column = Chan0Column + chan;
      break;
    }
  }
 
  if (!found)
  {
    if (_offset && (VkCallbackObject *)_offset == obj)
    {
      column = OffsetColumn;
      dprintf(stderr, "callback from _offset\n");
    }
    else if (_vicorVoltage && (VkCallbackObject *)_vicorVoltage == obj)
    {
      column = VicorVoltageColumn;
      dprintf(stderr, "callback from _vicorVoltage\n");
    }
  }
  
  callCallbacks(alarmUpdateCallback, (void *)column);
}


IbcGf::IbcGf(const char *name, Widget parent, Ibc *ibc, int period)
  : MicroGf5v(name, parent)
{
  IbcDm *ibcDm = ibc->ibcDm;

  Pixel background;
  XtVaGetValues(AlarmedTableRow::_baseWidget, XmNbackground, &background, 
		NULL);

  /* Find alarm items */
  SystemAlarms *alarms = ((TiburonApp *)theApplication)->systemAlarms;
  
  char alarmName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(alarmName, (const char *)ibcDm->dmPrefix());
  
  char *alarmNamePtr = alarmName + strlen(alarmName);

  strcpy(alarmNamePtr, GF_5V_VICOR_VOLTAGE_ALARM_DM);
  Alarm *vicorVoltAlarm;
  if ((vicorVoltAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "IbcGf::IbcGf() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }

  XtVaSetValues(_row->baseWidget(),
		XmNleftAttachment, XmATTACH_POSITION,
		XmNleftPosition, 0,
		XmNtopAttachment, XmATTACH_FORM,
		XmNrightAttachment, XmATTACH_FORM,
		NULL);
  
  Widget nameWidget =
    XtVaCreateManagedWidget(name, xmLabelWidgetClass, _row->baseWidget(),
			    NULL);			    

  _row->append(nameWidget);
  
  char widgetName[100];

  Widget channelWidgets[N_GF5V_CHANNELS];
  
  for (int chan = 0; chan < N_GF5V_CHANNELS; chan++)
  {
    strcpy(alarmNamePtr, Gf5vDm::currentAlarmDmName(chan));

    Alarm *alarm;
    if ((alarm = alarms->find(alarmName)) == NULL)
    {
      sprintf(errorBuf,
	      "IbcGf::IbcGf() - couldn't find alarm \"%s\"",
	      alarmName);

      theErrorDialog->postAndWait(errorBuf);
    }

    sprintf(widgetName, "chan%dCurrent", chan);
    
    _current[chan] = 
      new AlarmedInt16Text(widgetName, _row->baseWidget(), "%-3.0f", 
			   ibcDm->gf5vDm->current[chan],
			   period, alarm, Dynamic);

    _current[chan]->addCallback(AlarmedText::alarmUpdateCallback, this,
				(VkCallbackMethod )
				&MicroGf5v::alarmUpdate);

    XtVaSetValues(_current[chan]->baseWidget(),
		  XmNborderWidth, SampledChanBorderWidth,
		  XmNborderColor, background,
		  NULL);
    
    _row->append(_current[chan]);

    channelWidgets[chan] = _current[chan]->baseWidget();
  }

  _scanner = new GfScanner("scanner", _baseWidget,
			   ibcDm->gf5vDm->sampledChannel,
			   channelWidgets, period);
  _offset = 
    new AlarmedInt16Text("offset", _row->baseWidget(), "%-3.0f", 
			 ibcDm->gf5vDm->offsetCurrent,
			 period, NULL, Dynamic); 

  _offset->addCallback(AlarmedText::alarmUpdateCallback, this,
		       (VkCallbackMethod )&MicroGf5v::alarmUpdate);

  _row->append(_offset);
  
  _vicorVoltage = 
    new AlarmedInt16Text("vicorVoltage", _row->baseWidget(), "%-3.0f", 
			 ibcDm->gf5vDm->vicorVoltage,
			 period, vicorVoltAlarm, Dynamic); 

  _vicorVoltage->addCallback(AlarmedText::alarmUpdateCallback, this,
			     (VkCallbackMethod )&MicroGf5v::alarmUpdate);

  _row->append(_vicorVoltage);
  
  _row->show();
}


IbcGf::~IbcGf()
{
}




XtResource Gf5vGui::_resources[] = 
{
  {  
    "sampledChanBorderColor",
    "SampledChanBorderColor",
    XtRPixel,
    sizeof(Pixel),
    XtOffset(Gf5vGui *, _sampledChanBorderColor),
    XmRString, "white"
  },

  {  
    "sampledChanBorderWidth",
    "SampledChanBorderWidth",
    XmRDimension,
    sizeof(Dimension),
    XtOffset(Gf5vGui *, _sampledChanBorderWidth),
    XmRString, "1"
  }
};


Gf5vGui::Gf5vGui(const char *name, Widget parent, Gf5vDm *gf5vDm, int period,
		 Boolean showCapacitorData)
  : DmGuiObject(name, parent)
{
  int chan;
  
  for (chan = 0; chan < N_GF5V_CHANNELS; chan++)
    _current[chan] = 0;

  _temp = 0;
  _offset = 0;
  _vicorVolt = 0;
  _selfTest = 0;
  _capacitance = 0;
  _capacitorCurrent = 0;
  
  _baseWidget = 
    XtVaCreateWidget(name, xmRowColumnWidgetClass, parent, 
		     XmNorientation, XmVERTICAL, NULL);

  installDestroyHandler();

  getResources(_resources, XtNumber(_resources));

  XtVaGetValues(_baseWidget, XmNbackground, &_background, NULL);
  
  _gf5vDm = gf5vDm;
  
  /* Find alarm items */
  SystemAlarms *alarms = ((TiburonApp *)theApplication)->systemAlarms;
  
  char alarmName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(alarmName, (const char *)gf5vDm->dmPrefix());
  
  char *alarmNamePtr = alarmName + strlen(alarmName);

  strcpy(alarmNamePtr, GF_5V_TEMP_ALARM_DM);
  Alarm *tempAlarm;
  if ((tempAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "Gf5vGui::Gf5vGui() - couldn't find alarm \"%s\"",
	    alarmName);

    stopConsume();
    theErrorDialog->postAndWait(errorBuf);
    startConsume();
  }

  strcpy(alarmNamePtr, GF_5V_VICOR_VOLTAGE_ALARM_DM);
  Alarm *vicorVoltAlarm;
  if ((vicorVoltAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "Gf5vGui::Gf5vGui() - couldn't find alarm \"%s\"",
	    alarmName);

    stopConsume();
    theErrorDialog->postAndWait(errorBuf);
    startConsume();
  }

  _selfTest = new Gf5vSelfTest("selfTest", _baseWidget, _gf5vDm);
  
  _selfTest->show();
  
  Widget label;
  
  char widgetName[100];

  static char *itemNames[] = 
  {
    "temp", "currentOffset", "vicorVolt", NULL
  };
  
  TableRowForm *mgr;
  
  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("tempLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _temp = 
    new AlarmedInt16Text("temp", mgr->baseWidget(), "%-3.0f C", gf5vDm->temp, 
			 period, tempAlarm, Dynamic, 1., 
			 XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_temp);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);
  
  label = 
    XtVaCreateManagedWidget("currentOffsetLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), 
			    NULL);
  
  _offset = 
    new AlarmedInt16Text("offset", mgr->baseWidget(), "%-3.0f", 
			 gf5vDm->offsetCurrent,
			 period, NULL, Dynamic, 1., 
			 XmALIGNMENT_BEGINNING); 

  mgr->append(label);
  mgr->append(_offset);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("vicorVoltLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), 
			    NULL);

  _vicorVolt = 
    new AlarmedInt16Text("vicorVolt", mgr->baseWidget(), "%-3.0f", 
			 gf5vDm->vicorVoltage, 
			 period, vicorVoltAlarm, Dynamic, 1., 
			 XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_vicorVolt);
  mgr->show();

  for (chan = 0; chan < N_GF5V_CHANNELS; chan++)
  {
    mgr = new TableRowForm("mgr", _baseWidget, 2);

    sprintf(widgetName, "chan%dCurrentLabel", chan);
    
    label = 
      XtVaCreateManagedWidget(widgetName, xmLabelWidgetClass, 
			      mgr->baseWidget(), NULL);

    strcpy(alarmNamePtr, Gf5vDm::currentAlarmDmName(chan));

    Alarm *alarm;
    if ((alarm = alarms->find(alarmName)) == NULL)
    {
      sprintf(errorBuf,
	      "Gf5vGui::Gf5vGui() - couldn't find alarm \"%s\"",
	      alarmName);

    stopConsume();
    theErrorDialog->postAndWait(errorBuf);
    startConsume();
    }
    
    sprintf(widgetName, "chan%dCurrent", chan);

    _current[chan] = 
      new AlarmedInt16Text(widgetName, mgr->baseWidget(), "%-3.0f", 
			   gf5vDm->current[chan], 
			   period, alarm, Dynamic, 1., 
			   XmALIGNMENT_BEGINNING);

    XtVaSetValues(_current[chan]->baseWidget(),
		  XmNborderWidth, _sampledChanBorderWidth,
		  XmNborderColor, _background,
		  NULL);

    mgr->append(label);
    mgr->append(_current[chan]);
    _current[chan]->show();
    mgr->show();
  }

  for (chan = 0; chan < N_GF5V_CHANNELS; chan++)
  { 
    mgr = new TableRowForm("mgr", _baseWidget, 2);

    sprintf(widgetName, "chan%dChargeTimeLabel", chan);
    
    label = 
      XtVaCreateManagedWidget(widgetName, xmLabelWidgetClass, 
			      mgr->baseWidget(), NULL);

    sprintf(widgetName, "chan%dChargeTime", chan);

    _chargeTime[chan] = new TextField(widgetName, mgr->baseWidget());
    _chargeTime[chan]->setColumns(5);
    _chargeTime[chan]->addCallback(TextField::acceptCallback, this,
				   (VkCallbackMethod )
				   &Gf5vGui::writeChargeTime);
    mgr->append(label);
    mgr->append(_chargeTime[chan]);
    _chargeTime[chan]->show();
    mgr->show();
  }

  if (showCapacitorData)
  {
    mgr = new TableRowForm("mgr", _baseWidget, 2);

    label = 
      XtVaCreateManagedWidget("capacitanceLabel", xmLabelWidgetClass, 
			      mgr->baseWidget(),
			      NULL);

    _capacitance = 
      new AlarmedNat16Text("capacitance", mgr->baseWidget(), "%-4.0f", 
			   gf5vDm->busCapacitance,
			   period, NULL, Dynamic, 1., 
			   XmALIGNMENT_BEGINNING);

    mgr->append(label);
    mgr->append(_capacitance);
    mgr->show();

    mgr = new TableRowForm("mgr", _baseWidget, 2);
    
    label = 
      XtVaCreateManagedWidget("capacitorCurrentLabel", xmLabelWidgetClass, 
			      mgr->baseWidget(),
			      NULL);

    _capacitorCurrent = 
      new AlarmedInt16Text("capacitorCurrent", mgr->baseWidget(), "%-4.0f", 
			   gf5vDm->busCapacitorCurrent,
			   period, NULL, Dynamic, 1., 
			   XmALIGNMENT_BEGINNING);

    mgr->append(label);
    mgr->append(_capacitorCurrent);
    mgr->show();
  }
  _showCapacitorData = showCapacitorData;
  
  for (chan = 0; chan < N_GF5V_CHANNELS; chan++)
  {
    if (addDmObject(gf5vDm->chargeTime[chan], DmConsumeFlag | DmProvideFlag) 
	== -1)
      return;

    _prevChargeTime[chan] = -1;
  }

  if (addDmObject(gf5vDm->sampledChannel, DmConsumeFlag) == -1)
    return;

  _prevSampledChannelMask = -1;

  _scanEnableButton =
    XtVaCreateManagedWidget("scanEnableButton", xmToggleButtonWidgetClass, 
			    _baseWidget,
			    NULL);

  XtAddCallback(_scanEnableButton, XmNvalueChangedCallback,
		&Gf5vGui::scanEnableCallback,
		(XtPointer )this);

  if (addDmObject(gf5vDm->scanEnabled, DmConsumeFlag | DmProvideFlag) == -1)
    return;

  _prevScanEnabled = FALSE;
  
  if (setConsumePeriod(Gf5vCurrentPeriod) == -1)
    return;

  updateGui();
}


Gf5vGui::~Gf5vGui()
{
  for (int chan = 0; chan < N_GF5V_CHANNELS; chan++)
    delete _current[chan];
  
  delete _temp;
  delete _offset;
  delete _vicorVolt;
  delete _selfTest;
 
  if (_showCapacitorData)
  {
    delete _capacitance;
    delete _capacitorCurrent;
  }
}


void Gf5vGui::updateGui(DM_Item handle)
{
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  Int32 chargeTime;
  char buf[100];

  Int16 sampledChannelMask;
  int chan;

  if ((errno = _gf5vDm->sampledChannel->read(&sampledChannelMask, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "Gf5vGui::updateGui()", errorBuf);
    setError(errorBuf);
    return;
  }
  else
  {
    // Draw a box around sampled current
    if (sampledChannelMask != _prevSampledChannelMask)
    {
      for (chan = 0; chan < N_GF5V_CHANNELS; chan++)
      {
	if (sampledChannelMask == (01 << chan))
	{
	  XtVaSetValues(_current[chan]->baseWidget(),
			XmNborderColor, _sampledChanBorderColor,
			NULL);
	}
	else
	{
	  XtVaSetValues(_current[chan]->baseWidget(),
			XmNborderColor, _background,
			NULL);
	}
      }
      _prevSampledChannelMask = sampledChannelMask;
    }
  }
  
  for (chan = 0; chan < N_GF5V_CHANNELS; chan++)
  {
    if ((errno = _gf5vDm->chargeTime[chan]->read(&chargeTime, &t)) != SUCCESS)
    {
      sprintDmError(errno, "Gf5vGui::updateGui()", errorBuf);
      setError(errorBuf);
      return;
    }
    else
    {
      if (chargeTime != _prevChargeTime[chan])
      {
	sprintf(buf, "%.0f", chargeTime / 1000.);
	_chargeTime[chan]->set(buf);
	_prevChargeTime[chan] = chargeTime;
      }
    }
  }

  MBool scanEnabled;
  
  if ((errno = _gf5vDm->scanEnabled->read(&scanEnabled, &t)) != SUCCESS)
  {
    sprintDmError(errno, "Gf5vGui::updateGui(), reading scanEnabled", 
		  errorBuf);

    setError(errorBuf);
    return;
  }
  else if (scanEnabled != _prevScanEnabled)
  {
    if (scanEnabled)
      XtVaSetValues(_scanEnableButton, XmNset, True, NULL);
    else
      XtVaSetValues(_scanEnableButton, XmNset, False, NULL);

    _prevScanEnabled = scanEnabled;
  }
}


void Gf5vGui::toggleScanEnable(Boolean enable)
{
  MBool set;
  
  if (enable)
    set = TRUE;
  else
    set = FALSE;
  
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;
  
  Errno errno;
  char errorBuf[errorMsgSize];
  
  if ((errno = _gf5vDm->scanEnabled->write(set, &t)) != SUCCESS)
  {
    sprintDmError(errno, "Gf5vGui::updateGui(), reading scanEnabled", 
		  errorBuf);

    theErrorDialog->postAndWait(errorBuf);
  }
}



void Gf5vGui::writeChargeTime(VkCallbackObject *obj,
			      void *clientData,
			      void *callData)
{
  MBool debug = FALSE;

  Boolean found = False;
  int chan;
  
  for (chan = 0; chan < N_GF5V_CHANNELS; chan++)
  {
    if (obj == _chargeTime[chan])
    {
      found = True;
      break;
    }
  }

  if (!found)
    return;

  char errorBuf[512];
  const char *ptr = _chargeTime[chan]->get();
  if (!isFloat((char *)ptr))
  {
    sprintf(errorBuf, 
	    "\"%s\" - invalid charge time. Must be floating point number.",
	    ptr);
    
    theErrorDialog->postAndWait(errorBuf);
    return;
  }

  Int32 chargeTime = atof(ptr) * 1000;
  
  Errno errno;
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;
  if ((errno = _gf5vDm->chargeTime[chan]->write(chargeTime, &t)) != SUCCESS)
  {
    sprintDmError(errno, "Gf5vGui::writeChargeTime()", errorBuf);
    setError(errorBuf);
    theErrorDialog->postAndWait(errorBuf);
    return;
  }
}


void Gf5vGui::scanEnableCallback(Widget w,
				 XtPointer clientData,
				 XtPointer callData)
{
  Boolean debug = ((TiburonApp *)theApplication)->debug();
  
  dprintf(stderr, "Gf5vGui::scanEnableCallback()\n");
  Gf5vGui *obj = (Gf5vGui *)clientData;
  Boolean set;
  XtVaGetValues(obj->_scanEnableButton, XmNset, &set, NULL);

  obj->toggleScanEnable(set);
}


MicroGui::MicroGui(const char *name, Widget parent, Micro *micro)
 : DmGuiObject(name, parent)
{
  _ramTestStatus = 0;
  _resetDetector = 0;
  _softwareRevDetector = 0;
  _idDetector = 0;
  _serialNoDetector = 0;

  _baseWidget = XtVaCreateWidget(name, xmRowColumnWidgetClass, parent, 
				 XmNorientation, XmVERTICAL,
				 NULL);
  installDestroyHandler();

  _resetDetector = _softwareRevDetector = _idDetector 
    = _serialNoDetector = NULL;
  
  _micro = micro;
  
  SystemAlarms *alarms = ((TiburonApp *)theApplication)->systemAlarms;

  char alarmName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(alarmName, (const char *)_micro->microDm->dmPrefix());
  
  char *alarmNamePtr = alarmName + strlen(alarmName);

  strcpy(alarmNamePtr, RAM_TEST_STATUS_DM);
  Alarm *ramTestStatusAlarm;
  if ((ramTestStatusAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "MicroGui::MicroGui() - couldn't find alarm \"%s\"",
	    alarmName);

    stopConsume();
    theErrorDialog->postAndWait(errorBuf);
    startConsume();
  }
  
  char buf[100];
  Widget label;
  
  TableRowForm *mgr;

  mgr = new TableRowForm("mgr", _baseWidget, 2);
  
  label = XtVaCreateManagedWidget("microIdLabel", xmLabelWidgetClass, 
				  mgr->baseWidget(),
				  NULL);

  _id = 
    XtVaCreateManagedWidget("id", xmLabelWidgetClass, mgr->baseWidget(), NULL);

  mgr->append(label);
  mgr->append(_id);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("softwareRevLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _softwareRev = 
    XtVaCreateManagedWidget("softwareRev", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  mgr->append(label);
  mgr->append(_softwareRev);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("microRamTestStatusLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);  

  _ramTestStatus = 
    new AlarmText("ramTestStatus", mgr->baseWidget(), 
		  ramTestStatusAlarm, "%s");

  mgr->append(label);
  mgr->append(_ramTestStatus);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("microSerialNoLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  

  _microSerialNo = XtVaCreateManagedWidget("microSerialNo", xmLabelWidgetClass,
					   mgr->baseWidget(),
					   NULL);
  
  mgr->append(label);
  mgr->append(_microSerialNo);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  Widget resetButton =
    XtVaCreateManagedWidget("microResetButton", xmPushButtonWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  
  XtAddCallback(resetButton, XmNactivateCallback,
		&MicroGui::resetCallback, (XtPointer )this);
  
  mgr->append(resetButton);
  mgr->show();

  XtVaCreateManagedWidget("separator", 
			  xmSeparatorWidgetClass, _baseWidget,
			  NULL);

  _resetDetector = new DmInputDetector("resetDetector", _baseWidget,
				       micro->microDm->resetEvent, this);

  _softwareRevDetector = new DmInputDetector("softwareRevDetector",
					     _baseWidget,
					     micro->microDm->softwareRev,
					     this);

  _idDetector = new DmInputDetector("idDetector", _baseWidget,
				    micro->microDm->id, this);

  _serialNoDetector = new DmInputDetector("serialNoDetector", _baseWidget,
					  micro->microDm->microSerialNo, 
					  this);
  
  if (addDmObject(micro->microDm->resetCmd, DmProvideFlag) == -1)
    return;

  updateFromPeer(_resetDetector, NULL);
  updateFromPeer(_softwareRevDetector, NULL);
  updateFromPeer(_idDetector, NULL);
  updateFromPeer(_serialNoDetector, NULL);

}


MicroGui::~MicroGui()
{
  delete _ramTestStatus;
  delete _resetDetector;
  delete _softwareRevDetector;
  delete _idDetector;
  delete _serialNoDetector;
}


void MicroGui::updateFromPeer(DmGuiObject *peer, XtPointer clientData)
{
  Boolean debug = False; 

  XmString xmstr;
  DM_Time t;
  char str[512];
  Errno errno;
  char errorBuf[errorMsgSize];

  dprintf(stderr, "MicroGui::updateGui() - read software rev\n");
  
  if ((errno = _micro->microDm->softwareRev->read(str, &t)) != SUCCESS)
  {
    sprintDmError(errno, "MicroGui::updateFromPeer(), reading softwareRev", 
		  errorBuf);

    setError(errorBuf);
  }
  else
  {
    xmstr = XmStringCreateSimple(str);
    XtVaSetValues(_softwareRev, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);
  }
  
  dprintf(stderr, "MicroGui::updateFromPeer() - read id\n");

  if ((errno = _micro->microDm->id->read(str, &t)) != SUCCESS)
  {
    sprintDmError(errno, "MicroGui::updateFromPeer(), reading id", 
		  errorBuf);

    setError(errorBuf);
  }
  else
  {
    xmstr = XmStringCreateSimple(str);
    XtVaSetValues(_id, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);
  }
  
  dprintf(stderr, "MicroGui::updateFromPeer() - read serial no.\n");

  if ((errno = _micro->microDm->microSerialNo->read(str, &t)) != SUCCESS)
  {
    char buf[512];
    
    sprintf(buf, 
	    "MicroGui::updateFromPeer() (object \"%s\"), reading microSerialNo", 
	    name());
    
    sprintDmError(errno, buf, errorBuf);

    setError(errorBuf);
  }
  else
  {
    xmstr = XmStringCreateSimple(str);
    XtVaSetValues(_microSerialNo, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);
  }

  dprintf(stderr, "MicroGui::updateFromPeer() - done\n");
}


void MicroGui::writeReset()
{
  DM_Time t;
  static struct timezone tz = 
  {
    0, 0
  };
  
  gettimeofday(&t, &tz);
  Errno errno;
  char errorBuf[errorMsgSize];
  
  if ((errno = _micro->microDm->resetCmd->write(&t)) != SUCCESS)
  {
    sprintDmError(errno, "MicroGui::writeReset()",  errorBuf);
    setError(errorBuf);
    fprintf(stderr, errorBuf);
  }
}


void MicroGui::resetCallback(Widget w,
			     XtPointer clientData, XtPointer callData)
{
  MicroGui *obj = (MicroGui *)clientData;
  obj->writeReset();
}


void MicroGui::writeValue(VkCallbackObject *obj,
			  void *clientData,
			  void *callData)
{
  MBool debug = FALSE;

  dprintf(stderr, "MicroGui::writeValue()\n");
  int value = (int )clientData;
  dprintf(stderr, "MicroGui::writeValues(), clientData = %d\n", value);
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;
  
  fprintf(stderr, "MicroGui::writeValues() - unknown object\n");
}


IbcGui::IbcGui(const char *name, Widget parent, Ibc *ibc, int period)
  : MicroGui(name, parent, ibc)
{
  _humidity = 0;
  _housingWater = 0;
  _jboxWater = 0;
  _cardError = 0;
  _gf5vGui = 0;

  Boolean debug = False;

  // Not done building yet, so stop any consumers
  stopConsume();
  
  if (error())
    return;
  
  _ibc = ibc;

  /* Find alarm items */
  SystemAlarms *alarms = ((TiburonApp *)theApplication)->systemAlarms;
  
  char alarmName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(alarmName, (const char *)_ibc->ibcDm->dmPrefix());
  
  char *alarmNamePtr = alarmName + strlen(alarmName);

  strcpy(alarmNamePtr, HUMIDITY_ALARM_DM);
  Alarm *humidityAlarm;
  if ((humidityAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "IbcGui::IbcGui() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }
  
  strcpy(alarmNamePtr, HOUSING_WATER_ALARM_DM);  
  Alarm *housingWaterAlarm;
  if ((housingWaterAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "IbcGui::IbcGui() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }

  strcpy(alarmNamePtr, JBOX_WATER_ALARM_DM);  
  Alarm *jboxWaterAlarm;
  
  if ((jboxWaterAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "IbcGui::IbcGui() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }

  strcpy(alarmNamePtr, IBC_CARD_ERROR_DM);  
  Alarm *cardAlarm;
  if ((cardAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "IbcGui::IbcGui() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }
  
  Widget label;
  Widget form;
  
  form = 
    XtVaCreateWidget("form", xmFormWidgetClass, _baseWidget, NULL);

  label = 
    XtVaCreateManagedWidget("cardConfigLabel", xmLabelWidgetClass, form,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_FORM,
			    NULL);

  _cardConfig = 
    XtVaCreateManagedWidget("cardConfig", xmLabelWidgetClass, form,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, label,
			    NULL);

  XtManageChild(form);
  
  TableRowForm *mgr;
  
  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("cardErrorLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _cardError = new DynamicLabel("cardError", mgr->baseWidget());
 
  mgr->append(label);
  mgr->append(_cardError);
  _cardError->show();
  mgr->show();


  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("housingWaterLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), 
			    NULL);

  _housingWater = 
    new AlarmText("housingWater", mgr->baseWidget(), housingWaterAlarm, "%s");

  mgr->append(label);
  mgr->append(_housingWater);
  mgr->show();
  
  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("jboxWaterLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), 
			    NULL);

  _jboxWater = 
    new AlarmText("jboxWater", mgr->baseWidget(), jboxWaterAlarm, "%s");

  mgr->append(label);
  mgr->append(_jboxWater);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("humidityLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _humidity = 
    new AlarmedNat16Text("humidity", mgr->baseWidget(), "%-3.0f %%",
			 _ibc->ibcDm->humidity, period, humidityAlarm,
			 Dynamic, 1., XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_humidity);
  mgr->show();

  Widget frame = 
    XtVaCreateManagedWidget("frame", xmFrameWidgetClass, _baseWidget,
			    NULL);
  
  Boolean showCapacitorData = True;  // TEST
  
  _gf5vGui = new Gf5vGui("gf5vGui", frame, _ibc->ibcDm->gf5vDm,
			 period, showCapacitorData);
  
  if (_gf5vGui->error())
  {
    _gf5vGui->errorMsg(errorBuf);
    setError(errorBuf);
  }

  _gf5vGui->show();

  if (addDmObject(_ibc->ibcDm->cardConfig, DmConsumeFlag) == -1)
    return;

  if (addDmObject(_ibc->ibcDm->cardError, DmConsumeFlag) == -1)
    return;

  if (setConsumePeriod(Aperiodic) == -1)
    return;

  updateGui();
}


IbcGui::~IbcGui()
{
  delete _humidity;
  delete _housingWater;
  delete _jboxWater;
  delete _cardError;
  delete _gf5vGui;
}


void IbcGui::updateGui(DM_Item handle)
{
  Boolean debug = False;
  
  dprintf(stderr, "IbcGui::updateGui()\n");

  XmString xmstr;
  char buf[512];
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];

  IbcCardConfig config;
  
  if ((errno = _ibc->ibcDm->cardConfig->read(&config, &t)) != SUCCESS)
  {
    sprintDmError(errno, "IbcGui::updateGui(), reading cardError", 
		  errorBuf);

    setError(errorBuf);
  }
  else
  {
    // List names of cards
    char *ptr = buf;
    *ptr = '\0';
    for (int card = 0; card < config.numCards; card++)
    {
      if (card > 0)
      {
	strcat(ptr, ", ");
	if (!(card % 3))
	  strcat(ptr, "\n");
      
	ptr += strlen(ptr);
      } 

      IbcCardInfo::sprint(config.address[card], ptr);
      ptr += strlen(ptr);
    }
  
    xmstr = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
    XtVaSetValues(_cardConfig, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);
  }
  
  Nat16 value;
  
  if ((errno = _ibc->ibcDm->cardError->read(&value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "IbcGui::updateGui(), reading cardError", 
		  errorBuf);

    setError(errorBuf);
  }
  else
  {
    if (value != 0)
      sprintf(buf, "0X%x", value); 
    else
      sprintf(buf, "OK");
  
    _cardError->setText(buf);
  }
}


DconGui::DconGui(const char *name, Widget parent, Dcon *dcon, int period)
  : IbcGui(name, parent, dcon, period)
{
  if (error())
    return;
  
  _dcon = dcon;
}


DconGui::~DconGui()
{
}


void DconGui::updateGui(DM_Item handle)
{
  IbcGui::updateGui();
}



GfScanner::GfScanner(const char *name, Widget parent, 
		     DmInt16Object *dmSampledChannel,
		     Widget *channelWidgets,
		     int period)
  : DmGuiObject(name, parent)
{
  // Since this has no actual GUI, just make a tiny, unmanaged manager 
  // Widget 
  _baseWidget = XtVaCreateWidget(name, xmRowColumnWidgetClass, parent,
				 XmNwidth, 0, XmNheight, 0, NULL);
  installDestroyHandler();

  for (int chan = 0; chan < N_GF5V_CHANNELS; chan++)
    _channelWidgets[chan] = channelWidgets[chan];
  
  XtVaGetValues(_baseWidget, XmNbackground, &_background, 
		NULL);

  int screenNum = DefaultScreen(theApplication->display());
  _sampledChanColor = WhitePixel(theApplication->display(), screenNum);

  _prevSampledChannelMask = -1;

  _dmSampledChannel = dmSampledChannel;

  if (addDmObject(_dmSampledChannel, DmConsumeFlag) == -1)
    return;
  
  if (setConsumePeriod(Gf5vCurrentPeriod) == -1)
    return;

  updateGui();
}


GfScanner::~GfScanner()
{
}


void GfScanner::updateGui(DM_Item handle)
{
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  Int32 chargeTime;
  char buf[100];

  Int16 sampledChannelMask;
  int chan;

  if ((errno = _dmSampledChannel->read(&sampledChannelMask, &t)) != SUCCESS)
  {
    sprintDmError(errno, "GfScanner::updateGui()", errorBuf);
    setError(errorBuf);
    return;
  }
  else
  {
    // Draw a box around sampled current
    if (sampledChannelMask != _prevSampledChannelMask)
    {
      for (chan = 0; chan < N_GF5V_CHANNELS; chan++)
      {
	if (sampledChannelMask == (01 << chan))
	{
	  XtVaSetValues(_channelWidgets[chan],
			XmNborderColor, _sampledChanColor,
			NULL);
	}
	else
	{
	  XtVaSetValues(_channelWidgets[chan],
			XmNborderColor, _background,
			NULL);
	}
      }
      _prevSampledChannelMask = sampledChannelMask;
    }
  }
}
