/******************************************************************************
 * Toolkit for building distributed control systems or any other distributed system.
 *
 * Copyright (c) 1990-2005 by European Synchrotron Radiation Facility,
 *                            Grenoble, France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * File          :  xdev_cb.c
 *
 * Project       :  Xdevmenu application (new generation made by BX)
 *
 * Description   :  The module which contains all the entry points for callbacks
 *
 * Author(s)     :  Builder Xcessory then completed by Faranguiss Poncet
 *		    $Author: jkrueger1 $
 *
 * Original      :  February 1997
 *
 * Date:	    $Date: 2008/04/06 09:08:04 $
 */

#ifdef HAVE_CONFIG_H
#	include "config.h"
#endif

/*
 * README: This file is appended to at file generation time.
 * Edits can be made throughout the file
 */
/*
 * Generated by the ICS Builder Xcessory (BX).
 *
 * Builder Xcessory 4.0
 * Code Generator Xcessory 2.0 (09/09/96)
 *
 */
#include <Xm/Xm.h>
#include <Xm/SelectioB.h>
#include <Xm/Text.h>
#include <Xm/ScrolledW.h>
#include <Xm/PanedW.h>
#include <Xm/MessageB.h>
#include <Xm/List.h>
#include <Xm/ToggleB.h>


/*
 * Standard includes for builtins.
 */
#include <stdio.h>
#include <string.h>
#include <ctype.h>


/*
 * Application includes
 */
#include "xdev_gui.h"
#include "xdev_dev.h"
#include <API.h>

extern Widget  gui_widget_array[];

/*
 * Macros to make code look nicer between ANSI and K&R.
 */
#ifndef ARGLIST
#if (NeedFunctionPrototypes == 0)
#define PROTOTYPE(p)	()
#define ARGLIST(p)	p
#define ARG(a, b)	a b;
#define GRA(a, b)	a b;
#define UARG(a, b)      a b;
#define GRAU(a, b)      a b;
#else
#define PROTOTYPE(p)	p
#define ARGLIST(p)	(
#define ARG(a, b)	a b,
#define GRA(a, b)	a b)
#ifdef __cplusplus
#define UARG(a, b)      a,
#define GRAU(a, b)      a)
#else
#define UARG(a, b)      a b,
#define GRAU(a, b)      a b)
#endif
#endif
#endif

Widget		BxFindTopShell PROTOTYPE((Widget));
WidgetList	BxWidgetIdsFromNames PROTOTYPE((Widget, char*, char*));

void gui_display_dev_info(char  *, char  *, char  *, char  *, char  *);

extern long dev_free_sig_struct(long , DevVarFloatArray *, DevVarDoubleArray *);
extern long dev_read_sig_values(int , DevVarStringArray *, DevVarFloatArray *,
                                       DevVarDoubleArray *, char **, char  **);
extern void gui_display_sigs(DevVarStringArray , long , DevVarFloatArray ,
                             DevVarDoubleArray , char  *);


/*** for forward reference ***/
void cb_device_import( Widget , XtPointer , XtPointer );


/*** local static variables ***/
static  char   *current_rpc_protocol=NULL;

/*
 *  BX predefined Callbacks are included here
 *  -----------------------------------------
 */


/*      Function Name:	BxExitCB
 *
 *      Description:   	This functions expects an integer to be passed in
 *		       	client data.  It calls the exit() system call with
 *			the integer value as the argument to the function.
 *
 *      Arguments:      Widget		w: 	the activating widget.
 *			XtPointer	client:	the integer exit value.
 *			XtPointer	call:	the call data (unused).
 */

#ifdef VMS
#include <stdlib.h>
#endif

/* ARGSUSED */
void
BxExitCB ARGLIST((w, client, call))
UARG( Widget, w)
ARG( XtPointer, client)
GRAU( XtPointer, call)
{
    int		exitValue = (int)client;
    
    exit(exitValue);
}

/*      Function Name: 	BxManageCB
 *
 *      Description:   	Given a string of the form:
 *		       	"(WL)[widgetName, widgetName, ...]"
 *			BxManageCB attempts to convert the name to a Widget
 *			ID and manage the widget.
 *
 *      Arguments:     	Widget	    w:      the widget activating the callback.
 *		       	XtPointer   client: the list of widget names to attempt
 *					    to find and manage.
 *		       	XtPointer   call:   the call data (unused).
 *
 *      Notes:        *	This function expects that there is an application
 *		       	shell from which all other widgets are descended.
 */

/* ARGSUSED */
void
BxManageCB ARGLIST((w, client, call))
ARG( Widget, w)
ARG( XtPointer, client)
GRAU( XtPointer, call)
{
    WidgetList		widgets;
    int			i;

    /*
     * This function returns a NULL terminated WidgetList.  The memory for
     * the list needs to be freed when it is no longer needed.
     */
    widgets = BxWidgetIdsFromNames(w, "BxManageCB", (String)client);

    i = 0;
    while( widgets && widgets[i] != NULL )
    {
	XtManageChild(widgets[i]);
	i++;
    }
    XtFree((char *)widgets);
}

