/************************************************************************/
/* Copyright 1992 MBARI							*/
/************************************************************************/
/* $Header: /usr/tiburon/unix/gui/proto/RCS/vehiclecall.c,v 1.1 1998/01/28 16:17:12 oreilly Exp $		*/
/* Summary  : Callbacks for Vehicle Screen of ROV User Interface	*/
/* Filename : vehiclecall.c						*/
/* Author   : Bob Herlien (rah)						*/
/* Project  : New ROV							*/
/* $Revision: 1.1 $							*/
/* Created  : 05/21/92							*/
/************************************************************************/
/* Modification History:						*/
/* $Log: vehiclecall.c,v $
 * Revision 1.1  1998/01/28 16:17:12  oreilly
 * Initial revision
 *
 * Revision 2.0  95/09/20  14:22:58  14:22:58  hebo (Bob Herlien)
 * Support for final vehicle integration.  AC, PDU micros.
 * 
 * Revision 1.8  94/08/19  17:20:18  17:20:18  hebo (Bob Herlien)
 * Interface to Unix version of Data Manager
 * 
 * Revision 1.7  94/03/21  14:15:12  14:15:12  hebo (Bob Herlien)
 * Misc bug fixes and enhancements
 * 
 * Revision 1.6  93/12/17  15:04:49  15:04:49  hebo (Bob Herlien)
 * December Wet Test
 * 
 * Revision 1.5  93/07/08  18:10:49  18:10:49  hebo (Bob Herlien)
 * Prior to Prototype Phase I testing
 * 
 * Revision 1.4  93/05/27  15:47:56  15:47:56  hebo (Bob Herlien)
 * Data Manager Interface
 * 
 * Revision 1.2  93/01/21  10:34:14  10:34:14  hebo (Bob Herlien)
 * Changes after Level 0
 * 
 * Revision 1.0  92/11/20  12:03:25  12:03:25  hebo (Bob Herlien)
 * Initial revision
 * 
*/
/************************************************************************/

#include <mbari/types.h>
#include <mbari/const.h>
#include <Xm/Xm.h>
#include <Xm/ToggleB.h>
#include <X11/Intrinsic.h>
#include <X11/Xc/Xc.h>
#include <X11/Xc/ToggleB.h>
#include <X11/Xc/BarGraf.h>
#include <X11/Xc/Led.h>
#include "rov.h"
#include "tiburon.h"
#include <thrusterDM.h>
#include <controlDM.h>
#include <sio32Diag.h>
#include <ers.h>
#include <ersDcon.h>
#include <panTilt.h>
#include "alarm.h"
#include "ibc.h"
#include "rdmif.h"
#include <datamgr.h>
#include <sys/socket.h>			/* Stuff for gethostbyaddr()	*/
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

#define MISC_ITEM_WIDTH		210
#define MISC_INFO_LEFT_POS	60
#define MISC_INFO_RT_POS	99
#define PEERLIST_STRING_SIZE	1024
#define PEERLIST_NAMESIZE	32


/********************************/
/*	External Functions	*/
/********************************/

Extern Void	createItems( rovItem **ipp, TimeoutStruct *tp );
Extern Void	startTimeout( TimeoutStruct *tp );
Extern Void	stopTimeout( TimeoutStruct *tp );
Extern Void	updateToggle( rovItem *rp );
Extern Widget	createIbcGroup( Widget parent, ibcItemSet *isp,
			        Dimension width, Int32 lpos, Int32 rpos );
Extern Void	createIbcItems( Reg ibcItemDesc *idp, char *dmprefix );
Extern Void	ibcStartTimeout( ibcItemDesc *idp, char *dmprefix );
Extern Void	ibcStopTimeout( ibcItemDesc *idp );
Extern Void	labelCreate( Widget parent, ibcItem *itm,
			     Int32 lpos, Int32 rpos );
Extern Void	updateIntLabel( ibcItem *itm );
Extern Void	updateFltLabel( ibcItem *itm );
Extern Void	rovWriteEvent(Widget w, rovItem *ip, XmAnyCallbackStruct *cbp);


/********************************/
/*	External Data		*/
/********************************/

Extern XtAppContext	appcontext;	/* The application context	*/
Extern AppData		appdata;	/* Application-wide resources	*/
Extern Widget		miscValueLabel;	/* Label for misc values	*/
Extern Widget		joystickIndicator;
Extern Widget		peerWindow;	/* Scrolled list for peerList	*/
Extern Widget		peerList;	/* Label for peer DM connections*/

