/******************************************************************************/
/* Copyright 1995 MBARI                                                       */
/******************************************************************************/
/* Summary  : CTD Data Acquisition and Display Module                         */
/* Filename : ctd.c                                                           */
/* Author   : Janice Tarrant                                                  */
/* Project  : Tiburon                                                         */
/* Version  : Version 1.0                                                     */
/* Created  : 02/02/95                                                        */
/* Modified : 03/21/96                                                        */
/* Archived :                                                                 */
/******************************************************************************/
/* Modification History :                                                     */
/* $Header: /usr/tiburon/unix/gui/ctd/RCS/ctd.c,v 1.4 1998/03/26 00:04:58 oreilly Exp $
 * $Log: ctd.c,v $
 * Revision 1.4  1998/03/26 00:04:58  oreilly
 * Display processed oxygen_temp and oxygen_current instead of raw
 *
 * Revision 1.3  1998/03/12 18:17:29  oreilly
 * *** empty log message ***
 *
 * Revision 1.2  1998/03/12 18:15:37  oreilly
 * Popdown parameter windows in response to WM close-window message, instead
 * of destroying
 *
 * Revision 1.1  1998/03/12 17:52:41  oreilly
 * Initial revision
 *
 *
 */
/******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <mbari/types.h>        /* MBARI style guide type declarations        */
#include <dmUnix.h>		/* unix data manager definitions              */
#include <semLib.h>             /* semaphore library                          */
#include <time.h>		/* MBARI time declarations                    */
#include <datamgr.h>		/* data manager declarations                  */
#include <dm_errno.h>		/* data manager error declarations            */
#include <sensorDcon.h>        	/* sensor data concentrator definitions       */
#include <sensorsDm.h>        	/* sensor data manager definitions            */
#include <ctdDM.h>        	/* CTD data manager definitions               */
#include <Xm/Xm.h>
#include <Xm/DrawingA.h>
#include <Xm/MessageB.h>
#include <Xm/Protocols.h>
#include "ctdDisplay.h"

#define ACQUISITION_PERIOD 1000000	/* acquisition period (microsec)(1 Hz)*/

Widget appShell;			/* main application shell             */
Widget displayShell;
Widget guiShell;
Widget guiForm;
Widget xShell[NUM_X_VARS];
Widget xForm[NUM_X_VARS];
Widget yShell;
Widget yForm;
Widget canvas;
GC     gc;

configurationParameters configParams;	/* display configuration parameters   */
					/* plot scrolling flag                */
MBool                   plotScrolling = FALSE;
					/* auto start flag                    */
MBool                   autoStart = FALSE;
MBool                   startDisplay = FALSE;
MBool                   restartDisplay;
MBool                   freezeDisplay;
MBool                   stopAcquisition;
MBool                   resetYTickLabels;
MBool                   rescale;
Int16  loopNumber = 1;
Int32  numDataPoints;
Int32  pointCount = -1;
Int32  plotStart = 0;
Int32  plotEnd = 0;
Int32  plotSpan = 0;
Int32  plotMax = 0;
Flt32  minInSecs;			/* min time value in seconds          */
Flt32  maxInSecs;                       /* max time value in seconds          */
Flt32  yTimeUnitsScale;			/* scale y values by the time units   */
Flt32  *dataValues[NUM_DATA_POINTS];	/* pointers to data values            */

String fallbackResources[] =
{
    "Ctd*background:	grey70",
    "Ctd*foreground:	RoyalBlue4",
    NULL
};

Int16         readInParams(char *filename, plotParameters *plotParams);
void          showXYPosition(Widget w, XtPointer clientData, XEvent *event,
                             Boolean *flag);
void          trackXYPosition(Widget w, XtPointer clientData, XEvent *event,
                              Boolean *flag);
void          clearXYPosition(Widget w, XtPointer clientData, XEvent *event,
                              Boolean *flag);
Int16         getStatusLineItems(char *statusLineString, Int16 *statusVar);
Int16         checkStatusLineName(Int16 statusVar, char *string);
Int16         countToken(char *string);
Int16         getYParams(FILE *fpr);
Int16         getXParams(FILE *fpr, varNum x);
Int16         checkParamName(char *nameString, char *name);
itemVariables toItem(char *itemName);
unitsOfTime   toTimeUnits(char *unitsName);
void          toColour(xItemParameters *xVar, char *colourName);
Int16         ctdDMInit(itemsUpdateData *itemsData);
Int32         allocateDataMemory(Widget w);
void          initGraphics(Widget w, plotParameters *plotParams);
Widget        createDisplayDrawingArea(Widget w);
Widget        CreateguiForm(Widget w, plotParameters *plotParams);
Widget        CreatexForm(Widget w, Int16 var, plotParameters *plotParams);
Widget        CreateyForm(Widget w, yItemParameters *yVar,
			  plotParameters *plotParams);
void          closeDisplayCallback(Widget w, XtPointer clientData,
				   XtPointer callData);
void          redisplayCallback(Widget w, XtPointer clientData,
				XtPointer callData);
void          resizeCallback(Widget w, XtPointer clientData,
			     XtPointer callData);
void          startDisplayGraphics(plotParameters *plotParams);
static void   updateDataValues(XtPointer clientData, XtIntervalId *id);

/* Popdown window in response to close-window message from WM */
static void   closeWindowCallback(Widget w, XtPointer clientData, 
				  XtPointer callData);