/*      Function Name: 	BxUnmanageCB
 *
 *      Description:   	Given a string of the form:
 *		       	"(WL)[widgetName, widgetName, ...]"
 *			BxUnmanageCB attempts to convert the name to a Widget
 *			ID and unmanage the widget.
 *
 *      Arguments:     	Widget	    w:      the widget activating the callback.
 *		       	XtPointer   client: the list of widget names to attempt
 *					    to find and unmanage.
 *		       	XtPointer   call:   the call data (unused).
 *
 *      Notes:        *	This function expects that there is an application
 *		       	shell from which all other widgets are descended.
 */

/* ARGSUSED */
void
BxUnmanageCB ARGLIST((w, client, call))
ARG( Widget, w)
ARG( XtPointer, client)
GRAU( XtPointer, call)
{
    WidgetList		widgets;
    int			i;

    /*
     * This function returns a NULL terminated WidgetList.  The memory for
     * the list needs to be freed when it is no longer needed.
     */
    widgets = BxWidgetIdsFromNames(w, "BxUnmanageCB", (String)client);

    i = 0;
    while( widgets && widgets[i] != NULL )
    {
	XtUnmanageChild(widgets[i]);
	i++;
    }
    XtFree((char *)widgets);
}

/*
 *  End of the BX predefined Callbacks
 *  -----------------------------------
 */