Extern Widget		portHorizBarGraph, stbdHorizBarGraph, fwdLatBarGraph;
Extern Widget		portVertBarGraph, stbdVertBarGraph, aftLatBarGraph;
Extern Widget		autoHeadingToggle, autoPositionToggle;
Extern Widget		autoDepthToggle, autoAltitudeToggle;
Extern Widget		miscVehScrolledWindow, compLevelBarGraph;
Extern Widget		aliveButton, inWaterButton;
Extern Widget		toolsledLatchButton, toolsledConnectButton;
Extern Widget		toolsledLatchArmButton, toolsledLatchReleaseButton;
Extern Widget		deployLatchArmButton, deployLatchReleaseButton;
Extern char		buff[];		/* Misc buffer used application-wide*/


/********************************/
/*	Forward Declarations	*/
/********************************/

Void		updateInt16BarGraph( rovItem *ip );
Void		updateJoystickMode( rovItem *ip );
Void		updateJoystickGainSwitch( rovItem *ip );
Void		updatePeerStatus( TimeoutStruct *tp );
Void		updateAliveButton( rovItem *ip );
Void		updateInWaterButton( rovItem *ip );
Void		updateLatchButton( rovItem *ip );
Void		updateConnectButton( rovItem *ip );
Void		updateToolsledLatchButtons( rovItem *ip );
Void		updateDeployLatchButtons( rovItem *ip );


/********************************/
/*	Module Local Data	*/
/********************************/

MLocal Int		stillCount = 0;
MLocal Pixel		joystickIndicatorStateBackground;
MLocal Pixel		connectok_fg, connectok_bg;
MLocal Pixel		releaseDisarmColor;
MLocal Widget		peerClipWindow;
MLocal Int32		dmPeerSeqNo = -1;
MLocal char		peerListString[PEERLIST_STRING_SIZE];
MLocal char		*dmPeerStrings[] =
  { "Down", "Not Connected", "Booting", "Init Phase 1", "Initializing",
    "Init Sent", "Init Rcvd", "Connected" };

MLocal char		*joystickStates[] = {"Speed", "Thrust"};

MLocal rovItem		portHorizThrustItem = 
{ TIBURON_DM_PREFIX "THRUSTER.PORT_HORIZ.CMD_THRUST", DM_INT16, 1, FALSE,
  NO_ITEM, 0, &portHorizBarGraph, updateInt16BarGraph, 0 };

MLocal rovItem		sbHorizThrustItem = 
{ TIBURON_DM_PREFIX "THRUSTER.STBD_HORIZ.CMD_THRUST", DM_INT16, 1, FALSE,
  NO_ITEM, 0, &stbdHorizBarGraph, updateInt16BarGraph, 0 };

MLocal rovItem		portVertThrustItem = 
{ TIBURON_DM_PREFIX "THRUSTER.PORT_VERT.CMD_THRUST", DM_INT16, 1, FALSE,
  NO_ITEM, 0, &portVertBarGraph, updateInt16BarGraph, 0 };

MLocal rovItem		sbVertThrustItem = 
{ TIBURON_DM_PREFIX "THRUSTER.STBD_VERT.CMD_THRUST", DM_INT16, 1, FALSE,
  NO_ITEM, 0, &stbdVertBarGraph, updateInt16BarGraph, 0 };

MLocal rovItem		fwdLatThrustItem = 
{ TIBURON_DM_PREFIX "THRUSTER.FWD_LATERAL.CMD_THRUST", DM_INT16, 1, FALSE,
  NO_ITEM, 0, &fwdLatBarGraph, updateInt16BarGraph, 0 };

MLocal rovItem		aftLatThrustItem = 
{  TIBURON_DM_PREFIX "THRUSTER.AFT_LATERAL.CMD_THRUST", DM_INT16, 1, FALSE,
   NO_ITEM, 0, &aftLatBarGraph, updateInt16BarGraph, 0 };

MLocal rovItem		vehicleStateItem =
{ TIBURON_DM_PREFIX TIBURON_ALIVE_DM, DM_MBOOL, 1, TRUE, NO_ITEM, TRUE, 
  &aliveButton, updateAliveButton, 0 };

