/************************************************************************/
/* Copyright 1992 - 1996 MBARI						*/
/************************************************************************/
/* $Header: motortest.c,v 2.2 96/05/15 11:14:49 bobh Exp $		*/
/* Summary  : Main Routines for User Interface for Motor Testing	*/
/* Filename : motortest.c						*/
/* Author   : Bob Herlien (rah)						*/
/* Project  : Tiburon							*/
/* $Revision: 2.2 $							*/
/* Created  : 09/30/96							*/
/************************************************************************/
/* Modification History:						*/
/* $Log$
   30sep96,rah, created from rov.c
*/
/************************************************************************/

#include <mbari/types.h>
#include <mbari/const.h>
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/keysym.h>
#include <Xm/Xm.h>
#include <Xm/Protocols.h>
#include <Xm/ScrolledW.h>
#include <Xm/RowColumn.h>
#include <Xm/MessageB.h>
#include <Xm/MenuShell.h>
#include "rov.h"
#include "rdmif.h"
#include <dm_errno.h>
#include <signal.h>
#include <malloc.h>


/************************/
/* External Functions	*/
/************************/

Extern Void	initIbc( Void );


/************************/
/* External Data	*/
/************************/

Extern Select testMotorSel;


/************************/
/* Global Data		*/
/************************/

Global XtAppContext appcontext;		/* The application context	    */
Global Widget	toplevel, appForm;	/* Top level widget, top form	    */
Global Widget	ibcRowColumn;		/* Parent to all IBC group RowCols  */
Global AppData	appdata;		/* Application-wide resources	    */

Global Nat32		typeSizes[] =
{ 0, 0, sizeof(char), sizeof(char), sizeof(Int16), sizeof(Nat16), 
  sizeof(Int32), sizeof(Nat32), sizeof(MBool), sizeof(Flt32), sizeof(Flt64),
  sizeof(void *), sizeof(int) };

Global char		*ibcAlarmStrings[] = { "OK", "Warning", "Alarm" };

Global char		*motorStatus[] = 
{ "Unknown", "OK", "Control Voltage Alarm", "Temperature Error", "Stalled",
  "Resolver Failure", "OverCurrent", "Misc Fault" };

Global char	buff[4096];		/* Misc buffer used application-wide*/


/************************/
/* Forward Declarations	*/
/************************/

Widget	createIbcForm(Widget parent);
Widget	createQuitButton(Widget parent);
Void	terminate(Void);
Void	terminateCallback(Widget w, XtPointer unused, XmAnyCallbackStruct *cbs);


/********************************/
/* Application-wide Resources	*/
/********************************/

MLocal XtResource resources[] =		
{
  { "datamgr", XtCString, XtRString, sizeof(String), 
    XtOffset(AppDataPtr, datamgr), XtRString,
    "/usr/vw/mbari/dm/unix/datamgrd" },
  { "alarm_update", "Rate", XtRInt, sizeof(int), 
    XtOffset(AppDataPtr, alarm_update), XtRImmediate, (caddr_t)500 },
  { "ibc_update", "Rate", XtRInt, sizeof(int), 
    XtOffset(AppDataPtr, ibc_update), XtRImmediate, (caddr_t)500 },
  { "pwrerr_fg", XtCForeground, XtRPixel, sizeof(Pixel),
    XtOffset(AppDataPtr, pwrerr_fg), XtRString, "White" },
  { "pwrerr_bg", XtCBackground, XtRPixel, sizeof(Pixel),
    XtOffset(AppDataPtr, pwrerr_bg), XtRString, "Red" },
  { "gf_current", XtCBackground, XtRPixel, sizeof(Pixel),
    XtOffset(AppDataPtr, gf_current_bg), XtRString, "SlateBlue3" },
  { "debug", "BitField", XtRInt, sizeof(DWord),
    XtOffset(AppDataPtr, debug), XtRImmediate, (caddr_t)0 },
  { "bell", XtCBoolean, XtRBoolean, sizeof(Boolean),
    XtOffset(AppDataPtr, ring_bell), XtRImmediate, (caddr_t)True }
};

MLocal String fallback_resources[] =
{
    "*geometry:		=650x800", 
    "*background:	SlateBlue",
    "*foreground:	White",
    "*labelColor:	White",
    "*fontList:	variable",
    NULL
};


/************************************************************************/
/* Function    : main							*/
/* Purpose     : Main Routine for ROV User Interface			*/
/* Inputs      : argc, argv						*/
/* Outputs     : None							*/
/* Comments    : Created by Builder Xcessory, modified by Bob Herlien	*/
/************************************************************************/
    void