/****************************************************************************
                                                                           
 Function     : void ccb_save_widget_id()

 Description  : create callback attached to all widgets which need to be save
                for further use in the application. The widget Id is stored
                in the widget array.

 Arg(s) In    : Widget      w           : The widget Id to be stored.
                XtPointer   client_data : the index in the widget array where
                                          the widget Id should be stored.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void ccb_save_widget_id( Widget w, XtPointer client_data, XtPointer call_data)
{
    int       widget_index;

    widget_index = (int) client_data;

    gui_widget_array[widget_index] = w;
}





/****************************************************************************
                                                                           
 Function     : void ccb_dev_import_selbox()

 Description  : create callback attached to the selection box widget related
                to the selection of a device name to be imported. This creation
                callback sets the Default Button of the Parent Widget "form"
                to the "helpPushButton" which is in fact displayed as "Filter".

 Arg(s) In    : Widget      w           : The widget Id of the selection box.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void ccb_dev_import_selbox(Widget w, XtPointer client_data, XtPointer call_data)
{
    Widget       filterPB, listW;

    filterPB = XmSelectionBoxGetChild(w, XmDIALOG_HELP_BUTTON);

    XtVaSetValues( w, XmNdefaultButton, filterPB, NULL);
    XtVaSetValues( XtParent(w), XmNdefaultButton, filterPB, NULL);

    listW = XmSelectionBoxGetChild(w, XmDIALOG_LIST);
    XtAddCallback(listW, XmNdefaultActionCallback, cb_device_import, (XtPointer)0);


}






/****************************************************************************
                                                                           
 Function     : void ccb_file_cb()

 Description  : create callback attached to the "File" cascade button of the
                menu bar. This callback is a work around a bug
                which comes with the usage of HP VUE and Motif 1.2. It concerns
                the background colour of the Menu Bar.

 Arg(s) In    : Widget      w           : The widget Id of the exit pushbutton.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void ccb_file_cb( Widget w, XtPointer client_data, XtPointer call_data)
{
    Pixel      bg;

    XtVaGetValues(w, XmNbackground, &bg, NULL);
    XtVaSetValues( XtParent(w), XmNbackground, bg, NULL);
}






/****************************************************************************
                                                                           
 Function     : void ccb_cmd_sel_box()

 Description  : create callback attached to the selection box widget related
                to the selection of a command to be executed. This creation
                callback removes the Help button in this window.

 Arg(s) In    : Widget      w           : The widget Id of the selection box.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void ccb_cmd_sel_box( Widget w, XtPointer client_data, XtPointer call_data)
{
    Widget       helpPB;

    helpPB = XmSelectionBoxGetChild(w, XmDIALOG_HELP_BUTTON);
    XtUnmanageChild(helpPB);

}







/****************************************************************************
                                                                           
 Function     : void ccb_help_version_text()

 Description  : create callback attached to the text widget in the help on
                version dialog window. This create callback initializes the
                text string inside this window.

 Arg(s) In    : Widget      w           : The widget Id of the text widget
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/
void ccb_help_version_text( Widget w, XtPointer client_data, XtPointer call_data)
{
   char      message_txt[301];
   char      revision_text[120];
   char      *rev_nb_pointer;
   size_t    nb_chars;
   int       cur_posit;

   strcpy(revision_text , "$Revision: 1.3 $");

   rev_nb_pointer = strstr(revision_text, ":");
   rev_nb_pointer++;
   nb_chars = strcspn(rev_nb_pointer, "$");

   strcpy(message_txt, "\n\n               XDEVMENU  application");
   strcat(message_txt, "\n\n                       Version : ");
   strncat(message_txt, rev_nb_pointer, nb_chars);
   strcat(message_txt, "\n\n\n\n\n             ESRF Computing Services\n ");

   cur_posit = XmTextGetLastPosition (gui_widget_array[GUI_HELP_VERS_TEXT]);
   XmTextReplace( gui_widget_array[GUI_HELP_VERS_TEXT],
                  0, cur_posit, message_txt);

}






/****************************************************************************
                                                                           
 Function     : void ccb_confirm_messbox()

 Description  : create callback attached to the confirmation window's message
                box. This callback is used to remove the help button in this
                message box.

 Arg(s) In    : Widget      w           : The widget Id of the message box
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/
void ccb_confirm_messbox( Widget w, XtPointer client_data, XtPointer call_data)
{
   Widget   help_pb;

   help_pb = XmMessageBoxGetChild(w, XmDIALOG_HELP_BUTTON);
   XtUnmanageChild(help_pb);

}







/****************************************************************************
                                                                           
 Function     : void ccb_error_messbox()

 Description  : create callback attached to the error window's message
                box. This callback is used to remove the help and cancel
                buttons in this message box.

 Arg(s) In    : Widget      w           : The widget Id of the message box
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/
void ccb_error_messbox( Widget w, XtPointer client_data, XtPointer call_data)
{
   Widget   help_pb, cancel_pb;

   help_pb = XmMessageBoxGetChild(w, XmDIALOG_HELP_BUTTON);
   cancel_pb = XmMessageBoxGetChild(w, XmDIALOG_CANCEL_BUTTON);
   XtUnmanageChild(help_pb);
   XtUnmanageChild(cancel_pb);

}








/****************************************************************************
                                                                           
 Function     : void ccb_timeout_prompt()

 Description  : create callback attached to the selection box widget related
                to the prompt window for the change of the timeout value.
                Removes the help button in this window.

 Arg(s) In    : Widget      w           : The widget Id of the selection box.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/
void ccb_timeout_prompt( Widget w, XtPointer client_data, XtPointer call_data)
{
    Widget       help_pb;


    help_pb = XmSelectionBoxGetChild(w, XmDIALOG_HELP_BUTTON);
    XtUnmanageChild(help_pb);

}







/****************************************************************************
                                                                           
 Function     : void cb_fill_dev_selbox()

 Description  : callback attached to the filter pushbutton in the selection box
                widget related to the selection of a device name to be imported.
                This function fills in the list of the items of the selection
                box, taking into account the filters specified in other text
                widgets of the same window.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_fill_dev_selbox( Widget w, XtPointer client_data, XtPointer call_data)
{
    char            *textw_str;
    char            dom_mask[101], family_mask[101], member_mask[101];
    long            status;
    char            **device_names;
    unsigned int    nb_devices;
    char            *error_str=NULL;
    char            *err_disp;


    textw_str = XmTextGetString(gui_widget_array[GUI_DOMAIN_TEXT]);
    strcpy(dom_mask, textw_str);
    XtFree(textw_str);

    textw_str = XmTextGetString(gui_widget_array[GUI_FAMILY_TEXT]);
    strcpy(family_mask, textw_str);
    XtFree(textw_str);

    textw_str = XmTextGetString(gui_widget_array[GUI_MEMBER_TEXT]);
    strcpy(member_mask, textw_str);
    XtFree(textw_str);

    device_names = NULL;
    nb_devices = 0;
    error_str = NULL;
    status = dev_get_exported_devices(dom_mask, family_mask, member_mask,
                                                &device_names, &nb_devices,
                                                &error_str);

    if (status == XDEV_NOTOK)
    {
       if (error_str != NULL)
          err_disp = (char *) malloc (strlen(error_str)+501);
       else
          err_disp = (char *) malloc (501);

       strcpy (err_disp, "Cannot find the list of the exported devices.\n");
       strcat(err_disp, "\n");

       if (error_str != NULL)
          strcat(err_disp, error_str);

       gui_display_error(err_disp);
       if (error_str != NULL)
       {
          free(error_str);
          error_str = NULL;
       };
       free(err_disp);
       return;
    }

    gui_fill_dev_list(nb_devices, device_names);

    status = dev_free_dev_names(&device_names, &error_str);
    if (status == XDEV_NOTOK)
       if (error_str != NULL) free(error_str);

    return;

}







/****************************************************************************
                                                                           
 Function     : void cb_activate_text_filter()

 Description  : "activate" callback attached to the text widgets (domain,
                family and member) of the device import dialogue window.
                This callback is called when the user types in "return" in one
                of these text.
                This function will simply call "cb_fill_dev_selbox" to make
                the filter to be taken into account.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_activate_text_filter( Widget w, XtPointer client_data, XtPointer call_data)
{
    cb_fill_dev_selbox(w, (XtPointer) NULL, (XtPointer) NULL);
}






/****************************************************************************
                                                                           
 Function     : void cb_device_import()

 Description  : callback attached to the "import" pushbutton in the selection
                box widget related to the selection of a device name to be
                imported.
                This function will try to import the device. If succeeded
                it builds up all the necessary and internal data structures
                to handle the device included the icon ...etc.
                Otherwise the function displays an error message.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_device_import( Widget w, XtPointer client_data, XtPointer call_data)
{
   XmSelectionBoxCallbackStruct    *selbox_cbs;
   Boolean                         xms_status;
   long                            status;
   int                             dev_index;
   char                            *dev_name, *error_str=NULL, *err_disp;


   selbox_cbs = (XmSelectionBoxCallbackStruct *) call_data;

   dev_name = NULL;
   xms_status = XmStringGetLtoR( selbox_cbs->value, XmFONTLIST_DEFAULT_TAG,
                                                    &dev_name);

   if (xms_status == False)
   {
      gui_display_error("Cannot find the name of the device to import.\n");
      return;
   };

   error_str = NULL;
   status = dev_import_device(dev_name, &dev_index, &error_str);

   if (status == XDEV_NOTOK)
   {
      if (error_str != NULL)
         err_disp = (char *) malloc (strlen(error_str)+501);
      else
         err_disp = (char *) malloc (501);

      strcpy (err_disp, "Cannot import this device.\n");
      strcat(err_disp, "\n");

      if (error_str != NULL) strcat(err_disp, error_str);

      gui_display_error(err_disp);
      if (error_str != NULL)
      {
         free(error_str);
         error_str = NULL;
      };
      free(err_disp);
      return;
   }

   gui_add_device(dev_name, dev_index);

   free(dev_name);

   return;
}






/****************************************************************************
                                                                           
 Function     : void cb_select_device()

 Description  : callback attached to one of the pushbutton of the icon
                associated to an imported device.
                When the icon is selected, it will be highlighted by a thick
                border, and the command window will be updated and displayed.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : the index of the selected device
                                          in the internal arrays.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_select_device( Widget w, XtPointer client_data, XtPointer call_data)
{
   long     status;
   int      dev_index, nb_cmd=0;
   char     **cmd_names = NULL;
   char     *err_disp;

   dev_index = (int) client_data;
   status = dev_get_cmd_names( dev_index, &cmd_names , &nb_cmd );

   if (status == XDEV_NOTOK)
   {
     err_disp = (char *) malloc (101);
     strcpy (err_disp, "Cannot find the list of the commands.\n");
     strcat(err_disp, "\n");
     gui_display_error(err_disp);
     free(err_disp);
     return;
   }

   gui_select_device(dev_index);
   gui_show_cmds( cmd_names, nb_cmd );

   status = dev_free_cmd_names(&cmd_names, nb_cmd);

   if (status == XDEV_NOTOK)
   {
     err_disp = (char *) malloc (101);
     strcpy (err_disp, "Cannot free the list of the command names.\n");
     strcat(err_disp, "\n");
     gui_display_error(err_disp);
     free(err_disp);
   }
}








/****************************************************************************
                                                                           
 Function     : void cb_execute_cmd()

 Description  : callback attached "Execute" button of the command selection
                box. This callback will find out which device and which
                command are selected. Then it will execute the command on that
                device and displays the result in the result window (bottom
                area of the main window).

 Arg(s) In    : Widget      w           : command selection box.
                XtPointer   client_data : unused.
                XtPointer   call_data   : selected command name.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_execute_cmd( Widget w, XtPointer client_data, XtPointer call_data)
{
    XmSelectionBoxCallbackStruct  *selbox_cbs;
    char                          *cmd_name, name_cmd[101];
    Boolean                       xms_status;
    Widget                        listW;
    int                           item_pos, ind_cmd, ind_dev;
    long                          status;
    char                          *err_str=NULL, *out_str=NULL, *time_str=NULL;
    char                          name_in[101], name_out[101];
    char                          *in_name, *out_name;
    long                          type_in, type_out;
    char                          buffer[101];
    char                          *err_disp;
    DevVarStringArray             sig_conf;
    DevVarFloatArray              sig_vals_f;
    DevVarDoubleArray             sig_vals_d;




    selbox_cbs = (XmSelectionBoxCallbackStruct *) call_data;

    listW = XmSelectionBoxGetChild(w, XmDIALOG_LIST);

    item_pos = XmListItemPos(listW, selbox_cbs->value);

    if (item_pos < 1)
    {
       gui_display_error("Cannot find the index of the command to execute.\n");
       return;
    };

    ind_cmd = item_pos - 1;
    ind_dev = gui_get_selected_dev();

    if (ind_dev < 0)
    {
       gui_display_error("Click on an icon to select a device first.\n");
       return;
    };

    in_name = (char *) name_in;
    out_name = (char *) name_out;
    cmd_name = (char *) name_cmd;
    status = dev_get_cmd_profile( ind_dev, ind_cmd, &cmd_name,
                                                    &in_name, &out_name,
                                                    &type_in, &type_out,
                                                    &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
          err_disp = (char *) malloc (strlen(err_str)+501);
       else
          err_disp = (char *) malloc (501);

       strcpy (err_disp, "Cannot execute this command.\n");
       strcat(err_disp, "\n");

       if (err_str != NULL) strcat(err_disp, err_str);

       gui_display_error(err_disp);
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, NULL, err_str, NULL);
          free(err_str);
          err_str = NULL;
       };

       free(err_disp);
       return;
    }
    
    if ( (type_in == D_VOID_TYPE) 
         && ( (type_out == D_VAR_FLOATARR) || (type_out == D_VAR_DOUBLEARR) )
         && (strcmp(cmd_name, "DevReadSigValues")==0)
	 && (dev_sig_interface_exist(ind_dev) == 0) )
    {
       sig_conf.length=0;
       sig_conf.sequence = NULL;
       sig_vals_f.length = 0;
       sig_vals_f.sequence = NULL;
       sig_vals_d.length = 0;
       sig_vals_d.sequence = NULL;
       status = dev_read_sig_values(ind_dev, &sig_conf,
                                             &sig_vals_f, &sig_vals_d,
                                             &time_str, &err_str);
						      
       if (status == XDEV_NOTOK)
       {
	  if (err_str != NULL)
	  {
             gui_error_out(ind_dev, cmd_name, err_str, time_str);
             /** free(err_str); **/
             err_str = NULL;
	  }

	  if (time_str != NULL)
	  {
             /** free(time_str); **/
             time_str = NULL;
	  };

	  return;
       }
       
       /*** XDEV_OK for dev_read_sig_values ***/
       gui_display_sigs(sig_conf, type_out, sig_vals_f, sig_vals_d, time_str);
       
       status = dev_free_sig_struct(type_out, &sig_vals_f, &sig_vals_d);
       return;
    }

  
    if (type_in != D_VOID_TYPE)
    {
       gui_display_argin_window(ind_cmd, in_name, type_in);
       return;
    }

    status = dev_exec_cmd( ind_dev, ind_cmd, buffer,
                                             &out_str, &time_str, &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, cmd_name, err_str, time_str);
          /** free(err_str); **/
          err_str = NULL;
       }

       if (time_str != NULL)
       {
          /** free(time_str); **/
          time_str = NULL;
       };

       return;
    }

    if (type_out == D_VOID_TYPE)
       gui_display_arg_out( cmd_name, NULL, type_out, " ", time_str );
    else
       gui_display_arg_out( cmd_name, name_out, type_out, out_str, time_str );


    if (out_str != NULL)
    {
       /** free(out_str); **/
       out_str = NULL;
    };

    if (time_str != NULL)
    {
       /** free(time_str); **/
       time_str = NULL;
    };
}