MLocal rovItem		inWaterItem =
{ TIBURON_DM_PREFIX TIBURON_IN_WATER_DM, DM_MBOOL, 1, FALSE, NO_ITEM, TRUE, 
  &inWaterButton, updateInWaterButton, 0 };

MLocal rovItem		toolsledLatchItem =
{ TIBURON_DM_PREFIX TOOLSLED_LATCHED_DM, DM_MBOOL, 1, FALSE, NO_ITEM, TRUE, 
  &toolsledLatchButton, updateLatchButton, 0 };

MLocal rovItem		toolsledConnectItem =
{ TIBURON_DM_PREFIX TOOLSLED_CONNECTED_DM, DM_MBOOL, 1, FALSE, NO_ITEM, TRUE, 
  &toolsledConnectButton, updateConnectButton, 0 };

MLocal rovItem		toolsledLatchArmItem =
{ TIBURON_DM_PREFIX TOOLSLED_LATCH_ARM_DM, DM_NAT16, 1, FALSE, NO_ITEM, TRUE, 
  &toolsledLatchArmButton, NULLF, 0 };

MLocal rovItem		toolsledLatchStatusItem =
{ TIBURON_DM_PREFIX TOOLSLED_LATCH_STATUS_DM, DM_ENUM, 1, FALSE, NO_ITEM, TRUE, 
  &toolsledLatchArmButton, updateToolsledLatchButtons, 0 };

MLocal rovItem		toolsledLatchReleaseItem =
{ TIBURON_DM_PREFIX TOOLSLED_LATCH_RELEASE_DM, DM_MBOOL, 1, FALSE, NO_ITEM,
  TRUE, &toolsledLatchReleaseButton, NULLF, 0 };

MLocal rovItem		deployLatchArmItem =
{ TIBURON_DM_PREFIX DEPLOYMENT_LATCH_ARM_DM, DM_NAT16, 1, FALSE, NO_ITEM,
  TRUE, &deployLatchArmButton, NULLF, 0 };

MLocal rovItem		deployLatchStatusItem =
{ TIBURON_DM_PREFIX DEPLOYMENT_LATCH_STATUS_DM, DM_ENUM, 1, FALSE, NO_ITEM,
  TRUE, &deployLatchArmButton, updateDeployLatchButtons, 0 };

MLocal rovItem		deployLatchReleaseItem =
{ TIBURON_DM_PREFIX DEPLOYMENT_LATCH_RELEASE_DM, DM_EMPTY, 1, FALSE, NO_ITEM,
  TRUE, &deployLatchReleaseButton, NULLF, 0 };

MLocal rovItem		joystickModeItem =
{ JOYSTICK_MODE_DM, DM_ENUM, 1, FALSE, NO_ITEM, 0, &joystickIndicator,
  updateJoystickMode, 0 };

MLocal rovItem		joystickGainSwitchItem =
{ JOYSTICK_GAIN_SWITCH_DM, DM_MBOOL, 1, FALSE, NO_ITEM, 0, &joystickIndicator,
  updateJoystickGainSwitch, 0 };

MLocal rovItem		compLevelItem =
{ TIBURON_DM_PREFIX COMP_SYSTEM_LEVEL_PERCENT_DM, DM_NAT16, 1, FALSE,
  NO_ITEM, 0, &compLevelBarGraph, updateInt16BarGraph, 0 };

Global rovItem		autoHeadingItem =
{ "TIBURON.CONTROL.AUTO_HEADING", DM_MBOOL, 1, FALSE, NO_ITEM, 0, 
  &autoHeadingToggle, updateToggle, 0 };

Global rovItem		autoPositionItem =
{ AUTO_POSITION_DM, DM_MBOOL, 1, FALSE, NO_ITEM, 0, 
  &autoPositionToggle, updateToggle, 0 };

Global rovItem		autoDepthItem =
{ "TIBURON.CONTROL.AUTO_DEPTH", DM_MBOOL, 1, FALSE, NO_ITEM, 0, 
  &autoDepthToggle, updateToggle, 0 };

Global rovItem		autoAltitudeItem =
{ AUTO_ALTITUDE_DM, DM_MBOOL, 1, FALSE, NO_ITEM, 0, 
  &autoAltitudeToggle, updateToggle, 0 };