main(int argc, char **argv)
{
    itemsUpdateData itemsData;			/* display items update data  */
    plotParameters  plotParams;			/* plot parameters            */
    Arg             args[256];			/* Xt arguments               */
    Cardinal        argcnt;			/* Xt argument count          */
    XtAppContext    context;
    Cardinal        depth;
    XGCValues       values;
    char            filename[STRING_LENGTH];	/* configuration file name    */
    Int16           var;			/* variable counter           */
						/* data update interval       */
    Nat32           updateInterval = 1000.0 / DATA_UPDATE_RATE;

    Atom WM_DELETE_WINDOW;
    
/* get the configuration file name and auto start flag                        */
    if (argc == 3)
    {
	strcpy(filename, argv[1]);
	if (strcmp(argv[2], "-a") == 0)
	    autoStart = TRUE;
	else
	    printf("Unrecognized option %s\n", argv[2]);
    }
    else if (argc == 2)
	strcpy(filename, argv[1]);
    else
    {
	printf("Enter configuration file name :\n");
	gets(filename);
    }

/* read in display configuration parameters                                   */
    if (readInParams(filename, &plotParams) == ERROR)
	exit(0);

/* initialize data manager items and start consumers                          */
    if (ctdDMInit(&itemsData) == ERROR)
    {
	dm_task_exit(0);
	exit(0);
    }

/* initialize display window and create application shell                     */
    appShell = XtAppInitialize(&context, "Ctd", NULL, 0, &argc, argv,
			       fallbackResources, args, argcnt);

/* create a pop-up shell for the application gui                              */
    argcnt = 0;
    XtSetArg(args[argcnt], XmNtitle, "CTD Display GUI"); argcnt++;
    XtSetArg(args[argcnt], XmNallowShellResize, False); argcnt++;
    XtSetArg(args[argcnt], XmNx, 10); argcnt++;
    XtSetArg(args[argcnt], XmNy, 100); argcnt++;
    XtSetArg(args[argcnt], XmNwidth, 600); argcnt++;
    XtSetArg(args[argcnt], XmNheight, 500); argcnt++;
    guiShell = XtCreatePopupShell("guiTopLevelShell", topLevelShellWidgetClass,
				  appShell, args, argcnt);
    guiForm = CreateguiForm(guiShell, &plotParams);

/* create a pop-up shell and drawing area widget for the data display         */
    argcnt = 0;
    XtSetArg(args[argcnt], XmNtitle, "CTD Display"); argcnt++;
    XtSetArg(args[argcnt], XmNiconName, "topLevelShell"); argcnt++;
    XtSetArg(args[argcnt], XmNx, 800); argcnt++;
    XtSetArg(args[argcnt], XmNy, 100); argcnt++;
    XtSetArg(args[argcnt], XmNwidth, 500); argcnt++;
    XtSetArg(args[argcnt], XmNheight, 500); argcnt++;
    displayShell = XtCreatePopupShell("CTD Display", 
                                      topLevelShellWidgetClass, appShell, args,
				      argcnt);
    XtAddCallback(displayShell, XmNdestroyCallback, closeDisplayCallback,
		  (XtPointer) NULL);

    canvas = createDisplayDrawingArea(displayShell);
    XtAddCallback(canvas, XmNexposeCallback, redisplayCallback,
		  (XtPointer) &plotParams);
    XtAddCallback(canvas, XmNresizeCallback, resizeCallback,
		  (XtPointer) &plotParams);

/* initialize graphics parameters                                             */
    initGraphics(canvas, &plotParams);

    WM_DELETE_WINDOW = XmInternAtom(XtDisplay(appShell), 
				    "WM_DELETE_WINDOW",
				    False);
    

/* create a pop-up shell for the x items parameters, for each x variable      */
    for (var = 0; var < configParams.numXVariables; var++)
    {
    	argcnt = 0;
    	XtSetArg(args[argcnt], XmNallowShellResize, False); argcnt++;
    	XtSetArg(args[argcnt], XmNx, 400); argcnt++;
    	XtSetArg(args[argcnt], XmNy, 400); argcnt++;
    	XtSetArg(args[argcnt], XmNwidth, 500); argcnt++;
    	XtSetArg(args[argcnt], XmNheight, 350); argcnt++;

    	xShell[var] = XtCreatePopupShell("x parameters", 
					 topLevelShellWidgetClass,
					 appShell, args, argcnt);

	XtVaSetValues(xShell[var], XmNdeleteResponse, XmDO_NOTHING);

	XmAddWMProtocolCallback(xShell[var], WM_DELETE_WINDOW, 
				closeWindowCallback, NULL);
    

    	xForm[var] = CreatexForm(xShell[var], var, &plotParams);
        XtManageChild(xForm[var]);
    }

/* create a pop-up shell for the y item parameters                            */
    argcnt = 0;
    XtSetArg(args[argcnt], XmNallowShellResize, False); argcnt++;
    XtSetArg(args[argcnt], XmNx, 400); argcnt++;
    XtSetArg(args[argcnt], XmNy, 400); argcnt++;
    XtSetArg(args[argcnt], XmNwidth, 500); argcnt++;
    XtSetArg(args[argcnt], XmNheight, 340); argcnt++;
    yShell = XtCreatePopupShell("y parameters", topLevelShellWidgetClass,
				appShell, args, argcnt);

    XtVaSetValues(yShell, XmNdeleteResponse, XmDO_NOTHING);

    WM_DELETE_WINDOW = XmInternAtom(XtDisplay(yShell), "WM_DELETE_WINDOW",
				    False);
    
    XmAddWMProtocolCallback(yShell, WM_DELETE_WINDOW, closeWindowCallback, 
			    NULL);
    

    yForm = CreateyForm(yShell, &configParams.yVariable, &plotParams);
    XtManageChild(yForm);

/* show the main gui                                                          */
    XtManageChild(guiForm);
    XtPopup(XtParent(guiForm), XtGrabNone);

/* allocate space for display items                                           */
    numDataPoints = allocateDataMemory(guiForm);
    itemsData.w = guiForm;

/* show the display window                                                    */
    XtManageChild(canvas);
    XtPopup(XtParent(canvas), XtGrabNone);

/* create a graphics context */
    XtVaGetValues(canvas, XmNforeground, &values.foreground,
		  XmNbackground, &values.background, XmNdepth, &depth, NULL);
    gc = XtAllocateGC(canvas, depth, GCForeground | GCBackground, &values,
		      GCForeground | GCLineStyle, (XtGCMask) NULL);

/* start data acquisition                                                     */
    updateDataValues((XtPointer) &itemsData, NULL);

/* if auto start option selected, start display                               */
    if (autoStart)
    	startDisplayGraphics(&plotParams);

    XtAppMainLoop(context);

} /* main */


/******************************************************************************/
/* Function : readInParams                                                    */
/* Purpose  : Reads the configuration parameters from the input file.         */
/* Inputs   : Configuration parameter filename and plot parameters.           */
/* Outputs  : Returns ERROR or OK.                                            */
/******************************************************************************/
    Int16