main(int argc, char ** argv)
{
    Reg Errno	rtn;
    Atom	wmDeleteAtom;
    Widget	quitButton;

/* Set signal handlers if user trys to quit				*/
    signal( SIGINT, terminate );
    signal( SIGQUIT, terminate );
    signal( SIGTERM, terminate );

    toplevel = XtAppInitialize( &appcontext, "MotorTest",
			        (XrmOptionDescList)NULL,
			        0, &argc, argv, fallback_resources,
			        (ArgList)NULL, 0 );
    XmRegisterConverters();

    XtGetApplicationResources( toplevel, &appdata, resources, 
			       XtNumber(resources), (ArgList)NULL, 0 );

    if ( (rtn = rdm_init()) != OK )		/* Initialize Data manager */
    {
	if ( rtn == EDM_NO_DAEMON )
	{
	    fprintf(stderr, "Data Manager isn't running\n");
	    fprintf(stderr, "Execute %s and try again\n", appdata.datamgr);
	}
	else
	    fprintf(stderr, "Data Manager initialization error %#x\n", rtn);
	exit(1);
    }

    appForm = createIbcForm( toplevel );
    XtRealizeWidget( toplevel );
/*  quitButton = createQuitButton( toplevel );  */
    initIbc();

    if ( testMotorSel.select != NULLF )
	(*testMotorSel.select)(&testMotorSel);	/* Call IBC select func	*/

    testMotorSel.status->current = &testMotorSel;

    wmDeleteAtom = XmInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", False);
    XmAddWMProtocolCallback( toplevel, wmDeleteAtom, 
			    (XtCallbackProc)terminateCallback, NULL );

    XtAppMainLoop( appcontext );

} /* main() */


/************************************************************************/
/* Function    : createIbcForm						*/
/* Purpose     : Create the form to put motortest IBC widgets into	*/
/* Inputs      : Parent widget						*/
/* Outputs     : Ibc window widget					*/
/************************************************************************/
	Widget
createIbcForm( Widget parent )
{
    Widget	ibcScrolledWindow;

    XtInitializeWidgetClass(xmScrolledWindowWidgetClass);
    ibcScrolledWindow = XtVaCreateManagedWidget("ibcScrolledWindow",
				xmScrolledWindowWidgetClass, parent,
				XmNscrollingPolicy, XmAUTOMATIC,
				NULL);

    XtInitializeWidgetClass(xmRowColumnWidgetClass);
    ibcRowColumn = XtVaCreateManagedWidget("ibcRowColumn",
		xmRowColumnWidgetClass,	ibcScrolledWindow,
		XmNrowColumnType, XmWORK_AREA, NULL );

    return( ibcScrolledWindow );

} /* createIbcForm() */


/************************************************************************/
/* Function    : createQuitButton					*/
/* Purpose     : Create "Quit" button					*/
/* Inputs      : Parent widget						*/
/* Outputs     : Button widget						*/
/************************************************************************/
	Widget
createQuitButton( Widget parent )
{
    Widget	menuShell, popupMenu;
    XmString	quitLabel, accelString;

    XtInitializeWidgetClass(xmMenuShellWidgetClass);
    menuShell = XtVaCreatePopupShell("menuShell",
				     xmMenuShellWidgetClass, parent, NULL );

    quitLabel = XmStringCreateSimple( "Quit" );
    accelString = XmStringCreateSimple( "Ctrl<Key>C" );

    popupMenu = XmVaCreateSimplePopupMenu(menuShell, "quitButton",
					  (XtCallbackProc)terminateCallback,
					  XmVaPUSHBUTTON,
					  quitLabel, XK_Cancel,
					  "Ctrl<Key>C", accelString,
					  NULL);
    XmStringFree( quitLabel );
    XmStringFree( accelString );
    XtManageChild( popupMenu );
    return( popupMenu );

} /* createQuitButton() */


/************************************************************************/
/* Function    : terminate						*/
/* Purpose     : Terminate ROV User Interface				*/
/* Inputs      : None							*/
/* Outputs     : None							*/
/* Comments    : Never returns						*/
/************************************************************************/
     Void
terminate( Void )
{
    if ( testMotorSel.unselect != NULLF )
	(*testMotorSel.unselect)(&testMotorSel);

    rdm_task_exit();
    exit(0);

} /* terminate() */


/************************************************************************/
/* Function    : terminateCallback					*/
/* Purpose     : Callback for Close Window user action on Main window	*/
/* Inputs      : Widget, unused pointer, unused callback struct		*/
/* Outputs     : None							*/
/* Comments    : Never returns						*/
/************************************************************************/
     Void
terminateCallback( Widget w, XtPointer unused, XmAnyCallbackStruct *cbs )
{
    terminate();

} /* terminateCallback() */


/************************************************************************/
/* Function    : deleteWidget						*/
/* Purpose     : Callback to delete a widget				*/
/* Inputs      : Widget ID, Client data pointer, CallbackStruct pointer	*/
/* Outputs     : None							*/
/************************************************************************/
    Void
deleteWidget( Widget w, XtPointer unused, XmAnyCallbackStruct *call_data )
{
    XtDestroyWidget( w );

} /* deleteWidget() */