/****************************************************************************
                                                                           
 Function     : void cb_execute_cmd_input()

 Description  : callback attached "Execute" button of the input argument dialog
                window.  This callback will find out which device and which
                command are current. Then it will readout the input argument
                typed in the input argument dialog window. And finally it will
                execute the command on that device and displays the result in
                the result window and also in the Historical Error Window and
                in the Output Parametre Window.

 Arg(s) In    : Widget      w           : execute push button.
                XtPointer   client_data : unused.
                XtPointer   call_data   : selected command name.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_execute_cmd_input( Widget w, XtPointer client_data, XtPointer call_data)
{
    int                ind_cmd, ind_dev;
    long               status;
    char               *err_str=NULL, *out_str=NULL, *time_str=NULL;
    char               *cmd_name, name_cmd[101];
    char               name_in[101], name_out[101];
    char               *in_name, *out_name;
    long               type_in, type_out;
    char               *err_disp;
    char               *in_string=NULL;
    char               *in_string_copy;




    status = gui_get_selected_dev_cmd(&ind_dev, &ind_cmd);

    if (status == XDEV_NOTOK)
    {
       err_disp = (char *) malloc (301);

       strcpy (err_disp, "Cannot execute the command.\n\n");
       strcat(err_disp, "Either the device or the command are not selected.\n");
       strcat(err_disp, "Ignored\n");

       gui_display_error(err_disp);

       free(err_disp);
       return;
    }

    in_name = (char *) name_in;
    out_name = (char *) name_out;
    cmd_name = (char *) name_cmd;
    status = dev_get_cmd_profile( ind_dev, ind_cmd, &cmd_name,
                                                    &in_name, &out_name,
                                                    &type_in, &type_out,
                                                    &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
          err_disp = (char *) malloc (strlen(err_str)+501);
       else
          err_disp = (char *) malloc (501);

       strcpy (err_disp, "Cannot execute this command.\n");
       strcat(err_disp, "\n");

       if (err_str != NULL) strcat(err_disp, err_str);

       gui_display_error(err_disp);
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, NULL, err_str, NULL);
          free(err_str);
          err_str = NULL;
       };

       free(err_disp);
       return;
    }

    in_string = XmTextGetString(gui_widget_array[GUI_INARG_VAL_TEXT]);

    if (in_string == NULL)
    {
       gui_display_error("Cannot execute the command.\n\nNo input.\n");
       return;
    }

    if (in_string[0] == '\0')
    {
       gui_display_error("Cannot execute the command.\n\nNo input.\n");
       return;
    }
   
    in_string_copy = in_string;
    while (in_string_copy[0] == ' ')
         in_string_copy = in_string_copy + 1;

    status = dev_exec_cmd( ind_dev, ind_cmd, in_string_copy,
                                             &out_str, &time_str, &err_str);

    XtFree(in_string);
    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, cmd_name, err_str, time_str);
          /** free(err_str); **/
          err_str = NULL;
       };

       if (time_str != NULL)
       {
          /** free(time_str); **/
          time_str = NULL;
       };

       return;
    }

    if (type_out == D_VOID_TYPE)
       gui_display_arg_out( cmd_name, NULL, type_out, "  ", time_str );
    else
       gui_display_arg_out( cmd_name, name_out, type_out, out_str, time_str );


    if (out_str != NULL)
    {
       /** free(out_str); **/
       out_str = NULL;
    };

    if (time_str != NULL)
    {
       /** free(time_str); **/
       time_str = NULL;
    };

}