readInParams(char *filename, plotParameters *plotParams)
{
    FILE        *fpr;				/* read file pointer          */
    static char pathName[3*STRING_LENGTH] = "";	/* config file path name      */
    char        fullName[4*STRING_LENGTH];	/* config file full name      */
    char        tmpString1[STRING_LENGTH];	/* temporary strings          */
    char        tmpString2[STRING_LENGTH];
    char        statusLineString[6*STRING_LENGTH];
    size_t      pathNameLen;			/* path name string length    */
    Int16       var;				/* x variable counter         */

/* concatenate the configuration file path and file names                     */
    if (strcmp(pathName, ""))
    {
	strcpy(fullName, pathName);
	strcat(fullName, filename);
    }
    else
	strcpy(fullName, filename);

/* open the configuration file                                                */
    if ( (fpr = fopen(fullName, "r")) == NULL)
    {
	printf("Could not open file %s\n", fullName);
	return(ERROR);
    }

/* get configuration file name                                                */
    fscanf(fpr, "%s %s\n", tmpString1, configParams.configFilename);
    if (checkParamName(tmpString1, "FILENAME") == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, configParams.configFilename);

/* determine the configuration file path                                      */
    if (strcmp(filename, configParams.configFilename))
    {
	pathNameLen = strlen(filename) - strlen(configParams.configFilename);
	if (pathNameLen > (3*STRING_LENGTH))
	{
	    printf("Configuration file path is too long to save for restart\n");
	    return(ERROR);
	}
	strncpy(pathName, filename, pathNameLen);
    }

/* get mark data file name                                                    */
    fscanf(fpr, "%s %s\n", tmpString1, configParams.markFilename);
    if (checkParamName(tmpString1, "MARK_FILENAME") == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, configParams.markFilename);

/* get graphics display rate                                                  */
    fscanf(fpr, "%s %f\n", tmpString1, &configParams.graphicsDisplayRate);
    if (checkParamName(tmpString1, "GRAPHICS_DISPLAY_RATE") == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %f\n", tmpString1, configParams.graphicsDisplayRate);
    if ( (configParams.graphicsDisplayRate < 0) ||
	 (configParams.graphicsDisplayRate > 1) )
    {
	printf("Graphics display rate %f out of range\n",
	       configParams.graphicsDisplayRate);
        fclose(fpr);
	return(ERROR);
    }

/* get status line display rate                                               */
    fscanf(fpr, "%s %f\n", tmpString1, &configParams.statusLineRate);
    if (checkParamName(tmpString1, "STATUS_LINE_RATE") == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %f\n", tmpString1, configParams.statusLineRate);
    if ( (configParams.statusLineRate < 0) ||
	 (configParams.statusLineRate > 1) )
    {
	printf("Status line rate %f out of range\n",
	       configParams.statusLineRate);
        fclose(fpr);
	return(ERROR);
    }

/* get display plot style                                                     */
    fscanf(fpr, "%s %s\n", tmpString1, tmpString2);
    if (checkParamName(tmpString1, "PLOT_STYLE") == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }
    if (!strcmp(tmpString2, "LINES"))
	configParams.lineDrawing = TRUE;
    else if (!strcmp(tmpString2, "DOTS"))
	configParams.lineDrawing = FALSE;
    else
    {
	printf("Display plot style %s unknown\n", tmpString2);
        fclose(fpr);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, tmpString2);

/* get show xy coordinates state                                              */
    fscanf(fpr, "%s %s\n", tmpString1, tmpString2);
    if (checkParamName(tmpString1, "SHOW_XY") == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }
    if (!strcmp(tmpString2, "ON"))
	configParams.showXY = TRUE;
    else if (!strcmp(tmpString2, "OFF"))
	configParams.showXY = FALSE;
    else
    {
	printf("Show xy coordinate state %s unknown\n", tmpString2);
        fclose(fpr);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, tmpString2);

/* get scrolling state                                                        */
    fscanf(fpr, "%s %s\n", tmpString1, tmpString2);
    if (checkParamName(tmpString1, "SCROLL") == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }
    if (!strcmp(tmpString2, "ON"))
	configParams.scrolling = TRUE;
    else if (!strcmp(tmpString2, "OFF"))
	configParams.scrolling = FALSE;
    else
    {
	printf("Scrolling state %s unknown\n", tmpString2);
        fclose(fpr);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, tmpString2);

/* get status line variables                                                  */
    fgets(statusLineString, 6 * STRING_LENGTH, fpr);
    configParams.numStatusLineVariables = countToken(statusLineString) - 1;
    sscanf(statusLineString, "%s", tmpString1);
    if (checkParamName(tmpString1, "STATUS_LINE_VARIABLES") == ERROR)
    {
      	fclose(fpr);
	return(ERROR);
    }
    if (getStatusLineItems(statusLineString,
        &configParams.numStatusLineVariables) == ERROR)
    {
      	fclose(fpr);
	return(ERROR);
    }

/* get number of x variables                                                  */
    fscanf(fpr, "%s %hd\n", tmpString1, &configParams.numXVariables);
    if (checkParamName(tmpString1, "NUMBER_X_VARIABLES") == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %d\n", tmpString1, configParams.numXVariables);
    if ( (configParams.numXVariables < 1) || (configParams.numXVariables > 4) )
    {
	printf("Number of x variables %d out of range\n",
	       configParams.numXVariables);
        fclose(fpr);
	return(ERROR);
    }

/* get y axis parameters                                                      */
    if (getYParams(fpr) == ERROR)
    {
        fclose(fpr);
	return(ERROR);
    }

/* get x axis parameters                                                      */
    for (var = 0; var < NUM_X_VARS; var++)
    	if (getXParams(fpr, var) == ERROR)
    	{
            fclose(fpr);
	    return(ERROR);
    	}

    fclose(fpr);
    return(OK);

} /* readInParams */


/******************************************************************************/
/* Function : getYParams                                                      */
/* Purpose  : Gets the y item variable parameters.                            */
/* Inputs   : Configuration parameter filename.                               */
/* Outputs  : Returns ERROR or OK.                                            */
/******************************************************************************/
    Int16
getYParams(FILE *fpr)
{
    char tmpString1[STRING_LENGTH];
    char tmpString2[STRING_LENGTH];
    char axisLabel[AXIS_LABEL_LENGTH];
    Int16 len, beg;

/* get the y item variable                                                    */
    fscanf(fpr, "%s %s\n", tmpString1, tmpString2);
    if (checkParamName(tmpString1, "Y_VARIABLE") == ERROR)
	return(ERROR);
    if ( (configParams.items[Y] = toItem(tmpString2)) == NO_VAR)
    {
	printf("Incorrect item name : %s\n", tmpString2);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, tmpString2);

/* get the y axis label                                                       */
    fscanf(fpr, "%s", tmpString1);
    if (checkParamName(tmpString1, "Y_LABEL") == ERROR)
	return(ERROR);
    fgets(axisLabel, AXIS_LABEL_LENGTH, fpr);
    len = strlen(axisLabel)-1;
    strcpy(axisLabel+len, "");
    beg = 0;
    while (isspace(axisLabel[beg]))
	beg++;
    strcpy(configParams.yVariable.axisLabel, axisLabel+beg);
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, configParams.yVariable.axisLabel);

/* get the y axis minimum value                                               */
    fscanf(fpr, "%s %f\n", tmpString1, &configParams.yVariable.minValue);
    if (checkParamName(tmpString1, "Y_MIN_VALUE") == ERROR)
	return(ERROR);
    if (VERIFY_ON)
        printf("%s %f\n", tmpString1, configParams.yVariable.minValue);

/* get the y axis maximum value                                               */
    fscanf(fpr, "%s %f\n", tmpString1, &configParams.yVariable.maxValue);
    if (checkParamName(tmpString1, "Y_MAX_VALUE") == ERROR)
	return(ERROR);
    if (VERIFY_ON)
        printf("%s %f\n", tmpString1, configParams.yVariable.maxValue);

/* get the y axis number of major divisions                                   */
    fscanf(fpr, "%s %hd\n", tmpString1, &configParams.yVariable.majorDivisions);
    if (checkParamName(tmpString1, "Y_MAJOR_DIVISIONS") == ERROR)
	return(ERROR);
    if (VERIFY_ON)
        printf("%s %d\n", tmpString1, configParams.yVariable.majorDivisions);

/* get the y axis time units                                                  */
    fscanf(fpr, "%s %s\n", tmpString1, tmpString2);
    if (checkParamName(tmpString1, "Y_TIME_UNITS") == ERROR)
	return(ERROR);
    if ( (configParams.yVariable.timeUnits = toTimeUnits(tmpString2)) ==
	  NO_UNITS)
    {
	printf("Incorrect time units : %s\n", tmpString2);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, tmpString2);

    return(OK);

} /* getYParams */


/******************************************************************************/
/* Function : getStatusLineItems                                              */
/* Purpose  : Gets the status line items.                                     */
/* Inputs   : Status line items string and status item variable.              */
/* Outputs  : Returns ERROR or OK.                                            */
/******************************************************************************/
    Int16
getStatusLineItems(char *statusLineString, Int16 *statusVar)
{
    char  tmpString1[STRING_LENGTH];
    char  tmpString2[STRING_LENGTH];
    char  tmpString3[STRING_LENGTH];
    char  tmpString4[STRING_LENGTH];
    char  tmpString5[STRING_LENGTH];
    char  tmpString6[STRING_LENGTH];

    if (*statusVar > 5)
    {
	*statusVar = 5;
	printf("cannot specify more than 5 status line parameters\n");
    }

    switch(*statusVar)
    {
	case 0 :
	    if (VERIFY_ON)
	        printf("No status line variables specified\n");
	    return(ERROR);
	    break;

	case 1:
    	    sscanf(statusLineString, "%s %s", tmpString1, tmpString2);
	    if (checkStatusLineName(*statusVar-1, tmpString2) == ERROR)
		return(ERROR);
    	    if (VERIFY_ON)
    	        printf("%s %s\n", tmpString1, tmpString2);
	    break;

	case 2:
    	    sscanf(statusLineString, "%s %s %s", tmpString1, tmpString2,
		   tmpString3);
	    if (checkStatusLineName(*statusVar-2, tmpString2) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-1, tmpString3) == ERROR)
		return(ERROR);
    	    if (VERIFY_ON)
    	        printf("%s %s %s\n", tmpString1, tmpString2, tmpString3);
	    break;

	case 3:
    	    sscanf(statusLineString, "%s %s %s %s", tmpString1, tmpString2,
		   tmpString3, tmpString4);
	    if (checkStatusLineName(*statusVar-3, tmpString2) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-2, tmpString3) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-1, tmpString4) == ERROR)
		return(ERROR);
    	    if (VERIFY_ON)
    	        printf("%s %s %s %s\n", tmpString1, tmpString2, tmpString3,
		       tmpString4);
	    break;

	case 4:
    	    sscanf(statusLineString, "%s %s %s %s %s", tmpString1, tmpString2,
		   tmpString3, tmpString4, tmpString5);
	    if (checkStatusLineName(*statusVar-4, tmpString2) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-3, tmpString3) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-2, tmpString4) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-1, tmpString5) == ERROR)
		return(ERROR);
    	    if (VERIFY_ON)
    	        printf("%s %s %s %s %s\n", tmpString1, tmpString2, tmpString3,
		       tmpString4, tmpString5);
	    break;

	case 5:
    	    sscanf(statusLineString, "%s %s %s %s %s %s", tmpString1,
		   tmpString2, tmpString3, tmpString4, tmpString5, tmpString6);
	    if (checkStatusLineName(*statusVar-5, tmpString2) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-4, tmpString3) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-3, tmpString4) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-2, tmpString5) == ERROR)
		return(ERROR);
	    if (checkStatusLineName(*statusVar-1, tmpString6) == ERROR)
		return(ERROR);
    	    if (VERIFY_ON)
    	        printf("%s %s %s %s %s %s\n", tmpString1, tmpString2,
		       tmpString3, tmpString4, tmpString5, tmpString6);
	    break;

	default :
	    break;
    }

    return(OK);

}  /* getStatusLineItems */