/************************************************************************/
/* Function    : rovError						*/
/* Purpose     : Create and pop up an Error dialog			*/
/* Inputs      : Parent, Message String					*/
/* Outputs     : Dialog Widget ID					*/
/************************************************************************/
	Widget
rovError( Widget parent, char *msg )
{
    Arg    	args[10];
    Cardinal   	argcnt;
    XmString	str;
    Widget	dialog;

    argcnt = 0;
    str = XmStringCreateLtoR( msg, XmSTRING_DEFAULT_CHARSET );
    XtSetArg(args[argcnt], XmNmessageString, str); argcnt++;

    dialog = XmCreateErrorDialog(parent, "rov_error", args, argcnt);

    XmStringFree( str );

    XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
    XtAddCallback( dialog, XmNokCallback, (XtCallbackProc)deleteWidget, NULL );
    XtManageChild( dialog );

    return( dialog );

} /* rovError() */


/************************************************************************/
/* Function    : rovMalloc						*/
/* Purpose     : Alloc memory, display error message if none		*/
/* Inputs      : Number of bytes to allocate				*/
/* Outputs     : Return code from malloc()				*/
/************************************************************************/
	char *
rovMalloc( Nat32 size )
{
    char	*rtn;

    if ( (rtn = malloc(size)) == NULL )
	rovError(appForm, "Out of memory\n");

    return( rtn );

} /* rovMalloc() */


/************************************************************************/
/* Function    : rovCreateQuestionDialog				*/
/* Purpose     : Create a question dialog without a Help Button		*/
/* Inputs      : Parent, Title String, Message String			*/
/* Outputs     : Dialog Widget ID					*/
/************************************************************************/
	Widget
rovCreateQuestionDialog( Widget parent, char *title, char *msg )
{
    Arg    	args[10];
    Cardinal   	argcnt;
    XmString	str, str1;
    Widget	dialog;

    argcnt = 0;
    str = XmStringCreateSimple( title );
    XtSetArg(args[argcnt], XmNdialogTitle, str); argcnt++;
    str1 = XmStringCreateLtoR( msg, XmSTRING_DEFAULT_CHARSET );
    XtSetArg(args[argcnt], XmNmessageString, str1); argcnt++;

    dialog = XmCreateQuestionDialog(parent, "question_popup", args, argcnt);

    XmStringFree( str );
    XmStringFree( str1 );

    XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));

    return( dialog );

} /* rovCreateQuestionDialog() */


/************************************************************************/
/* Function    : printType						*/
/* Purpose     : Printf data of given type into buffer			*/
/* Inputs      : Type of data, Num elements (for character data only),	*/
/*		 Data to print, buffer to print into			*/
/* Outputs     : Number of characters printed				*/
/************************************************************************/
     Int32
printType( DM_Type dtype, Nat32 nels, char *dat, char *buff )
{
    TypeUnion	udat;
    Reg Int32	rtn, i;

    bzero( &udat, sizeof(udat) );
    bcopy( dat, &udat, sizeof(udat) );

    switch( dtype )
    {
      case DM_EMPTY:
	buff[0] = '\0';
	return( 0 );

      case DM_CHAR:
      case DM_UCHAR:
	for ( i = rtn = 0; i < nels; i++ )
	{
	    if ( dat[i] == '\0' )
		break;
	    if ( isprint(dat[i]) )
		buff[rtn++] = dat[i];
	    else
		rtn += sprintf( buff + rtn, "\\%x", (Nat32)dat[i] );
	}
	buff[rtn] = '\0';
	return( rtn );

      case DM_INT16:
      case DM_MBOOL:
	return( sprintf(buff, "%hd", udat.int16) );

      case DM_NAT16:
	return( sprintf(buff, "%hu", udat.nat16) );
	    
      case DM_INT32:
      case DM_ENUM:
	return( sprintf(buff, "%d", udat.int32) );

      case DM_NAT32:
	return( sprintf(buff, "%u", udat.nat32) );

      case DM_FLT32:
	return( sprintf(buff, "%g", udat.flt32) );

      case DM_FLT64:
	return( sprintf(buff, "%lg", udat.flt64) );

      case DM_PTR:
	return( sprintf(buff, "%#x", udat.ptr) );

    } /* switch */

} /* printType() */


/************************************************************************/
/* Stuff not really used but here to satisfy common sources with GUI	*/
/************************************************************************/

/************************************************************************/
/* Function    : graphItemCnsmr						*/
/* Purpose     : None							*/
/* Inputs      : Don't care						*/
/* Outputs     : None							*/
/************************************************************************/
	Void
graphItemCnsmr( DM_Item item, Nat32 period )
{
} /* graphItemCnsmr() */


/************************************************************************/
/* Function    : graphItemInUse						*/
/* Purpose     : None							*/
/* Inputs      : Don't care						*/
/* Outputs     : FALSE							*/
/************************************************************************/
	MBool
graphItemInUse( DM_Item item )
{
    return( FALSE );

} /* graphItemInUser() */