/****************************************************************************
                                                                           
 Function     : void cb_specifed_cmd()

 Description  : callback attached to "State" and "Status" pushbuttons in the
                "Commands" pulldown menu.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : specified command name.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_specified_cmd( Widget w, XtPointer client_data, XtPointer call_data)
{

    char        *cmd_name;
    int         ind_cmd, ind_dev;
    long        status;
    char        *err_str=NULL, *out_str=NULL, *time_str=NULL;
    char        name_in[101], name_out[101];
    char        *in_name, *out_name;
    long        type_in, type_out;
    char        buffer[101];
    char        *err_disp;




    cmd_name = (char *) client_data;

    ind_dev = gui_get_selected_dev();

    if (ind_dev < 0)
    {
       gui_display_error("Click on an icon to select a device first.\n");
       return;
    };

    in_name = (char *) name_in;
    out_name = (char *) name_out;
    status = dev_get_cmd_name_profile( ind_dev, cmd_name, &ind_cmd,
                                                    &in_name, &out_name,
                                                    &type_in, &type_out,
                                                    &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
          err_disp = (char *) malloc (strlen(err_str)+501);
       else
          err_disp = (char *) malloc (501);

       strcpy (err_disp, "Cannot execute this command.\n");
       strcat(err_disp, "\n");

       if (err_str != NULL) strcat(err_disp, err_str);

       gui_display_error(err_disp);
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, NULL, err_str, NULL);
          free(err_str);
          err_str = NULL;
       };

       free(err_disp);
       return;
    }

    if (type_in != D_VOID_TYPE)
    {
       gui_display_argin_window(ind_cmd, in_name, type_in);
       return;
    }

    status = dev_exec_cmd( ind_dev, ind_cmd, buffer,
                                             &out_str, &time_str, &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, cmd_name, err_str, time_str);
          /** free(err_str); **/
          err_str = NULL;
       };

       if (time_str != NULL)
       {
          /** free(time_str); **/
          time_str = NULL;
       };

       return;
    }

    if (type_out == D_VOID_TYPE)
       gui_display_arg_out( cmd_name, NULL, type_out, "  ", time_str );
    else
       gui_display_arg_out( cmd_name, name_out, type_out, out_str, time_str );

    if (out_str != NULL)
    {
       /** free(out_str); **/
       out_str = NULL;
    };

    if (time_str != NULL)
    {
       /** free(time_str); **/
       time_str = NULL;
    };
}