/******************************************************************************/
/* Function : checkStatusLineName                                             */
/* Purpose  : Checks for a valid status line variable name.                   */
/* Inputs   : Status item variable and name string.                           */
/* Outputs  : Returns ERROR or OK.                                            */
/******************************************************************************/
    Int16
checkStatusLineName(Int16 statusVar, char *string)
{
    if ((configParams.statusLineItems[statusVar] = toItem(string)) == NO_VAR)
    {
       	printf("Incorrect item name : %s\n", string);
       	return(ERROR);
    }

    return(OK);

}  /* checkStatusLineName */


/******************************************************************************/
/* Function : countToken                                                      */
/* Purpose  : Counts then number of words in a string.                        */
/* Inputs   : String.                                                         */
/* Outputs  : Returns ERROR or OK.                                            */
/******************************************************************************/
    Int16
countToken(char *string)
{
    char buffer[256];
    Int16 count = 1;

    strcpy(buffer, string);
    if (strtok(buffer, " \t\n") == 0)
	return(0);
    for (;;)
    {
	if (strtok(0, " \t\n") == 0)
	    return(count);
	count++;
    }
}  /* countToken */


/******************************************************************************/
/* Function : getXParams                                                      */
/* Purpose  : Gets the x item variable parameters.                            */
/* Inputs   : Configuration parameter filename.                               */
/* Outputs  : Returns ERROR or OK.                                            */
/******************************************************************************/
    Int16