MLocal rovItem		*vehicleItems[] = 
{ &portHorizThrustItem, &sbHorizThrustItem, &portVertThrustItem,
  &sbVertThrustItem, &fwdLatThrustItem, &aftLatThrustItem,
  &joystickModeItem, &joystickGainSwitchItem, &autoHeadingItem, 
  &autoPositionItem, &autoDepthItem, &autoAltitudeItem, &compLevelItem,
  &vehicleStateItem, &inWaterItem, &toolsledLatchItem, &toolsledConnectItem,
  &toolsledLatchArmItem, &toolsledLatchStatusItem, &toolsledLatchReleaseItem,
  &deployLatchArmItem, &deployLatchStatusItem, &deployLatchReleaseItem, NULLR };

MLocal TimeoutStruct	vehicleTimeoutStruct = 
{ &appdata.vehicle_update, 0, vehicleItems, 0, "Vehicle Screen",
  updatePeerStatus };

MLocal ibcItem	miscVehItems[] =
{ { "Depth", TIBURON_DM_PREFIX "SENSOR.DEPTH.METERS", DM_FLT64, 1, labelCreate, updateFltLabel,
    NULLF, NULLF, UP_CONSUME, 1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Altitude", TIBURON_DM_PREFIX "SENSOR.ALTITUDE.METERS", DM_FLT32, 1,
    labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME, 1, 0, NULL, 0,
    NULLW, NULLW, NULLW, 0, -1},
  { "Raw Compass", TIBURON_DM_PREFIX "SENSOR.COMPASS.DEGREES", DM_FLT32, 1,
    labelCreate, updateFltLabel, NULLF, NULLF, UP_ALREADY_CONSUME, 1, 0,
    NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Raw Gyro", TIBURON_DM_PREFIX "SENSOR.GYRO.DEGREES", DM_FLT32, 1,
    labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME, 1, 0, NULL, 0,
    NULLW, NULLW, NULLW, 0, -1},
  { "Pitch Degrees", TIBURON_DM_PREFIX "SENSOR.PITCH.DEGREES", DM_FLT32, 1,
    labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME, 1, 0, NULL, 0,
    NULLW, NULLW, NULLW, 0, -1},
  { "Roll Degrees", TIBURON_DM_PREFIX "SENSOR.ROLL.DEGREES", DM_FLT32, 1,
    labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME, 1, 0, NULL, 0,
    NULLW, NULLW, NULLW, 0, -1},
  { "VME Temperature", TIBURON_DM_PREFIX VME_TEMPERATURE_DM, DM_INT16, 1,
    labelCreate, updateIntLabel, NULLF, NULLF, UP_CONSUME, 0, 0, NULL, 0,
    NULLW, NULLW, NULLW, 0, -1},
  { "VME Humidity",  TIBURON_DM_PREFIX "VME_IBC.MICRO_HUMIDITY", DM_NAT16, 1,
    labelCreate, updateIntLabel, NULLF, NULLF, UP_CONSUME, 0, 0, NULL, 0,
    NULLW, NULLW, NULLW, 0, -1},
  { "Port Light Pan", PAN_TILT_PORT_LIGHT_PAN_DM_PREFIX PT_ANALOG_POS_DM,
    DM_FLT32, 1, labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME,
    1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Port Light Tilt", PAN_TILT_PORT_LIGHT_TILT_DM_PREFIX PT_ANALOG_POS_DM,
    DM_FLT32, 1, labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME,
    1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Port Camera Pan", PAN_TILT_PORT_CAMERA_PAN_DM_PREFIX PT_ANALOG_POS_DM,
    DM_FLT32, 1, labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME,
    1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Port Camera Tilt", PAN_TILT_PORT_CAMERA_TILT_DM_PREFIX PT_ANALOG_POS_DM,
    DM_FLT32, 1, labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME,
    1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Stbd Light Pan", PAN_TILT_STBD_LIGHT_PAN_DM_PREFIX PT_ANALOG_POS_DM,
    DM_FLT32, 1, labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME,
    1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Stbd Light Tilt", PAN_TILT_STBD_LIGHT_TILT_DM_PREFIX PT_ANALOG_POS_DM,
    DM_FLT32, 1, labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME,
    1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Stbd Camera Pan", PAN_TILT_STBD_CAMERA_PAN_DM_PREFIX PT_ANALOG_POS_DM,
    DM_FLT32, 1, labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME,
    1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1},
  { "Stbd Camera Tilt", PAN_TILT_STBD_CAMERA_TILT_DM_PREFIX PT_ANALOG_POS_DM,
    DM_FLT32, 1, labelCreate, updateFltLabel, NULLF, NULLF, UP_CONSUME,
    1, 0, NULL, 0, NULLW, NULLW, NULLW, 0, -1}
};