/****************************************************************************
                                                                           
 Function     : void cb_dev_info()

 Description  : callback attached to "Device Info" pushbutton in the
                "Commands" pulldown menu.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_dev_info( Widget w, XtPointer client_data, XtPointer call_data)
{
    int         ind_dev;
    long        status;
    char        *err_str=NULL, *err_disp=NULL;
    char        dev_name[101], dev_class[101], dev_type[101],
                server_name[101], server_host[101];
    char        *name_dev, *class_dev, *type_dev,
                *name_server, *host_server;



    ind_dev = gui_get_selected_dev();

    if (ind_dev < 0)
    {
       gui_display_error("Click on an icon to select a device first.\n");
       return;
    };

    name_dev = (char *) dev_name;
    class_dev = (char *) dev_class;
    type_dev = (char *) dev_type;
    name_server = (char *) server_name;
    host_server = (char *) server_host;
    status = dev_info_device(ind_dev, &name_dev, &class_dev, &type_dev,
                                                 &name_server, &host_server,
                                                 &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
          err_disp = (char *) malloc (strlen(err_str)+501);
       else
          err_disp = (char *) malloc (501);

       strcpy (err_disp, "Cannot get the information for the selected device.");
       strcat(err_disp, "\n\n");

       if (err_str != NULL)
          strcat(err_disp, err_str);

       gui_display_error(err_disp);
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, "dev_inform", err_str, NULL);
          free(err_str);
          err_str = NULL;
       };
       free(err_disp);
       return;
    }

    gui_display_dev_info(name_dev, class_dev, type_dev,
                                              name_server, host_server);

}






/****************************************************************************
                                                                           
 Function     : void cb_default_action()

 Description  : callback attached to one of the pushbutton of the icon
                associated to an imported device.
                This callback has effect only when there is a double click.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : used to see if there has been a
                                          double click.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_default_action( Widget w, XtPointer client_data, XtPointer call_data)
{
   XmPushButtonCallbackStruct      *pb_cbs;


   pb_cbs = (XmPushButtonCallbackStruct *) call_data;

   if (pb_cbs->click_count <= 1)
      return;

   cb_dev_info(w, (XtPointer) NULL, (XtPointer) NULL);
}








/****************************************************************************
                                                                           
 Function     : void cb_close_device()

 Description  : callback attached to the "OK" pushbutton of the confirmation
                window's message box. When the okcallback (this function) is
                called the user wants to close the connection to the selected
                device.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_close_device( Widget w, XtPointer client_data, XtPointer call_data)
{
    int         ind_dev;
    long        status;
    char        *err_str=NULL, *err_disp=NULL;



    ind_dev = gui_get_selected_dev();

    if (ind_dev < 0)
    {
       gui_display_error("Click on an icon to select a device first.\n");
       return;
    };

    status = dev_close_device(ind_dev, &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
          err_disp = (char *) malloc (strlen(err_str)+501);
       else
          err_disp = (char *) malloc (501);

       strcpy (err_disp, "Cannot close the connection to the selected device.");
       strcat(err_disp, "\n\n");

       if (err_str != NULL)
          strcat(err_disp, err_str);

       gui_display_error(err_disp);
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, "dev_free", err_str, NULL);
          free(err_str);
          err_str = NULL;
       };
       free(err_disp);
    }

    gui_remove_device(ind_dev);
}








/****************************************************************************
                                                                           
 Function     : void cb_prompt_timeout()

 Description  : callback attached to the "change RPC timeout..." pushbutton of
                the Commands pulldown menu. This callback will give the current
                timeout for the selected device in a window and pops up this
                window to wait for the user to change the time out value.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_prompt_timeout( Widget w, XtPointer client_data, XtPointer call_data)
{
    int         ind_dev;
    long        status, time_val;
    char        time_str[101];
    Widget      textW;
    int         cur_posit;


    ind_dev = gui_get_selected_dev();

    if (ind_dev < 0)
    {
       gui_display_error("Click on an icon to select a device first.\n");
       return;
    };

    status = dev_get_timeout(ind_dev, &time_val);

    if (status == XDEV_NOTOK)
       strcpy(time_str, "?????");
    else
       if (time_val <= 0)
          strcpy(time_str, "?????");
       else
          sprintf(time_str, "%ld", time_val);


    textW = XmSelectionBoxGetChild( gui_widget_array[GUI_TIMEOUT_SELBOX],
                                    XmDIALOG_TEXT);

    cur_posit = XmTextGetLastPosition(textW);
    XmTextReplace( textW, 0, cur_posit, time_str);

    XtManageChild( gui_widget_array[GUI_TIMEOUT_SELBOX] );

}









/****************************************************************************
                                                                           
 Function     : void cb_change_timeout()

 Description  : callback attached to the "change timeout" pushbutton of the
                timeout prompt window. This callback will change the RPC
                timeout for the selected device.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_change_timeout( Widget w, XtPointer client_data, XtPointer call_data)
{
    int         ind_dev;
    Widget      textW;
    char        *textw_val=NULL;
    long        time_val;
    long        status;
    char        *err_str=NULL, *err_disp=NULL;



    ind_dev = gui_get_selected_dev();

    if (ind_dev < 0)
    {
       gui_display_error("Click on an icon to select a device first.\n");
       return;
    };

    textW = XmSelectionBoxGetChild(w, XmDIALOG_TEXT);
    textw_val = XmTextGetString(textW);

    if (textw_val == NULL)
    {
       gui_display_error("No time out value specified. Ignored.\n");
       return;
    }

    if ( strlen(textw_val) == 0)
    {
       gui_display_error("No time out value specified. Ignored.\n");
       return;
    }

    time_val = atol(textw_val);
    XtFree(textw_val);

    if (time_val <= 0)
    {
       gui_display_error("Incorrect timeout value. Ignored.\n");
       return;
    }

    status = dev_change_timeout(ind_dev, time_val, &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
          err_disp = (char *) malloc (strlen(err_str)+501);
       else
          err_disp = (char *) malloc (501);

       strcpy (err_disp, "Cannot change the timeout for the selected device.");
       strcat(err_disp, "\n\n");

       if (err_str != NULL)
          strcat(err_disp, err_str);

       gui_display_error(err_disp);
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, "dev_rpc_timeout", err_str, NULL);
          free(err_str);
          err_str = NULL;
       };
       free(err_disp);
       return;
    }

}











/****************************************************************************
                                                                           
 Function     : void cb_unset_rpc_protocol()

 Description  : callback attached to the "change RPC protocol" pushbutton of the
                Commands pulldown menu. This callback will set the current
                rpc protocol to NULL. It also toggles out the corresponding
                togglebuttons.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void
cb_unset_rpc_protocol( Widget w, XtPointer client_data, XtPointer call_data)
{
   current_rpc_protocol = NULL;
   XmToggleButtonSetState (gui_widget_array[GUI_TCP_TB], False, False);
   XmToggleButtonSetState (gui_widget_array[GUI_UDP_TB], False, False);
}







/****************************************************************************
                                                                           
 Function     : void cb_protocol_entry()

 Description  : callback attached to the protocol Radio Box. This callback is
                invoked each time one of the toggle buttons inside the
                Radio Box is selected or Unselected.

                This function will update the current_rpc_protocol variable
                accordingly.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void
cb_protocol_entry( Widget w, XtPointer client_data, XtPointer call_data)
{

   XmRowColumnCallbackStruct     *rc_cbs;
   XmToggleButtonCallbackStruct  *tb_cbs;

   rc_cbs = (XmRowColumnCallbackStruct *) call_data;

   tb_cbs = (XmToggleButtonCallbackStruct *) (rc_cbs->callbackstruct);

   if (tb_cbs->set == False)
      current_rpc_protocol = NULL;
   else
      if ( rc_cbs->widget == gui_widget_array[GUI_TCP_TB] )
         current_rpc_protocol = "TCP";
      else
         if ( rc_cbs->widget == gui_widget_array[GUI_UDP_TB] )
            current_rpc_protocol = "UDP";
         else
            current_rpc_protocol = NULL;
   
}







/****************************************************************************
                                                                           
 Function     : void cb_protocol_change()

 Description  : callback attached to the "Set Protocol" pushbutton in the
                "Change RPC Protocol" window. If the current_rpc_protocol has
                a coherent value the rpc protocol is effectively changed.

 Arg(s) In    : Widget      w           : unused.
                XtPointer   client_data : unused.
                XtPointer   call_data   : unused.

 Arg(s) Out   : none

 Return(s)    : none
                                                                           
***************************************************************************/