getXParams(FILE *fpr, varNum x)
{
    char namePrefix[STRING_LENGTH];
    char paramName[STRING_LENGTH];
    char tmpString1[STRING_LENGTH];
    char tmpString2[STRING_LENGTH];
    char axisLabel[AXIS_LABEL_LENGTH];
    Int16 len, beg;

    switch (x)
    {
	case X1 :
	    strcpy(namePrefix, "X1_");
	    break;

	case X2 :
	    strcpy(namePrefix, "X2_");
	    break;

	case X3 :
	    strcpy(namePrefix, "X3_");
	    break;

	case X4 :
	    strcpy(namePrefix, "X4_");
	    break;
    }

/* get the x item variables                                                   */
    strcpy(paramName, namePrefix);
    strcat(paramName, "VARIABLE");
    fscanf(fpr, "%s %s\n", tmpString1, tmpString2);
    if (checkParamName(tmpString1, paramName) == ERROR)
	return(ERROR);
    if ( (configParams.items[x] = toItem(tmpString2)) == NO_VAR)
    {
	printf("Incorrect item name : %s\n", tmpString2);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, tmpString2);

/* get the x axes labels                                                      */
    strcpy(paramName, namePrefix);
    strcat(paramName, "LABEL");
    fscanf(fpr, "%s", tmpString1);
    if (checkParamName(tmpString1, paramName) == ERROR)
	return(ERROR);
    fgets(axisLabel, AXIS_LABEL_LENGTH, fpr);
    len = strlen(axisLabel)-1;
    strcpy(axisLabel+len, "");
    beg = 0;
    while (isspace(axisLabel[beg]))
	beg++;
    strcpy(configParams.xVariables[x].axisLabel, axisLabel+beg);
    if (VERIFY_ON)
        printf("%s %s \n", tmpString1, configParams.xVariables[x].axisLabel);

/* get the x axes minimum values                                              */
    strcpy(paramName, namePrefix);
    strcat(paramName, "MIN_VALUE");
    fscanf(fpr, "%s %f\n", tmpString1, &configParams.xVariables[x].minValue);
    if (checkParamName(tmpString1, paramName) == ERROR)
	return(ERROR);
    if (VERIFY_ON)
        printf("%s %f\n", tmpString1, configParams.xVariables[x].minValue);

/* get the x axes maximum values                                              */
    strcpy(paramName, namePrefix);
    strcat(paramName, "MAX_VALUE");
    fscanf(fpr, "%s %f\n", tmpString1, &configParams.xVariables[x].maxValue);
    if (checkParamName(tmpString1, paramName) == ERROR)
	return(ERROR);
    if (VERIFY_ON)
        printf("%s %f\n", tmpString1, configParams.xVariables[x].maxValue);
    if (configParams.xVariables[x].maxValue <=
	configParams.xVariables[x].minValue)
    {
	printf("Max value must be greater than min value\n");
	return(ERROR);
    }

/* get the x axes number of major divisions                                   */
    strcpy(paramName, namePrefix);
    strcat(paramName, "MAJOR_DIVISIONS");
    fscanf(fpr, "%s %hd\n", tmpString1,
	   &configParams.xVariables[x].majorDivisions);
    if (checkParamName(tmpString1, paramName) == ERROR)
	return(ERROR);
    if (VERIFY_ON)
        printf("%s %d\n", tmpString1,
	       configParams.xVariables[x].majorDivisions);

/* get the x axes colours                                                     */
    strcpy(paramName, namePrefix);
    strcat(paramName, "COLOR");
    fscanf(fpr, "%s %s\n", tmpString1, tmpString2);
    if (checkParamName(tmpString1, paramName) == ERROR)
	return(ERROR);
    toColour(&configParams.xVariables[x], tmpString2); 
    if ( !strcmp(configParams.xVariables[x].colourName, "none") )
    {
	printf("Incorrect colour name : %s\n", tmpString2);
	return(ERROR);
    }
    if (VERIFY_ON)
        printf("%s %s\n", tmpString1, tmpString2);

    return(OK);

} /* getXParams */


/******************************************************************************/
/* Function : checkParamName                                                  */
/* Purpose  : Checks for a valid configuration parameter name.                */
/* Inputs   : Parameter name string and name.                                 */
/* Outputs  : Returns ERROR or OK.                                            */
/******************************************************************************/
    Int16
checkParamName(char *nameString, char *name)
{
    if (strcmp(nameString, name))
    {
	printf("%s misplaced in configuration file\n", name);
	return(ERROR);
    }

    return(OK);

} /* checkParamName */


/******************************************************************************/
/* Function : toItem                                                          */
/* Purpose  : Translates an item name to an item variable.                    */
/* Inputs   : Item name string.                                               */
/* Outputs  : Returns item variable.                                          */
/******************************************************************************/
    itemVariables
toItem(char *itemName)
{

    if (!strcmp(itemName, "BEAM_ATTENUATION"))
	return(BEAM_ATTENUATION);
    if (!strcmp(itemName, "BEAM_PERCENT"))
	return(BEAM_PERCENT);
    if (!strcmp(itemName, "CONDUCTIVITY"))
	return(CONDUCTIVITY);
    if (!strcmp(itemName, "DEPTH"))
	return(DEPTH);
    if (!strcmp(itemName, "OXYGEN"))
	return(OXYGEN);
    if (!strcmp(itemName, "OXYGEN_CURRENT"))
	return(OXYGEN_CURRENT);
    if (!strcmp(itemName, "OXYGEN_TEMP"))
	return(OXYGEN_TEMP);
    if (!strcmp(itemName, "PRESSURE"))
	return(PRESSURE);
    if (!strcmp(itemName, "SALINITY"))
	return(SALINITY);
    if (!strcmp(itemName, "SCAN_NUMBER"))
	return(SCAN_NUMBER);
    if (!strcmp(itemName, "SIGMA_T"))
	return(SIGMA_T);
    if (!strcmp(itemName, "SIGMA_THETA"))
	return(SIGMA_THETA);
    if (!strcmp(itemName, "SOUND_VELOCITY"))
	return(SOUND_VELOCITY);
    if (!strcmp(itemName, "TEMPERATURE"))
	return(TEMPERATURE);
    if (!strcmp(itemName, "TIME"))
	return(TIME);
    if (!strcmp(itemName, "THETA"))
	return(THETA);
    if (!strcmp(itemName, "TRANSMISSION"))
	return(TRANSMISSION);

    return(NO_VAR);

} /* toItem */


/******************************************************************************/
/* Function : toTimeUnits                                                     */
/* Purpose  : Translates the time units name to the time units.               */
/* Inputs   : Time units name string.                                         */
/* Outputs  : Time units.                                                     */
/******************************************************************************/
    unitsOfTime
toTimeUnits(char *unitsName)
{

    if (!strcmp(unitsName, "HOURS"))
	return(HOURS);
    if (!strcmp(unitsName, "MINUTES"))
	return(MINUTES);
    if (!strcmp(unitsName, "SECONDS"))
	return(SECONDS);

    return(NO_UNITS);

} /* toTimeUnits */


/******************************************************************************/
/* Function : toColour                                                        */
/* Purpose  : Translates the colour name to the display colour.               */
/* Inputs   : X item parameters and colour name string.                       */
/* Outputs  : None.                                                           */
/******************************************************************************/
    void