MLocal ibcItemSet  miscVehItemSet = 
{ miscVehItems, XtNumber(miscVehItems), NULLW };

MLocal ibcItemDesc	miscVehItemDesc =
{ {&miscVehItemSet, NULLIS, NULLIS, NULLIS},
  &appdata.vehicle_update, 0, 0, 0 };


/************************************************************************/
/* Function    : selectVehicle						*/
/* Purpose     : Callback function when vehicle screen is selected	*/
/* Inputs      : Select Struct ptr					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
selectVehicle( Select *sp )
{
    startTimeout( &vehicleTimeoutStruct );
    ibcStartTimeout( &miscVehItemDesc, NULL );

} /* selectVehicle() */


/************************************************************************/
/* Function    : unselectVehicle					*/
/* Purpose     : Callback function when vehicle screen is unselected	*/
/* Inputs      : Select Struct ptr					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
unselectVehicle( Select *sp )
{
    stopTimeout( &vehicleTimeoutStruct );
    ibcStopTimeout( &miscVehItemDesc );

} /* unselectVehicle() */


/************************************************************************/
/* Function    : updateInt16BarGraph					*/
/* Purpose     : Update Function for a BarGraph with short data		*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateInt16BarGraph( rovItem *ip )
{
    Int16	ival;
    XcVType	vval;
    
    rdm_read( ip->dmitem, (char *)&ival, sizeof(Int16) );
    if ( ival != ip->value )
    {
	vval.lval = ip->value = ival;
	XcBGUpdateValue( *ip->widget, &vval );
    }

} /* updateInt16BarGraph() */


/************************************************************************/
/* Function    : updateJoystickMode					*/
/* Purpose     : Function to update Joystick Mode indicator		*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateJoystickMode( rovItem *ip )
{
    Int32	mode;
    char	*statestr;

    rdm_read( ip->dmitem, (char *)&mode, sizeof(Int32) );
    if ( mode != ip->value )
    {
	statestr = (mode == 0) ? joystickStates[0] : joystickStates[1];
	XtVaSetValues( *ip->widget, XcNstate, statestr, NULL);
	ip->value = mode;
    }

} /* updateJoystickMode() */


/************************************************************************/
/* Function    : updateAliveButton					*/
/* Purpose     : Function to update Alive indicator			*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateAliveButton( rovItem *ip )
{
    char	*statestr;
    MBool	state;

    rdm_read( ip->dmitem, (char *)&state, sizeof(MBool) );
    if ( state != ip->value )
    {
	if ( state )
	{
	    XtVaSetValues( *ip->widget, XcNstate, "Alive",
			   XcNstateBackground, appdata.stateOK, NULL );
	}
	else
	{
	    XtVaSetValues( *ip->widget, XcNstate, "Down",
			   XcNstateBackground, appdata.stateBad, NULL );
	}
	ip->value = state;
    }

} /* updateAliveButton() */


/************************************************************************/
/* Function    : updateInWaterButton					*/
/* Purpose     : Function to update In-water indicator			*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateInWaterButton( rovItem *ip )
{
    char	*statestr;
    MBool	state;

    rdm_read( ip->dmitem, (char *)&state, sizeof(MBool) );
    if ( state != ip->value )
    {
	if ( state )
	    XtVaSetValues( *ip->widget, XcNstate, "Wet",
			   XcNstateBackground, appdata.inWater, NULL );
	else
	    XtVaSetValues( *ip->widget, XcNstate, "Dry",
			   XcNstateBackground, appdata.outOfWater, NULL );
	ip->value = state;
    }

} /* updateInWaterButton() */