void cb_protocol_change( Widget w, XtPointer client_data, XtPointer call_data)
{

    int         ind_dev;
    long        status;
    char        *err_str=NULL, *err_disp=NULL;



    ind_dev = gui_get_selected_dev();

    if (ind_dev < 0)
    {
       gui_display_error("Click on an icon to select a device first.\n");
       return;
    };

    if (current_rpc_protocol == NULL)
       return;

    if ( (strcmp(current_rpc_protocol, "TCP") != 0) &&
         (strcmp(current_rpc_protocol, "UDP") != 0)   )
       return;

    status = dev_change_rpc_protocol(ind_dev, current_rpc_protocol, &err_str);

    if (status == XDEV_NOTOK)
    {
       if (err_str != NULL)
          err_disp = (char *) malloc (strlen(err_str)+501);
       else
          err_disp = (char *) malloc (501);

       strcpy (err_disp, "Cannot change the RPC protocol for the selected device.");
       strcat(err_disp, "\n\n");

       if (err_str != NULL)
          strcat(err_disp, err_str);

       gui_display_error(err_disp);
       if (err_str != NULL)
       {
          gui_error_out(ind_dev, "dev_rpc_protocol", err_str, NULL);
          free(err_str);
          err_str = NULL;
       };
       free(err_disp);
       return;
    }

}