toColour(xItemParameters *xVar, char *colourName)
{

    if (!strcmp(colourName, "RED"))
    {
	strcpy(xVar->colourName, "red");
	xVar->colour = RED;
	return;
    }
    if (!strcmp(colourName, "BLUE"))
    {
	strcpy(xVar->colourName, "blue");
	xVar->colour = BLUE;
	return;
    }
    if (!strcmp(colourName, "GREEN"))
    {
	strcpy(xVar->colourName, "green");
	xVar->colour = GREEN;
	return;
    }
    if (!strcmp(colourName, "CYAN"))
    {
	strcpy(xVar->colourName, "cyan");
	xVar->colour = CYAN;
	return;
    }
    if (!strcmp(colourName, "YELLOW"))
    {
	strcpy(xVar->colourName, "yellow");
	xVar->colour = YELLOW;
	return;
    }
    if (!strcmp(colourName, "MAGENTA"))
    {
	strcpy(xVar->colourName, "magenta");
	xVar->colour = MAGENTA;
	return;
    }
    if (!strcmp(colourName, "WHITE"))
    {
	strcpy(xVar->colourName, "white");
	xVar->colour = WHITE;
	return;
    }

    strcpy(xVar->colourName, "none");
    xVar->colour = NO_COLOUR;

} /* toColour */


/******************************************************************************/
/* Function : ctdDMInit                                                       */
/* Purpose  : Looks up the item handle and starts consumers for the data      */
/*            manager items being recorded.                                   */
/* Inputs   : Items update data.                                              */
/* Outputs  : Returns OK or ERROR.                                            */
/******************************************************************************/
    Int16
ctdDMInit(itemsUpdateData *itemsData)
{
    char        *ctdDMName;             /* ctd display DM item name           */
    char        *sensorIbcDMPrefix =	/* sensor ibc DM item name prefix     */
		SENSOR_IBC_DM_PREFIX;
					/* conductivity name                  */
    MLocal char conductivityName[DM_ITEM_NAME_LEN];
					/* oxygen current name                */
    MLocal char oxygenCurrentName[DM_ITEM_NAME_LEN];
					/* oxygen temperature name            */
    MLocal char oxygenTempName[DM_ITEM_NAME_LEN];
					/* pressure name                      */
    MLocal char pressureName[DM_ITEM_NAME_LEN];
					/* temperature name                   */
    MLocal char temperatureName[DM_ITEM_NAME_LEN];
					/* transmissometer name               */
    MLocal char transmissometerName[DM_ITEM_NAME_LEN];
    Int16       item;			/* data manager item counter          */
    Errno       status;			/* data manager error code            */
    struct				/* data manager items init values     */
    {
        char      *name;		/* data manager array name            */
	DM_Type   type;                 /* data manager item type             */
        DM_Num    num;			/* number of data manager item        */
        DM_Item   *item;		/* data manager item handle pointer   */
    } dmiCreate[] =
    { { BEAM_ATTENUATION_DM,	   DM_FLT32,  1,  NO_ITEM },
      { BEAM_PER_CENT_DM,	   DM_FLT32,  1,  NO_ITEM },
      { conductivityName,	   DM_FLT32,  1,  NO_ITEM },
      { VEHICLE_DEPTH_DM,	   DM_FLT32,  1,  NO_ITEM },
      { OXYGEN_ML_PER_LITRE_DM,	   DM_FLT32,  1,  NO_ITEM },
      { oxygenCurrentName,	   DM_FLT32,  1,  NO_ITEM },
      { oxygenTempName,	   	   DM_FLT32,  1,  NO_ITEM },
      { pressureName,	   	   DM_FLT32,  1,  NO_ITEM },
      { SALINITY_PSU_DM,	   DM_FLT32,  1,  NO_ITEM },
      { CTD_SCAN_NUMBER_DM,	   DM_FLT32,  1,  NO_ITEM },
      { SIGMAT_KG_PER_M3_DM,	   DM_FLT32,  1,  NO_ITEM },
      { SIGMA_THETA_KG_PER_M3_DM,  DM_FLT32,  1,  NO_ITEM },
      { SOUND_VELOCITY_DM,	   DM_FLT32,  1,  NO_ITEM },
      { temperatureName,  	   DM_FLT32,  1,  NO_ITEM },
      { THETA_DEGREES_C_DM,	   DM_FLT32,  1,  NO_ITEM },
      { CTD_TIME_DM,  		   DM_FLT32,  1,  NO_ITEM },
      { transmissometerName,  	   DM_FLT32,  1,  NO_ITEM },
      { NULL, 0, NO_ITEM } };

    dmiCreate[BEAM_ATTENUATION].item = &itemsData->beamAttenuation;
    dmiCreate[BEAM_PERCENT].item = &itemsData->beamPercent;
    dmiCreate[CONDUCTIVITY].item = &itemsData->conductivity;
    dmiCreate[DEPTH].item = &itemsData->depth;
    dmiCreate[OXYGEN].item = &itemsData->oxygen;
    dmiCreate[OXYGEN_CURRENT].item = &itemsData->oxygenCurrent;
    dmiCreate[OXYGEN_TEMP].item = &itemsData->oxygenTemp;
    dmiCreate[PRESSURE].item = &itemsData->pressure;
    dmiCreate[SALINITY].item = &itemsData->salinity;
    dmiCreate[SCAN_NUMBER].item = &itemsData->scanNumber;
    dmiCreate[SIGMA_T].item = &itemsData->sigmaT;
    dmiCreate[SIGMA_THETA].item = &itemsData->sigmaTheta;
    dmiCreate[SOUND_VELOCITY].item = &itemsData->soundVelocity;
    dmiCreate[TEMPERATURE].item = &itemsData->temperature;
    dmiCreate[THETA].item = &itemsData->theta;
    dmiCreate[TIME].item = &itemsData->time;
    dmiCreate[TRANSMISSION].item = &itemsData->transmissometer;

    status = dm_init((DM_Define *) NULL);
    if (checkCreate(status) == ERROR)
	return(ERROR);

/* create conductivity data manager item name                                 */
    ctdDMName = CONDUCTIVITY_SENSOR_DM;
    strcpy(conductivityName, sensorIbcDMPrefix);
    strcat(conductivityName, ctdDMName);

/* create oxygen current data manager item name                               */
    ctdDMName = OXYGEN_SENSOR_CURRENT_READING_DM;
    strcpy(oxygenCurrentName, sensorIbcDMPrefix);
    strcat(oxygenCurrentName, ctdDMName);

/* create oxygen temperature data manager item name                           */
    ctdDMName = OXYGEN_SENSOR_TEMPERATURE_READING_DM;
    strcpy(oxygenTempName, sensorIbcDMPrefix);
    strcat(oxygenTempName, ctdDMName);

/* create pressure data manager item name                                     */
    ctdDMName = PRESSURE_SENSOR_DM;
    strcpy(pressureName, sensorIbcDMPrefix);
    strcat(pressureName, ctdDMName);

/* create temperature data manager item name                                  */
    ctdDMName = TEMPERATURE_SENSOR_DM;
    strcpy(temperatureName, sensorIbcDMPrefix);
    strcat(temperatureName, ctdDMName);

/* create transmissometer data manager item name                              */
    ctdDMName = TRANSMISSOMETER_SENSOR_DM;
    strcpy(transmissometerName, sensorIbcDMPrefix);
    strcat(transmissometerName, ctdDMName);

/* create data manager items                                                  */
    for (item = 0; dmiCreate[item].item != NO_ITEM; item++)
    {
     	status = dm_create(dmiCreate[item].name, dmiCreate[item].num,
			   dmiCreate[item].item, dmiCreate[item].type,
			   1, DM_ENDT);
	if (checkCreate(status, dmiCreate[item].name, FALSE) == ERROR)
	    return(ERROR);
    }

/* start consumer items and check status                                      */
    for (item = 0; dmiCreate[item].name != NULL; item++)
    {
	status = dm_start_consumer(*(dmiCreate[item].item), ACQUISITION_PERIOD,
				   SEM_NULL);
        if (checkConsumer(status, dmiCreate[item].name, TRUE) == ERROR)
	    return(ERROR);
    }

    return(OK);

} /* ctdDMCreate */