/************************************************************************/
/* Function    : updateVehicleToggleButton				*/
/* Purpose     : Function to update XmToggleButton on vehicle screen	*/
/* Inputs      : Pointer to rovItem, label strings for True, False	*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateVehicleToggleButton( rovItem *ip, char *trueString, char *falseString )
{
    MBool	state;
    XmString	str;

    rdm_read( ip->dmitem, (char *)&state, sizeof(MBool) );
    if ( state != ip->value )
    {
	if ( state )
	{
	    str = XmStringCreateSimple( trueString );
	    XtVaSetValues( *ip->widget, XmNlabelString, str, XmNset, True,
			   NULL );
	}
	else
	{
	    str = XmStringCreateSimple( falseString );
	    XtVaSetValues( *ip->widget, XmNlabelString, str, XmNset, False,
			   NULL );
	}
	ip->value = state;
	XmStringFree( str );
    }

} /* updateVehicleToggleButton() */


/************************************************************************/
/* Function    : updateLatchButton					*/
/* Purpose     : Function to update Toolsled latched indicator		*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateLatchButton( rovItem *ip )
{
    updateVehicleToggleButton( ip, "Latched", "UnLatched" );

} /* updateLatchButton() */


/************************************************************************/
/* Function    : updateConnectButton					*/
/* Purpose     : Function to update Toolsled Connected indicator	*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateConnectButton( rovItem *ip )
{
    updateVehicleToggleButton( ip, "Connected", "UnConnected" );

} /* updateConnectButton() */


/************************************************************************/
/* Function    : activateLatchRelease					*/
/* Purpose     : Activate Callback for Latch Release			*/
/* Inputs      : Widget ID, rovItem ptr, callback struct		*/
/* Outputs     : None							*/
/************************************************************************/
    Void
activateLatchRelease( Widget w, rovItem *ip, XmAnyCallbackStruct *cbs )
{
    MBool		dmstate;

    rdm_read( ip->dmitem, (char *)&dmstate, sizeof(MBool) );
    dmstate = dmstate ? FALSE : TRUE;
    ip->value = dmstate;
    rdm_write_once( ip->dmitem, (char *)&dmstate, sizeof(MBool) );

} /* activateLatchRelease() */


/************************************************************************/
/* Function    : updateLatchButtons					*/
/* Purpose     : Function to update the Latch Arm & Release buttons	*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateLatchButtons( rovItem *statusItem, rovItem *releaseItem,
		    XtCallbackProc releaseCallback )
{
    ersLatchMode	mode;
    XmString		label;
    Pixel		color;
    Boolean		isSensitive;

    rdm_read( statusItem->dmitem, (char *)&mode, sizeof(mode) );

    if ( mode != statusItem->value )
    {
	XtRemoveAllCallbacks( *releaseItem->widget, XmNactivateCallback );
	color = appdata.releaseArmColor;
	isSensitive = True;

	switch( mode )
	{
	  case LATCH_DISARMED:
	    label = XmStringCreateLtoR("Release\n(Disarmed)",
				       XmSTRING_DEFAULT_CHARSET);
	    color = releaseDisarmColor;
	    isSensitive = False;
	    break;

	  case LATCH_ARMED:
	    label = XmStringCreateLtoR("Release\n(Armed)",
				       XmSTRING_DEFAULT_CHARSET);
	    break;

	  case LATCH_ARMED_NO_PWR:
	    label = XmStringCreateLtoR("Release\n(No Pwr)",
				       XmSTRING_DEFAULT_CHARSET);
	    break;

	  case LATCH_RUNNING:
	    label = XmStringCreateLtoR("Release\n(Running)",
				       XmSTRING_DEFAULT_CHARSET);
	    break;
	}

	XtVaSetValues( *statusItem->widget, XmNbackground, color, NULL );
	XtVaSetValues( *releaseItem->widget, XmNbackground, color,
		       XmNlabelString, label, XmNsensitive, isSensitive, NULL );
	XmStringFree( label );

	if ( mode != LATCH_DISARMED )
	    XtAddCallback( *releaseItem->widget, XmNactivateCallback, 
			   releaseCallback, releaseItem );
    }

} /* updateLatchButtons() */


/************************************************************************/
/* Function    : updateToolsledLatchButtons				*/
/* Purpose     : Function to update Toolsled Latch Arm & Release Buttons*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateToolsledLatchButtons( rovItem *ip )
{
    updateLatchButtons( ip, &toolsledLatchReleaseItem,
		        (XtCallbackProc)activateLatchRelease );

} /* updateToolsledLatchButtons() */


/************************************************************************/
/* Function    : updateDeployLatchArmButton				*/
/* Purpose     : Function to update Deployment Latch Arm & Release Buttons*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateDeployLatchButtons( rovItem *ip )
{
    updateLatchButtons( ip, &deployLatchReleaseItem,
		        (XtCallbackProc)rovWriteEvent );

} /* updateDeployLatchButtons() */


/************************************************************************/
/* Function    : activateLatchArmButton					*/
/* Purpose     : Callback indicating user hit an Arm button		*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
activateLatchArmButton( rovItem *armItem, Nat16 armCode )
{
    Nat16	armState;

    rdm_read( armItem->dmitem, (char *)&armState, sizeof(armState) );

    armState = (armState == armCode) ? 0 : armCode;

    rdm_write_once( armItem->dmitem, (char *)&armState, sizeof(armState) );

} /* activateLatchArmButton() */


/************************************************************************/
/* Function    : activateToolsledLatchArmButton				*/
/* Purpose     : Callback indicating user hit Toolsled Arm button	*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
activateToolsledLatchArmButton( Widget w, XtPointer unused,
			        XmPushButtonCallbackStruct *cbp )
{
    activateLatchArmButton( &toolsledLatchArmItem, TOOLSLED_LATCH_ARM_CODE );

} /* activateToolsledLatchArmButton() */


/************************************************************************/
/* Function    : activateDeployLatchArmButton				*/
/* Purpose     : Callback indicating user hit Deployment Arm button	*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
activateDeployLatchArmButton( Widget w, XtPointer unused,
			        XmPushButtonCallbackStruct *cbp )
{
    activateLatchArmButton( &deployLatchArmItem, DEPLOYMENT_LATCH_ARM_CODE );

} /* activateDeployLatchArmButton() */


/************************************************************************/
/* Function    : updateJoystickGainSwitch				*/
/* Purpose     : Get peer name and status strings			*/
/* Inputs      : Pointer to rovItem					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updateJoystickGainSwitch( rovItem *ip )
{
    MBool	gainsw;
    Pixel	color;

    rdm_read( ip->dmitem, (char *)&gainsw, sizeof(MBool) );
    if ( gainsw != ip->value )
    {
	color = gainsw ? appdata.joystick_warning : 
	    		 joystickIndicatorStateBackground;
	XtVaSetValues( *ip->widget, XcNstateBackground, color, NULL );
	ip->value = gainsw;
    }

} /* updateJoystickGainSwitch() */


/************************************************************************/
/* Function    : peerStatusString					*/
/* Purpose     : Get Peer name and status string			*/
/* Inputs      : Peer inaddr, status, ptr to place to return name	*/
/* Outputs     : Ptr to status string					*/
/************************************************************************/
    char *
peerStatusString( InAddr addr, Int32 status, char *np, Nat32 nmlen )
{
    Reg struct hostent	*hp;
    Reg char		*p;
    struct in_addr	inaddr;
    char		nodename[PEERLIST_NAMESIZE];

    inaddr.s_addr = addr;    
    if ( (hp = gethostbyaddr((char *)&inaddr, sizeof(inaddr), AF_INET))
	 == (struct hostent *)NULL )
	strncpy( np, inet_ntoa(inaddr), nmlen );
    else
    {
	strncpy( np, hp->h_name, nmlen );
	if ( (p = strchr(np, '.')) != NULL )
	    *p = '\0';
    }

    return( (status <= DMP_CONN) ? dmPeerStrings[status+1] : "Unknown" );

} /* peerStatusString() */


/************************************************************************/
/* Function    : updatePeerStatus					*/
/* Purpose     : Update DM Peer Connection Status List			*/
/* Inputs      : Pointer to TimeoutStruct				*/
/* Outputs     : None							*/
/************************************************************************/
    Void