/******************************************************************************/
/* Function : allocateDataMemory                                              */
/* Purpose  : Allocates memory for the data values.                           */
/* Inputs   : GUI form widget.                                                */
/* Outputs  : Number of data points allocated.                                */
/******************************************************************************/
    Int32
allocateDataMemory(Widget w)
{
    static Widget dialogue = NULL;
    char          message[AXIS_LABEL_LENGTH];
    Int32         point;
    Flt32         hours;

/* malloc space for each set of ith data points                               */
    for (point = 0; point < NUM_DATA_POINTS; point++)
    {
	dataValues[point] = (Flt32 *) malloc(NUM_DISPLAY_ITEMS * sizeof(Flt32));

	if (!dataValues[point])		/* out of memory                      */
	{
	    hours = (Flt32) point;
	    hours /= SECONDS_PER_HOUR;
	    sprintf(message,
	    "Could not allocate all data storage, only %5.2f hours available",
	    hours);

	    if (!dialogue)
	    {
		dialogue = XmCreateWarningDialog(w, "dialog", NULL, 0);
		XtVaSetValues(dialogue, XtVaTypedArg, XmNmessageString,
			      XmRString, message, strlen(message) + 1, NULL);
	    }
	    XtManageChild(dialogue);

	    return(point - 1);
	}
    }

    return(NUM_DATA_POINTS);

} /* allocateDataMemory */


/******************************************************************************/
/* Function : updateDataValues                                                */
/* Purpose  : Reads the data values at the desired update rate.               */
/* Inputs   : Items data and interval id.                                     */
/* Outputs  : None.                                                           */
/******************************************************************************/
    static void
updateDataValues(XtPointer clientData, XtIntervalId *id)
{
    itemsUpdateData *data = (itemsUpdateData *) clientData;
    static Flt32    scanNumber = -1.0;
    static Flt32    firstTime;
    Nat32           updateInterval = 1000.0 / DATA_UPDATE_RATE;
    Int16           var;
    Flt64           conductivity;		/* conductivity value         */
    Flt64           depth;			/* depth value                */
    Flt64           pressure;			/* pressure value             */
    Flt64           temperature;		/* temperature value          */
    Errno           status;
    time_t          scanTime;
    struct tm       timeData, *timeDataPtr;

/* restart timeout                                                            */
    XtAppAddTimeOut(XtWidgetToApplicationContext(data->w), updateInterval,
		    updateDataValues, (XtPointer) data);

/* point count increases up to the max number of data points, then is reset   */
/* to zero and the data array is overwritten                                  */
    pointCount++;
    if (pointCount == numDataPoints)
    {
	pointCount = 0;
	loopNumber++;				/* increment loop counter     */
    }

/* read the data values                                                       */
    status = dm_read(data->beamAttenuation,
                     (Void *) &dataValues[pointCount][BEAM_ATTENUATION],
                     sizeof(dataValues[pointCount][BEAM_ATTENUATION]),
                     &data->sensorTime[BEAM_ATTENUATION]);
    status = dm_read(data->beamPercent,
                     (Void *) &dataValues[pointCount][BEAM_PERCENT],
                     sizeof(dataValues[pointCount][BEAM_PERCENT]),
                     &data->sensorTime[BEAM_PERCENT]);
    status = dm_read(data->conductivity, (Void *) &conductivity,
                     sizeof(conductivity), &data->sensorTime[CONDUCTIVITY]);
    dataValues[pointCount][CONDUCTIVITY] = (Flt32) conductivity;
    status = dm_read(data->depth, (Void *) &depth, sizeof(depth),
                     &data->sensorTime[DEPTH]);
    dataValues[pointCount][DEPTH] = (Flt32) depth;
    status = dm_read(data->oxygen,
                     (Void *) &dataValues[pointCount][OXYGEN],
                     sizeof(dataValues[pointCount][OXYGEN]),
                     &data->sensorTime[OXYGEN]);
    status = dm_read(data->oxygenCurrent,
                     (Void *) &dataValues[pointCount][OXYGEN_CURRENT],
                     sizeof(dataValues[pointCount][OXYGEN_CURRENT]),
                     &data->sensorTime[OXYGEN_CURRENT]);
    status = dm_read(data->oxygenTemp,
                     (Void *) &dataValues[pointCount][OXYGEN_TEMP],
                     sizeof(dataValues[pointCount][OXYGEN_TEMP]),
                     &data->sensorTime[OXYGEN_TEMP]);
    status = dm_read(data->pressure, (Void *) &pressure, sizeof(pressure),
                     &data->sensorTime[PRESSURE]);
    dataValues[pointCount][PRESSURE] = (Flt32) pressure;
    status = dm_read(data->salinity,
                     (Void *) &dataValues[pointCount][SALINITY],
                     sizeof(dataValues[pointCount][SALINITY]),
                     &data->sensorTime[SALINITY]);
    dataValues[pointCount][SCAN_NUMBER] = (Flt32) ++scanNumber;
/*
    status = dm_read(data->scanNumber,
                     (Void *) &dataValues[pointCount][SCAN_NUMBER],
                     sizeof(dataValues[pointCount][SCAN_NUMBER]),
                     &data->sensorTime[SCAN_NUMBER]);
*/
    status = dm_read(data->sigmaT,
                     (Void *) &dataValues[pointCount][SIGMA_T],
                     sizeof(dataValues[pointCount][SIGMA_T]),
                     &data->sensorTime[SIGMA_T]);
    status = dm_read(data->sigmaTheta,
                     (Void *) &dataValues[pointCount][SIGMA_THETA],
                     sizeof(dataValues[pointCount][SIGMA_THETA]),
                     &data->sensorTime[SIGMA_THETA]);
    status = dm_read(data->soundVelocity,
                     (Void *) &dataValues[pointCount][SOUND_VELOCITY],
                     sizeof(dataValues[pointCount][SOUND_VELOCITY]),
                     &data->sensorTime[SOUND_VELOCITY]);
    status = dm_read(data->temperature, (Void *) &temperature,
                     sizeof(temperature), &data->sensorTime[TEMPERATURE]);
    dataValues[pointCount][TEMPERATURE] = (Flt32) temperature;
    status = dm_read(data->theta,
                     (Void *) &dataValues[pointCount][THETA],
                     sizeof(dataValues[pointCount][THETA]),
                     &data->sensorTime[THETA]);
/*
    status = dm_read(data->time,
                     (Void *) &scanTime, sizeof(scanTime),
                     &data->sensorTime[TIME]);
*/
    scanTime = time(NULL);
    timeDataPtr = localtime(&scanTime);
    timeData = *timeDataPtr;
    dataValues[pointCount][TIME] = timeData.tm_sec + 
				   SECONDS_PER_MINUTE * timeData.tm_min +
				   SECONDS_PER_HOUR * timeData.tm_hour;
    if (scanNumber == 0)
	firstTime = dataValues[0][TIME];
    dataValues[pointCount][TIME] -= firstTime;
/*
    printf("%s    seconds %f\n",
	   ctime(&scanTime), dataValues[pointCount][TIME]);
*/
    status = dm_read(data->transmissometer,
                     (Void *) &dataValues[pointCount][TRANSMISSION],
                     sizeof(dataValues[pointCount][TRANSMISSION]),
                     &data->sensorTime[TRANSMISSION]);

/*
printf("num %f  time %ld %s %f\n",
       dataValues[pointCount][SCAN_NUMBER], scanTime, ctime(&scanTime),
       dataValues[pointCount][SCAN_NUMBER]);
printf("p %f  t %f  c %f  s %f  th %f  st %f sth %f\n",
       dataValues[pointCount][PRESSURE], dataValues[pointCount][TEMPERATURE],
       dataValues[pointCount][CONDUCTIVITY], dataValues[pointCount][SALINITY],
       dataValues[pointCount][THETA], dataValues[pointCount][SIGMA_T],
       dataValues[pointCount][SIGMA_THETA]);
printf("d %f  sv %f  o %f  bp %f  ba %f\n",
       dataValues[pointCount][DEPTH], dataValues[pointCount][SOUND_VELOCITY],
       dataValues[pointCount][OXYGEN], dataValues[pointCount][BEAM_PERCENT],
       dataValues[pointCount][BEAM_ATTENUATION]);
    printf("time %s  hours %d  minutes %d  seconds %d\n",
	   ctime(&scanTime), timeData.tm_hour, timeData.tm_min,
	   timeData.tm_sec);
*/

/* set the plot start, end, max and span values                               */
    if (configParams.items[Y] == SCAN_NUMBER)
    {			
	if ( (pointCount > plotStart) && (pointCount <= plotMax) )
	    plotEnd = pointCount;
    }
    else if (configParams.items[Y] == TIME)
    {
    	if (scanNumber == 0)			/* set on first iteration     */
    	{
	    if (dataValues[0][TIME] >= minInSecs)
	    {
		plotStart = 0;
		if (dataValues[0][TIME] >= maxInSecs)
		{
		    plotMax = 0;
		    printf("Time range specified is before start of data acquisition\n");
		}
		else
		    plotMax = (maxInSecs - dataValues[0][TIME]) *
			       DATA_UPDATE_RATE; 
	    }
	    else
	    {
		plotStart = (minInSecs - dataValues[0][TIME]) *
			     DATA_UPDATE_RATE;
		plotMax = plotStart + plotSpan;
	    } 
	    plotEnd = plotStart;
	}
	else					/* set every iteration        */
	    if ( (pointCount > plotStart) && (pointCount <= plotMax) )
	        plotEnd = pointCount;
    }
    else
    {
	if (plotStart < 0)			/* set start to first data    */
						/* value between min and max  */
	    if ((dataValues[pointCount][configParams.items[Y]] >=
		 configParams.yVariable.minValue) &&
		(dataValues[pointCount][configParams.items[Y]] <=
		 configParams.yVariable.maxValue))
	    {
		plotStart = pointCount;
		plotEnd = plotStart;
		plotMax = plotEnd;
	    }
						/* check each new value to see*/
						/* if within min/max range    */
	if ((dataValues[pointCount][configParams.items[Y]] >=
		 configParams.yVariable.minValue) &&
	        (dataValues[pointCount][configParams.items[Y]] <=
		 configParams.yVariable.maxValue))
	{
	    plotEnd = pointCount;
	    plotMax = pointCount;
	    plotSpan = plotMax - plotStart;
	}

/*
	    printf("start %d  end %d  max %d  span %d\n", 
	           plotStart, plotEnd, plotMax, plotSpan);
*/
    }

#if TRACE_ON
    printf("point %d ydata %f\n", pointCount,
	   dataValues[pointCount][configParams.items[Y]]);
#endif

}  /* updateDataValues */


/******************************************************************************/
/* Function : startDisplayGraphics                                            */
/* Purpose  : Starts the graphics for the display data.                       */
/* Inputs   : Plot parameters.                                                */
/* Outputs  : None.                                                           */
/******************************************************************************/
    void
startDisplayGraphics(plotParameters *plotParams)
{
    Display            *display = XtDisplay(plotParams->displayData.display);
    Drawable           drawable = XtWindow(plotParams->displayData.display);

    updateDisplay((XtPointer) plotParams, NULL);
    updateStatusLine((XtPointer) &plotParams->displayData, NULL);
    restartDisplay = FALSE;
    resetYTickLabels = FALSE;
    rescale = FALSE;    
    startDisplay = TRUE;
    freezeDisplay = FALSE;
    stopAcquisition = FALSE;
    if (configParams.showXY == TRUE)
    {
        XtAddEventHandler(plotParams->displayData.display, ButtonPressMask,
			  FALSE, showXYPosition, (XtPointer) plotParams);
	XtAddEventHandler(plotParams->displayData.display, ButtonMotionMask,
			  FALSE, trackXYPosition, (XtPointer) plotParams);
	XtAddEventHandler(plotParams->displayData.display,
			  ButtonReleaseMask | LeaveWindowMask, FALSE,
			  clearXYPosition, (XtPointer) plotParams);
    }

}  /* startDisplayGraphics */


static void closeWindowCallback(Widget w, 
				XtPointer clientData,
				XtPointer callData)
{
  XtPopdown(w);
}