updatePeerStatus( TimeoutStruct *tp )
{
    DmPeerSts		status[MAX_PEERS];
    Reg Nat32		i, n;
    Reg char		*sts;
    Reg Int32		newPeerSeqNo;
    Nat32		npeers;
    XmString		str;
    Pixel		fg, bg;
    char		nodename[PEERLIST_NAMESIZE];

    npeers = MAX_PEERS;
    if ( (newPeerSeqNo = rdm_peer_status(status, &npeers)) == dmPeerSeqNo )
	return;

    dmPeerSeqNo = newPeerSeqNo;
    fg = connectok_fg;
    bg = connectok_bg;

    for ( i = n = 0; i < npeers; i++ )
	if ( status[i].peer_addr != (InAddr)0 )
	{
	    sts = peerStatusString( status[i].peer_addr, status[i].peer_state,
				    nodename, PEERLIST_NAMESIZE );

	    n += sprintf(peerListString + n, "%-16s %s\n", nodename, sts);
	    if ( status[i].peer_state != DMP_CONN )
	    {
		fg = appdata.connect_fg;
		bg = appdata.connect_bg;
	    }
	}

    if ( n == 0 )
	strcpy( peerListString, "None" );
    else 
	peerListString[n-1] = '\0';		/* Remove trailing '\n'	*/

    str = XmStringCreateLtoR(peerListString, XmSTRING_DEFAULT_CHARSET);

    XtVaSetValues( peerList, XmNlabelString, str,
		   XmNforeground, fg, XmNbackground, bg, NULL );

    XtVaSetValues( peerClipWindow, XmNbackground, bg, NULL );

    XmStringFree(str);

} /* updatePeerStatus() */


/************************************************************************/
/* Function    : activateDepthAltToggle					*/
/* Purpose     : Activate Auto Depth or Altitude Toggle, which are exclusive*/
/* Inputs      : Widget ID, rovItem ptr, callback struct		*/
/* Outputs     : None							*/
/************************************************************************/
    Void
activateDepthAltToggle( Widget w, rovItem *rp, XmAnyCallbackStruct *cbs )
{
    XcToggleState	state;
    MBool		dmstate;

    XcToggleGet( w, &state );
    dmstate = (state == XcOn) ? TRUE : FALSE;
    rp->value = dmstate;

    if ( autoAltitudeItem.value && autoDepthItem.value )
    {
	XcToggleSet( *rp->widget, XcOff );
	rp->value = FALSE;
    }
    else
	rdm_write_once( rp->dmitem, (char *)&dmstate, sizeof(MBool) );

} /* activateDepthAltToggle() */


/************************************************************************/
/* Function    : toggleEnable						*/
/* Purpose     : Enable (set sensitive) a widget based on toggleButton state*/
/* Inputs      : Widget ID, Ptr to Widget to enable, CallbackStruct	*/
/* Outputs     : None							*/
/************************************************************************/
    Void
toggleEnable( Widget w, Widget *target, XmAnyCallbackStruct *call_data )
{
    XcToggleState	state;

    XtVaGetValues( w, XcNstate, &state, NULL );
    XtSetSensitive( *target, (state == XcOn) );

} /* toggleEnable() */


/************************************************************************/
/* Function    : shootStill						*/
/* Purpose     : Shoot a Still Picture					*/
/* Inputs      : Widget ID, Ptr to Widget to enable, CallbackStruct	*/
/* Outputs     : None							*/
/************************************************************************/
    Void
shootStill( Widget w, XtPointer client, XmAnyCallbackStruct *call)
{
/*
    XmString	str;

    stillCount++;
    sprintf( buff, "%d", stillCount );
    str = XmStringCreateSimple( buff );
    XtVaSetValues( stillCamCount, XmNlabelString, str, NULL );
    XmStringFree( str );
*/
} /* shootStill() */


/************************************************************************/
/* Function    : initVehicle						*/
/* Purpose     : Initialize function for vehicle screen			*/
/* Inputs      : None							*/
/* Outputs     : None							*/
/************************************************************************/
    Void
initVehicle( Void )
{
    createItems( vehicleItems, &vehicleTimeoutStruct );

    createIbcItems( &miscVehItemDesc, NULL );

    createIbcGroup( miscVehScrolledWindow, &miscVehItemSet, MISC_ITEM_WIDTH,
		    MISC_INFO_LEFT_POS, MISC_INFO_RT_POS );
    XtManageChild( miscVehItemSet.widget );

    XtVaGetValues(joystickIndicator,
		  XcNstateBackground, &joystickIndicatorStateBackground, NULL);

    XtVaGetValues( peerList, XmNforeground, &connectok_fg,
			     XmNbackground, &connectok_bg, NULL );

    XtVaGetValues( peerWindow, XmNclipWindow, &peerClipWindow, NULL );

    XtVaGetValues( toolsledLatchArmButton, XmNbackground,
		   &releaseDisarmColor, NULL );

    updatePeerStatus( &vehicleTimeoutStruct );

} /* initVehicle() */
