 /*
  * Khoros: $Id: callbacks.c,v 1.5 1992/03/20 22:46:51 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: callbacks.c,v 1.5 1992/03/20 22:46:51 dkhoros Exp $";
#endif

 /*
  * $Log: callbacks.c,v $
 * Revision 1.5  1992/03/20  22:46:51  dkhoros
 * VirtualPatch5
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "forms.h"

#define MaxArg 25

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>             file name: callbacks.c                    <<<<
   >>>>                                                       <<<<
   >>>>		       Callback Routines                      <<<<
   >>>>                                                       <<<<
   >>>>       These are the XtCallbackProc's that are called  <<<<
   >>>>       when the user mouse clicks within the various   <<<<
   >>>>       buttons of the forms, and react appropriately,  <<<<
   >>>>       according to the type of button it is. Note     <<<<
   >>>>       that asciiString widgets (parameter boxes on    <<<<
   >>>>       selections) do not have callbacks.  When a      <<<< 
   >>>>       selection is "live" or has a scroll bar, the    <<<<
   >>>>       routine initiated by the user hitting <CR> in   <<<<
   >>>>       the string widget is an XtActionProc, not a     <<<<
   >>>>       callback.                                       <<<<
   >>>>                                                       <<<<
   >>>>                xvf_quit_master_cb()                   <<<<
   >>>>                xvf_quit_subform_cb()                  <<<<
   >>>>                xvf_subform_cb()                       <<<<
   >>>>                xvf_psuedo_subform_cb()                <<<<
   >>>>                xvf_guide_cb()                         <<<<
   >>>>                xvf_logic_opt_cb()                     <<<<
   >>>>                xvf_int_opt_cb()                       <<<<
   >>>>                xvf_int_incr_scroll_cb()               <<<<
   >>>>                xvf_int_flow_scroll_cb()               <<<<
   >>>>                xvf_float_opt_cb()                     <<<<
   >>>>                xvf_float_incr_scroll_cb()             <<<<
   >>>>                xvf_float_flow_scroll_cb()             <<<<
   >>>>                xvf_string_opt_cb()                    <<<<
   >>>>                xvf_input_opt_cb()                     <<<<
   >>>>                xvf_input_label_cb()                   <<<<
   >>>>                xvf_output_opt_cb()                    <<<<
   >>>>                xvf_output_label_cb()                  <<<<
   >>>>                xvf_toggle_opt_cb()                    <<<<
   >>>>                xvf_master_action_cb()                 <<<<
   >>>>                xvf_subform_action_cb()                <<<<
   >>>>                xvf_pane_action_cb()                   <<<<
   >>>>                xvf_master_help_button_cb()            <<<<
   >>>>                xvf_subform_help_button_cb()           <<<<
   >>>>                xvf_pane_help_button_cb()              <<<<
   >>>>                xvf_routine_cb()                       <<<<
   >>>>                xvf_glyph_cb()                         <<<<
   >>>>                xvf_unglyph_cb()                       <<<<
   >>>>                xvf_do_toggle()                        <<<<
   >>>>                xvf_change_opt_selected()              <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  */



/************************************************************
*
* Routine Name:  xvf_quit_master_cb
*
*      Purpose:  This is the callback for the "Quit" button on master form
*
*        Input:  widget     - the master quit button widget 
*	         clientData - structure used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/


void xvf_quit_master_cb(widget, clientData)
Widget widget;
caddr_t clientData;
{
   Callback_Data *cb_data;
   Line_Info     line_info;
   xvf_sub_form  *subform;
   char **database;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->formptr->db;
   subform = cb_data->subformptr;

   xvf_clear_line_info(&line_info);
   xvf_parse_quit_line(database[subform->button_index], &line_info);
   line_info.selected = true;
   xvf_deparse_quit_line(&line_info, database, subform->button_index);

   while (subform != NULL)
   {
	if ((subform->type==SubFormButton) && 
	    (subform->toplevel!=NULL) &&
	    (subform->selected == true))
	{
	   XtUnmapWidget(subform->toplevel);
           xvf_remove_protocol_handler(subform->toplevel, "WM_DELETE_WINDOW", 
				       xvf_quit_subform_cb, cb_data);
        }
	subform = subform->next_subform;
   }
   XtUnmapWidget(cb_data->formptr->toplevel); 
   xvf_remove_protocol_handler(cb_data->formptr->toplevel, "WM_DELETE_WINDOW",
                               xvf_quit_master_cb, cb_data);

   FORM_DONE = True;
   cb_data->formptr->form_sel = true;
   cb_data->formptr->quit = true;
   current_form = cb_data->formptr;
   current_subform = NULL;
}




/************************************************************
*
* Routine Name:  xvf_quit_subform_cb
*
*      Purpose:  This is the callback for the "Quit" button on subform
*
*        Input:  widget     - the subform quit button widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/


void xvf_quit_subform_cb(widget, clientData)
Widget widget;
caddr_t clientData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   xvf_sub_form *subform;
   xvf_guide_button *guide;
   char **database;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   subform = cb_data->subformptr;
   guide = cb_data->guideptr;

   /* change the subform's Quit line to show that it has been selected */
   xvf_clear_line_info(&line_info);
   xvf_parse_quit_line(database[guide->index], &line_info);
   line_info.selected = true;
   xvf_deparse_quit_line(&line_info, database, guide->index);

   /* collect & check data from forms */
   guide = xvf_search_sel_guide(subform);
   if (guide != NULL) xvf_collect_check_data(cb_data->formptr, database, guide);

   subform->subform_sel = true;
   subform->quit = true;

   /* change the subform's (-M) StartSubForm line 
      to show that it is no longer selected */
   xvf_parse_startsubform_line(database[subform->index], &line_info);
   line_info.selected = false;
   xvf_deparse_startsubform_line(&line_info, database, subform->index);
   subform->selected = false;

   /* if there is a true master,
      change the master form's (-d) subformbutton line 
      to show that it is no longer selected */
   if ((subform->button_index != -1) && (subform->button != NULL))
   {
       xvf_parse_subformbutton_line(database[subform->button_index], 
    			            &line_info);
       line_info.selected = false;
       xvf_deparse_subformbutton_line(&line_info, database,
				      subform->button_index);

       /* un-highlight the subform button if it not on a submenu */
       if (subform->submenu == False)
          xvf_reverse_colors(subform->button);
   }

   /* we're done */
   FORM_DONE = True;
   XtUnmapWidget(subform->toplevel);
   XFlush(XtDisplay(subform->toplevel));

   if (cb_data->formptr->toplevel == NULL)
	cb_data->formptr->quit = true;
   current_subform = cb_data->subformptr;
   current_form = cb_data->formptr;
}



/************************************************************
*
* Routine Name:  xvf_quit_pane_cb
*
*      Purpose:  This is the callback for the "Quit" button on pane
*
*        Input:  widget     - the pane quit button widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/


void xvf_quit_pane_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data 	*cb_data;
   Line_Info 	 	 line_info;
   xvf_sub_form 	*subform;
   xvf_selection 	*selection;
   char **database;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   subform = cb_data->subformptr;
   selection = cb_data->selptr;

   /* change the subform's Quit line to show that it has been selected */
   xvf_clear_line_info(&line_info);
   xvf_parse_quit_line(database[selection->index], &line_info);
   line_info.selected = true;
   xvf_deparse_quit_line(&line_info, database, selection->index);

   /* collect & check data from forms */
   xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr);

   /* change the subform's (-M) StartSubForm line 
      to show that it is no longer selected */
   xvf_parse_startsubform_line(database[subform->index], &line_info);
   line_info.selected = false;
   xvf_deparse_startsubform_line(&line_info, database, subform->index);
   subform->selected = false;
   subform->quit = true;

   /* if there is a guide pane,
      change the subform's (-g) subformbutton line 
      to show that it is no longer selected */
   if (subform->button_index != -1)
   {
       xvf_parse_subformbutton_line(database[subform->button_index], 
    			            &line_info);
       line_info.selected = false;
       xvf_deparse_subformbutton_line(&line_info, database,
				      subform->button_index);

       /* un-highlight the subform button if it not on a submenu */
       if ((subform->submenu == False) && (subform->button != NULL))
          xvf_reverse_colors(subform->button);
   }

   /* we're done */
   FORM_DONE = True;
   XtUnmapWidget(subform->toplevel);
   XFlush(XtDisplay(subform->toplevel));

   if (cb_data->formptr->toplevel == NULL)
	cb_data->formptr->quit = true;
   current_subform = cb_data->subformptr;
   current_form = cb_data->formptr;
}




/************************************************************
*
* Routine Name:  xvf_subform_cb
*
*      Purpose:  This is the callback for the subform buttons 
*		 on the master form that will bring up a subform
*		 when selected. 
*
*        Input:  widget     - the subform button widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

void xvf_subform_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   xvf_sub_form *old_subform, *current;
   Line_Info line_info;
   xvf_form *formptr;
   char **database;
   xvf_guide_button *guideptr;


   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   formptr = cb_data->formptr;
   database = formptr->db;

   /* highlight the current subform button if it not on a submenu */
   if (cb_data->subformptr->submenu == False)
      xvf_reverse_colors(widget);

   if (formptr->mut_excl == true)
   {
        /* search for the subform button that was selected before */
        old_subform = cb_data->formptr->subform;
        while (((old_subform->selected != true) && 
     		(old_subform->next_subform != NULL))
            || ((old_subform->type != SubFormButton) && 
		(old_subform->next_subform != NULL)))
		    old_subform = old_subform->next_subform;


        /* found the subform button last selected  & turn it off */
        if ((old_subform->selected == true) && 
	    (old_subform->type == SubFormButton))
        {
            /* un-highlight that widget if it not on a submenu */
	    if (old_subform->submenu == False)
               xvf_reverse_colors(old_subform->button);

            /* change the line in the database associated with that widget,
               indicating that it is no longer selected */
            xvf_clear_line_info(&line_info);
            xvf_parse_subformbutton_line(database[old_subform->button_index], 
	     	     		         &line_info);
            line_info.selected = false;
            xvf_deparse_subformbutton_line(&line_info, database,
				           old_subform->button_index);

          /* change the subform's (-M) StartSubForm line 
             to show that it is no longer selected */
            xvf_parse_startsubform_line(database[old_subform->index], 
	 		       &line_info);
            line_info.selected = false;
            xvf_deparse_startsubform_line(&line_info, database,
	 			          old_subform->index);

            /* unmap the old subform*/
	    xvf_unmap_subform(old_subform);
	    guideptr = xvf_search_sel_guide(old_subform);
	    xvf_collect_check_data(cb_data->formptr, old_subform->db, guideptr);
            old_subform->selected = false;
        }

  }


   /* find the structure associated with the new subform */
   current = cb_data->subformptr;

  /* change the line in the database associated with the new subform 
    button, indicating that it is now selected */
   xvf_clear_line_info(&line_info);
   xvf_parse_subformbutton_line(database[current->button_index], &line_info);
   line_info.selected = true;
   xvf_deparse_subformbutton_line(&line_info, database,current->button_index);

   /* mark this subforms's StartSubForm line as also being selected */
   xvf_parse_startsubform_line(database[current->index], &line_info);
   line_info.selected = true;
   xvf_deparse_startsubform_line(&line_info, database, current->index);


   /* map raised the new subform */
   current->selected = true;
   current_form = cb_data->formptr;

   xvf_map_subform(current_form, current);
   
} /* end xvf_subform_cb */


/************************************************************
*
* Routine Name:  xvf_psuedo_subform_cb
*
*      Purpose:  This is the callback for the psuedo subform buttons 
*		 on the master form.  Once this button is selected,
*                the corresponding "selected" field in
*                the database is put to a 1 and control is released
*		 to the application.
*
*        Input:  widget     - the psuedo subform button widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

void xvf_psuedo_subform_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;

   xvf_sub_form *subform;
   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->formptr->db;
   subform = cb_data->subformptr;

   xvf_clear_line_info(&line_info);
   xvf_gen_parse(database[subform->button_index], &line_info);
   line_info.selected = true;
   xvf_gen_deparse(&line_info, database, subform->button_index);

   cb_data->subformptr->selected = true;
   cb_data->formptr->form_sel = true;

   FORM_DONE = True;
   current_form = cb_data->formptr;
   current_subform = cb_data->subformptr;
}



/************************************************************
*
* Routine Name:  xvf_guide_cb
*
*      Purpose:  This is the callback for the guidebuttons that
*		 "change the channel" on the form, by bringing
*		 up their respective options panes when active 
*
*        Input:  widget     - the guide button widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

void xvf_guide_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   int index;
   Callback_Data *cb_data;
   xvf_guide_button *old_guide, *current;
   Widget old_pane_widget, new_pane_widget;
   Line_Info line_info;
   char **database;

   /* highlight the current guide button */
   xvf_reverse_colors(widget);

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;


   /* search for the guide button that was selected before */
   old_guide = cb_data->subformptr->guide_button;
   while (((old_guide->selected != true) && (old_guide->next_button != NULL))
           || ((old_guide->type != GuideButton) && 
		(old_guide->next_button != NULL)))
	old_guide = old_guide->next_button;


   /* found the guide button last selected */
   if ((old_guide->selected == true) && (old_guide->type == GuideButton))
   {

       /* un-highlight that widget */
       xvf_reverse_colors(old_guide->button);

       /* change the line in the database associated with that widget,
          indicating that it is no longer selected */
       xvf_clear_line_info(&line_info);
       xvf_parse_guide_line(database[old_guide->index], &line_info);
       line_info.selected = false;
       xvf_deparse_guide_line(&line_info, database,old_guide->index);
       old_guide->selected = false;


       index = old_guide->pane->index;
       xvf_clear_line_info(&line_info);
       xvf_parse_startpane_line(database[index], &line_info);
       line_info.selected = false;
       xvf_deparse_startpane_line(&line_info, database, index);
   }


   /* find the structure associated with the new guide button */
   current = cb_data->guideptr;

   /* change the line in the database associated with the new guide button,
      indicating that it is now selected */
   xvf_clear_line_info(&line_info);
   xvf_parse_guide_line(database[current->index], &line_info);
   line_info.selected = true;
   xvf_deparse_guide_line(&line_info, database, current->index);

   /* set the pointer to the pane background widget */
   if (current->pane->back == NULL)
   {
      XawFormDoLayout(cb_data->subformptr->back, (Boolean) false);
      if (!(xvf_create_pane(database, cb_data->formptr, cb_data->subformptr, 
			    current,current->pane, false)))
      {
	fprintf(stderr, "xvf_guide_cb:\n");
	fprintf(stderr, "   ERROR: Couldn't create pane\n");
	return;
      }
      XawFormDoLayout(cb_data->subformptr->back, (Boolean) true);
      current->pane->count++;
   }

   new_pane_widget = current->pane->back;

   /* show that this is the guide button currently selected */
   current->selected = true;

   /* mark this guide button's StartPane line as also being selected */
   xvf_parse_startpane_line(database[current->pane->index], &line_info);
   line_info.selected = true;
   xvf_deparse_startpane_line(&line_info, database, current->pane->index);

   if (old_guide->type == GuideButton)
   {
       /* unmap the old options pane */
       old_pane_widget = old_guide->pane->back;
       if (old_guide->pane->back)
       {
          XUnmapWindow(XtDisplay(old_pane_widget), XtWindow(old_pane_widget));
          XFlush(XtDisplay(old_pane_widget));
       }
   }
   /* map the new options pane -- this MUST be mapped raised! */
   XMapRaised(XtDisplay(new_pane_widget), XtWindow(new_pane_widget));
   XFlush(XtDisplay(new_pane_widget));

   current_form = cb_data->formptr;
   
} /* end xvf_guide_cb */


/************************************************************
*
* Routine Name:  xvf_logic_opt_cb
*
*      Purpose:  This is the callback for the logical selections' optional
*		 button. If the logical is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the optional button widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_logic_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   xvf_selection *selection;
   int index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   selection = cb_data->selptr;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_logic_line(database[index], &line_info);

   /* doing a toggle */
   if (cb_data->doing_toggle == true)
      xvf_do_toggle(widget,cb_data->toggle_start,cb_data);

   /* selection is mutually exclusive */
   else if (cb_data->selptr->mut_excl == true)
      xvf_do_mut_exclusion(widget, cb_data);

   /* general case */
   else
   {
      /* show it has been changed */
      cb_data->selptr->modified = true;
      /* reverse colors on widget */
      xvf_reverse_colors(widget);

      /* set the "opt_sel" field in the database line that
         describes the input selection is to be used */
      line_info.opt_sel = !line_info.opt_sel;
      line_info.selected = true;
      xvf_deparse_logic_line(&line_info, database,index);
      cb_data->selptr->opt_selected = line_info.opt_sel; 
   }

  /*
   * if the selection is live, update the form tree, indicate FORM_DONE,
   * collect & check the data in preparation for returning to application
   */

  if (line_info.live == true)
  {
    xvf_update_form_tree(database, selection->index, cb_data->subformptr);

    cb_data->subformptr->subform_sel = true;

    FORM_DONE = True;
    current_subform = cb_data->subformptr;
    current_form = cb_data->formptr;

    xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr);

  }
  current_form = cb_data->formptr;
   
}


/************************************************************
*
* Routine Name:  xvf_logic_val_cb
*
*      Purpose:  This is the callback for the logic options' value
*                button. It toggles between having the label specified
*		 for 1 for the label specified for 0.
*
*        Input:  widget     - the value widget of the logical selection
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

void xvf_logic_val_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   xvf_selection *selection;
   int  n, x, y, width, height;
   Arg  arg[MaxArgs];
   char *boolean_label;
   Window root;
   unsigned  int old_width, old_height, border_width, depth;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   selection = cb_data->selptr;
   database = cb_data->subformptr->db;

   /* show it has been changed */
   cb_data->selptr->modified = true;
   cb_data->selptr->selected = true;

   /* change the line in the database associated with the logical widget,
   indicating that it is has been toggled from "on" to "off" or vice versa,
   and change the title on the widget accordingly */

   xvf_clear_line_info(&line_info);
   xvf_parse_logic_line(database[selection->index], &line_info);
   line_info.selected = true;
   line_info.logical_val = !(line_info.logical_val);
   xvf_deparse_logic_line(&line_info, database,selection->index);

   if (line_info.logical_val == true)
   {
       if (line_info.val_labels[1] != NULL)
          boolean_label = xvf_strcpy(line_info.val_labels[1]);
       else boolean_label = xvf_strcpy(" ");
   }
   else
   {
       if (line_info.val_labels[0] != NULL)
          boolean_label = xvf_strcpy(line_info.val_labels[0]);
       else boolean_label = xvf_strcpy(" ");
   }


   if (XGetGeometry(xvf_display,  XtWindow(selection->value_widget),
                      &root, &x, &y, &old_width, &old_height, 
		      &border_width, &depth))
   {
	width = MAX(old_width,((xvf_font_width)*(xvf_strlen(boolean_label)+2)));
	height = MAX(old_height, (xvf_font_height +2)*line_info.height);
   }
   else 
   {
        width = (xvf_font_width)*(xvf_strlen(boolean_label)+2);
	height = (xvf_font_height +2)*line_info.height;
   }

   n = 0;
   XtSetArg(arg[n], XtNlabel, boolean_label); n++;
   if (xvf_font != NULL)
   {
       XtSetArg(arg[n],XtNfont,xvf_font);              	        n++;
   }
   XtSetArg(arg[n],XtNwidth, width); 				n++;
   XtSetArg(arg[n],XtNheight, height);				n++;
   XtSetValues(selection->value_widget,arg,n);

   /*
    * if the selection is live, update the form tree, indicate FORM_DONE,
    * collect & check the data in preparation for returning to application
    */

   if (line_info.live == true)
   {
     xvf_update_form_tree(database, selection->index, cb_data->subformptr);

     cb_data->subformptr->subform_sel = true;

     FORM_DONE = True;
     current_subform = cb_data->subformptr;
     current_form = cb_data->formptr;

     xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr);

   }
   current_form = cb_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_cycle_opt_cb
*
*      Purpose:  This is the callback for the cycle selections' optional
*		 button. If the selection is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the optional button widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

   
void xvf_cycle_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   xvf_selection *selection;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   selection = cb_data->selptr;

   xvf_clear_line_info(&line_info);
   xvf_parse_cycle_line(database[selection->index], &line_info);

   if (line_info.optional == false) return;
   else 
   {
          /* show it has been changed */
          cb_data->selptr->modified = true;

          /* reverse colors on widget */
          xvf_reverse_colors(widget);

          /* set the "opt_sel" field in the database line that 
	     describes the integer selection is to be used */
          line_info.opt_sel = !line_info.opt_sel;
          cb_data->selptr->opt_selected = line_info.opt_sel; 
	  line_info.selected = true;
          xvf_deparse_cycle_line(&line_info, database,selection->index);
   }
   current_form = cb_data->formptr;
}

/************************************************************
*
* Routine Name:  xvf_list_opt_cb
*
*      Purpose:  This is the callback for the list selections' optional
*		 button. If the selection is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the optional button widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

   
void xvf_list_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   xvf_selection *selection;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   selection = cb_data->selptr;

   xvf_clear_line_info(&line_info);
   xvf_parse_list_line(database[selection->index], &line_info);

   if (line_info.optional == false) return;
   else 
   {
          /* show it has been changed */
          cb_data->selptr->modified = true;

          /* reverse colors on widget */
          xvf_reverse_colors(widget);

          /* set the "opt_sel" field in the database line that 
	     describes the integer selection is to be used */
          line_info.opt_sel = !line_info.opt_sel;
          cb_data->selptr->opt_selected = line_info.opt_sel; 
	  line_info.selected = true;
          xvf_deparse_list_line(&line_info, database,selection->index);
   }
   current_form = cb_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_cycle_val_cb
*
*      Purpose:  This is the callback for the cycle options' value
*                button. It cycles through the string values specified.
*
*        Input:  widget     - the cycle value widget 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

   
void xvf_cycle_val_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   xvf_selection *selection;
   int  n, x, y, width, height;
   Arg  arg[MaxArgs];
   char *cycle_label;
   Window root;
   unsigned  int old_width, old_height, border_width, depth;


   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   selection = cb_data->selptr;
   database = cb_data->subformptr->db;

   /* show it has been changed */
   cb_data->selptr->modified = true;
   cb_data->selptr->selected = true;

   /* change the line in the database associated with the cycle widget,
   indicating that it is has been incremented one unit through the cycle,
   and change the title on the widget accordingly */

   xvf_clear_line_info(&line_info);
   xvf_parse_cycle_line(database[selection->index], &line_info);
   line_info.selected = true;

   line_info.cycle_val++;
   if (line_info.cycle_val == line_info.cycle_num) 
       line_info.cycle_val = 0;
   xvf_deparse_cycle_line(&line_info, database,selection->index);

   cycle_label = xvf_strcpy(line_info.val_labels[line_info.cycle_val]);

   if (XGetGeometry(xvf_display,  XtWindow(selection->value_widget),
                      &root, &x, &y, &old_width, &old_height,
                      &border_width, &depth))
   {
        width = MAX(old_width,((xvf_font_width)*(xvf_strlen(cycle_label)+2)));
        height = MAX(old_height, (xvf_font_height+2)*line_info.height);
   }
   else
   {
        width = (xvf_font_width)*(xvf_strlen(cycle_label)+2);
        height = (xvf_font_height +2)*line_info.height;
   }

   n = 0;
   XtSetArg(arg[n], XtNlabel, cycle_label); n++;
   if (xvf_font != NULL)
   {
       XtSetArg(arg[n],XtNfont,xvf_font);              	      	n++;
   }
   XtSetArg(arg[n],XtNwidth, width);                            n++;
   XtSetArg(arg[n],XtNheight, height);                          n++;
   XtSetValues(selection->value_widget,arg,n);

   /*
    * if the selection is live, update the form tree, indicate FORM_DONE,
    * collect & check the data in preparation for returning to application
    */

   if (line_info.live == true)
   {
     xvf_update_form_tree(database, selection->index, cb_data->subformptr);

     cb_data->subformptr->subform_sel = true;

     FORM_DONE = True;
     current_subform = cb_data->subformptr;
     current_form = cb_data->formptr;

     xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr);

   }
   current_form = cb_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_list_val_cb
*
*      Purpose:  This is the callback for the list selection's 
*                button. It puts up a list with the strings specified,
*		 returns the number of the list item selected.
*
*        Input:  widget     - the list selection's  button 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

   
void xvf_list_val_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database, *list[20], *label;
   xvf_selection *selection;
   XawListReturnStruct *list_return;
   int n, i, size,  x, y, width, height;
   char *prompt = "Select one of the following:";
   Arg arg[MaxArgs];
   Window root;
   unsigned  int old_width, old_height, border_width, depth;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   selection = cb_data->selptr;
   database = cb_data->subformptr->db;

   /* show it has been changed */
   cb_data->selptr->modified = true;
   cb_data->selptr->selected = true;

   /* change the line in the database associated with the list widget,
   indicating that it is has been incremented one unit through the list,
   and change the title on the widget accordingly */

   xvf_clear_line_info(&line_info);
   xvf_parse_list_line(database[selection->index], &line_info);
   line_info.selected = true;
   
   size = line_info.list_num;

   for (i=0; i < size; i++)
        list[i] = xvf_strcpy(line_info.val_labels[i]);
   label = line_info.title;

   list_return = xvf_run_list_wait(list, size, 1, prompt, 
				    label, line_info.list_val, false);

   if (list_return != NULL)
   {
      line_info.list_val = list_return->list_index + 1;
      xvf_deparse_list_line(&line_info, database,selection->index);
   
      label = xvf_strcpy(line_info.val_labels[list_return->list_index]);
      if (XGetGeometry(xvf_display,  XtWindow(selection->value_widget),
                      &root, &x, &y, &old_width, &old_height,
                      &border_width, &depth))
      {
        width = MAX(old_width,((xvf_font_width)*(xvf_strlen(label)+2)));
        height = MAX(old_height, (xvf_font_height +2)*line_info.height);
      }
      else
      {
        width = (xvf_font_width)*(xvf_strlen(label)+2);
        height = (xvf_font_height +2)*line_info.height;
      }

      n = 0;
      XtSetArg(arg[n], XtNlabel, label); n++;
      if (xvf_font != NULL)
      {
          XtSetArg(arg[n],XtNfont,xvf_font);          	           n++;
      }
      XtSetArg(arg[n],XtNwidth, width);                            n++;
      XtSetArg(arg[n],XtNheight, height);                          n++;
      XtSetValues(selection->value_widget,arg,n);


      /*
       * if the selection is live, update the form tree, indicate FORM_DONE,
       * collect & check the data in preparation for returning to application
       */

      if (line_info.live == true)
      {
        xvf_update_form_tree(database, selection->index, cb_data->subformptr);

        cb_data->subformptr->subform_sel = true;

        FORM_DONE = True;
        current_subform = cb_data->subformptr;
        current_form = cb_data->formptr;

        xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr);

      }
      current_form = cb_data->formptr;
   }
}



   
/************************************************************
*
* Routine Name:  xvf_int_opt_cb
*
*      Purpose:  This is the callback for the integer selections' optional
*		 button. If the selection is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the integer selection's  optional button 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_int_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   xvf_selection *selection;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   selection = cb_data->selptr;
   selection->modified = true;

   xvf_clear_line_info(&line_info);
   xvf_parse_int_line(database[selection->index], &line_info);

   if (line_info.optional == false) return;
   else 
   {
       /* doing a toggle */
       if (cb_data->doing_toggle == true)
           xvf_do_toggle(widget,cb_data->toggle_start,cb_data);

       /* selection is mutually exclusive */
       else if (cb_data->selptr->mut_excl == true)
 	   xvf_do_mut_exclusion(widget, cb_data);

       /* general case */
       else
       {
          /* show it has been changed */
          cb_data->selptr->modified = true;

          /* reverse colors on widget */
          xvf_reverse_colors(widget);

          /* set the "opt_sel" field in the database line that 
	     describes the integer selection is to be used */
          line_info.opt_sel = !line_info.opt_sel;
          cb_data->selptr->opt_selected = line_info.opt_sel; 
	  line_info.selected = true;
          xvf_deparse_int_line(&line_info, database,selection->index);
       }
   }
   current_form = cb_data->formptr;
}



/************************************************************
*
* Routine Name:  xvf_int_incr_scroll_cb
*
*      Purpose:  This is the callback for the integer selections' 
*		 scroll bar when it is used incrementally (left
*		 and right mouse buttons).
*
*        Input:  widget     - the integer selection's  scroll bar 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

void xvf_int_incr_scroll_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   int movement, status;
   IntScroll_Data *scroll_data;
   char temp[50];
   XawTextBlock text_block;
   float percent;
   Line_Info line_info;
   char **database;
   int    index;
   float  delta;

   movement = (int) callData;
   scroll_data = (IntScroll_Data *) clientData;
   database = scroll_data->subformptr->db;
   index    = scroll_data->selptr->index;

   scroll_data->selptr->modified = true;

   sprintf(temp, "%d", scroll_data->int_value);

   if ((scroll_data->int_value > scroll_data->int_max) ||
      (scroll_data->int_value < scroll_data->int_min))  return;

   delta = (float) ((float) scroll_data->interval /
		    (float) scroll_data->bar_width *
		    (float) scroll_data->increment);
   if (movement > 0)
   {
      if (delta > 0) scroll_data->int_value -= (int)(delta + 0.5);
      else scroll_data->int_value -= 1;
      
      if (scroll_data->int_value < scroll_data->int_min)
           scroll_data->int_value = scroll_data->int_min;
   }
   else if (movement < 0)
   {
      if (delta > 0) scroll_data->int_value += (int)(delta + 0.5);
      else scroll_data->int_value += 1;

      if (scroll_data->int_value > scroll_data->int_max)
           scroll_data->int_value = scroll_data->int_max;
   }

   sprintf(temp,"%d", scroll_data->int_value);

   text_block.firstPos = 0;
   text_block.length = xvf_strlen(temp);
   text_block.ptr = temp;
   text_block.format = FMT8BIT;
			      
   status = XawTextReplace(scroll_data->int_val_widget, (XawTextPosition)0,
        	         (XawTextPosition)(scroll_data->max_int_length), 
			 &text_block);
   XawTextDisplay(scroll_data->int_val_widget);

   if (status == XawPositionError)
   {
        fprintf(stderr, "\nxvf_int_incr_scroll_cb:\n");
        fprintf(stderr,"      ERROR: XawPositionError\n");
   }
   else if (status == XawEditError)
   {
        fprintf(stderr, "\nxvf_int_incr_scroll_cb:\n");
        fprintf(stderr,"      ERROR: XawEditError\n");
   }

   percent = ((float) scroll_data->int_value - (float) scroll_data->int_min)/
	     ((float)scroll_data->interval);
   XawScrollbarSetThumb(scroll_data->int_scroll, percent, 1.0);

   xvf_clear_line_info(&line_info);
   xvf_parse_int_line(database[index], &line_info);
   if (line_info.live == true)  
   {
        line_info.selected = true;
        line_info.int_val = scroll_data->int_value;
	sprintf(temp, "%d", line_info.int_val);
        line_info.literal = xvf_strcpy(temp);
        xvf_deparse_int_line(&line_info, database, index);

        xvf_update_form_tree(database, index, scroll_data->subformptr);

        scroll_data->subformptr->subform_sel = true;

        FORM_DONE = True;
        current_subform = scroll_data->subformptr;
        current_form = scroll_data->formptr;

        xvf_collect_check_data(scroll_data->formptr, database, 
				scroll_data->guideptr); 

   }
   current_form = scroll_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_int_flow_scroll_cb
*
*      Purpose:  This is the callback for the integer selections' 
*		 scroll bar when it is used smoothly 
*		 (middle mouse button).
*
*        Input:  widget     - the integer selection's  scroll bar 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

void xvf_int_flow_scroll_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   int status;
   IntScroll_Data *scroll_data;
   char temp[50];
   XawTextBlock text_block;
   float *movement;
   Line_Info line_info;
   char **database;
   int    index;

   movement = (float *) callData;
   scroll_data = (IntScroll_Data *) clientData;
   database = scroll_data->subformptr->db;
   index    = scroll_data->selptr->index;
   
   scroll_data->selptr->modified = true;

   scroll_data->int_value = (int) (*movement * scroll_data->interval) +
			    scroll_data->int_min;

   sprintf(temp,"%d", scroll_data->int_value);

   text_block.firstPos = 0;
   text_block.length = xvf_strlen(temp);
   text_block.ptr = temp;
   text_block.format = FMT8BIT;
			      
   status = XawTextReplace(scroll_data->int_val_widget, (XawTextPosition)0,
        	         (XawTextPosition)(scroll_data->max_int_length), 
			 &text_block);
   XawTextDisplay(scroll_data->int_val_widget);

   if (status == XawPositionError)
   {
        fprintf(stderr, "\nxvf_int_flow_scroll_cb:\n");
        fprintf(stderr,"      ERROR: XawPositionError\n");
   }
   else if (status == XawEditError)
   {
        fprintf(stderr, "\nxvf_int_flow_scroll_cb:\n");
        fprintf(stderr,"      ERROR: XawEditError\n");
   }

   xvf_clear_line_info(&line_info);
   xvf_parse_int_line(database[index], &line_info);
   if (line_info.live == true)  
   {
        line_info.selected = true;
        line_info.int_val = scroll_data->int_value;
	sprintf(temp, "%d", line_info.int_val);
        line_info.literal = xvf_strcpy(temp);
        xvf_deparse_int_line(&line_info, database, index);

        xvf_update_form_tree(database, index, scroll_data->subformptr);

        scroll_data->subformptr->subform_sel = true;

        FORM_DONE = True;
        current_subform = scroll_data->subformptr;
        current_form = scroll_data->formptr;

        xvf_collect_check_data(scroll_data->formptr, database, 
				scroll_data->guideptr); 

   }
   current_form = scroll_data->formptr;
}

/************************************************************
*
* Routine Name:  xvf_float_opt_cb
*
*      Purpose:  This is the callback for the float selections' optional
*		 button. If the selection is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the float selection's optional button 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_float_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;
   cb_data->selptr->modified = true;

   xvf_clear_line_info(&line_info);
   xvf_parse_float_line(database[index], &line_info);

   if (line_info.optional == false) return;
   else 
   {
       /* doing a toggle */
       if (cb_data->doing_toggle == true)
          xvf_do_toggle(widget,cb_data->toggle_start,cb_data);

      /* selection is mutually exclusive */
      else if (cb_data->selptr->mut_excl == true)
	 xvf_do_mut_exclusion(widget, cb_data);

      /* general case */
      else
      {
          /* show it has been changed */
          cb_data->selptr->modified = true;

          /* reverse colors on widget */
          xvf_reverse_colors(widget);

          /* set the "opt_sel" field in the database line that 
	     describes the float selection is to be used */
          line_info.opt_sel = !line_info.opt_sel;
          cb_data->selptr->opt_selected = line_info.opt_sel; 
	  line_info.selected = true;
          xvf_deparse_float_line(&line_info, database, index);
      }
   }
   current_form = cb_data->formptr;
}

/************************************************************
*
* Routine Name:  xvf_float_incr_scroll_cb
*
*      Purpose:  This is the callback for the float selections' 
*		 scroll bar when it is used incrementally 
*		 (right and left mouse buttons).
*
*        Input:  widget     - the float selection's scroll bar 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

void xvf_float_incr_scroll_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   int movement, status, signif_digits;
   FloatScroll_Data *scroll_data;
   char temp[50], scale[50];
   XawTextBlock text_block;
   float percent;
   Line_Info line_info;
   char **database, *string_return;
   int   i, index, end_pos;
   Arg  arg[MaxArgs];
   float delta;


   movement = (int) callData;
   scroll_data = (FloatScroll_Data *) clientData;
   database = scroll_data->subformptr->db;
   index    = scroll_data->selptr->index;
   scroll_data->selptr->modified = true;

   sprintf(temp, "%g", scroll_data->float_value);

   if ((scroll_data->float_value > scroll_data->float_max) ||
      (scroll_data->float_value < scroll_data->float_min))  return;

   delta = (float) (scroll_data->interval /
		   (float)scroll_data->bar_width *
		    scroll_data->increment);
   if (movement > 0)
   {
      if (delta > 0) scroll_data->float_value -= (int)(delta + 0.5);
      else scroll_data->float_value -= 1;

      if (scroll_data->float_value < scroll_data->float_min)
           scroll_data->float_value = scroll_data->float_min;
   }
   else if (movement < 0)
   {
      if (delta > 0) scroll_data->float_value += (int)(delta + 0.5);
      else scroll_data->float_value += 1;

      if (scroll_data->float_value > scroll_data->float_max)
           scroll_data->float_value = scroll_data->float_max;
   }

   /* set the float line to be selected */
   xvf_clear_line_info(&line_info);
   xvf_parse_float_line(database[index], &line_info);

   signif_digits = xvf_def_number_sign_digits(scroll_data->interval,
					      line_info.literal);
   sprintf(scale, "%%.%df", signif_digits);
   sprintf(temp,scale, scroll_data->float_value);

   text_block.firstPos = 0;
   text_block.length = xvf_strlen(temp);
   text_block.ptr = temp;
   text_block.format = FMT8BIT;

   i = 0;
   XtSetArg(arg[i], XtNstring, &string_return);    i++;
   XtGetValues(scroll_data->float_val_widget, arg, i);
   end_pos = xvf_strlen(string_return);

   status = XawTextReplace(scroll_data->float_val_widget, (XawTextPosition)0,
                         (XawTextPosition)(end_pos), &text_block);
   XawTextDisplay(scroll_data->float_val_widget);

   if (status == XawPositionError)
   {
        fprintf(stderr, "\nxvf_float_incr_scroll_cb:\n");
        fprintf(stderr,"      ERROR: XawPositionError\n");
   }
   else if (status == XawEditError)
   {
        fprintf(stderr, "\nxvf_float_incr_scroll_cb:\n");
        fprintf(stderr,"      ERROR: XawEditError\n");
   }

   percent = (scroll_data->float_value - scroll_data->float_min)/
             scroll_data->interval;
   XawScrollbarSetThumb(scroll_data->float_scroll, percent, 1.0);

   if (line_info.live == true)  
   {
        line_info.selected = true;
        line_info.float_val = scroll_data->float_value;
	sprintf(temp, "%f", scroll_data->float_value);
        line_info.literal = xvf_strcpy(temp);
        xvf_deparse_float_line(&line_info, database, index);

        xvf_update_form_tree(database, index, scroll_data->subformptr);

        scroll_data->subformptr->subform_sel = true;

        FORM_DONE = True;
        current_subform = scroll_data->subformptr;
        current_form = scroll_data->formptr;

        xvf_collect_check_data(scroll_data->formptr, database, scroll_data->guideptr); 
   }

   current_form = scroll_data->formptr;
}



/************************************************************
*
* Routine Name:  xvf_float_flow_scroll_cb
*
*      Purpose:  This is the callback for the float selections' 
*		 scroll bar when it is used smoothly
*		 (right and left mouse buttons).
*
*        Input:  widget     - the float selection's  scroll bar 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

void xvf_float_flow_scroll_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   int status, signif_digits;
   FloatScroll_Data *scroll_data;
   char temp[MaxLength], scale[MaxLength];
   XawTextBlock text_block;
   float *movement;
   Line_Info line_info;
   char **database;
   int    i, index, end_pos;
   Arg   arg[MaxArgs];
   char  *string_return;

   movement = (float *) callData;
   scroll_data = (FloatScroll_Data *) clientData;
   database = scroll_data->subformptr->db;
   index    = scroll_data->selptr->index;
   scroll_data->selptr->modified = true;
   
   scroll_data->float_value = *movement * scroll_data->interval +
			       scroll_data->float_min;

   /* set the integer line to be selected */
   xvf_clear_line_info(&line_info);
   xvf_parse_float_line(database[index], &line_info);

   signif_digits = xvf_def_number_sign_digits(scroll_data->interval,
					      line_info.literal);
   sprintf(scale, "%%.%df", signif_digits);
   sprintf(temp,scale, scroll_data->float_value);

   text_block.firstPos = 0;
   text_block.length = xvf_strlen(temp);
   text_block.ptr = temp;
   text_block.format = FMT8BIT;
			      
   i = 0;
   XtSetArg(arg[i], XtNstring, &string_return);    i++;
   XtGetValues(scroll_data->float_val_widget, arg, i);
   end_pos = xvf_strlen(string_return);

   status = XawTextReplace(scroll_data->float_val_widget, (XawTextPosition)0,
        	         (XawTextPosition)(end_pos), &text_block);
   XawTextDisplay(scroll_data->float_val_widget);


   if (status == XawPositionError)
   {
        fprintf(stderr, "\nxvf_float_flow_scroll_cb:\n");
        fprintf(stderr,"      ERROR: XawPositionError\n");
   }
   else if (status == XawEditError)
   {
        fprintf(stderr, "\nxvf_float_flow_scroll_cb:\n");
        fprintf(stderr,"      ERROR: XawEditError\n");
   }

   if (line_info.live == true)  
   {
        line_info.selected = true;
        line_info.float_val = scroll_data->float_value;
	sprintf(temp, "%f", scroll_data->float_value);
        line_info.literal = xvf_strcpy(temp);
        xvf_deparse_float_line(&line_info, database, index);

        xvf_update_form_tree(database, index, scroll_data->subformptr);

        scroll_data->subformptr->subform_sel = true;

        FORM_DONE = True;
        current_subform = scroll_data->subformptr;
        current_form = scroll_data->formptr;

        xvf_collect_check_data(scroll_data->formptr, database, 
				scroll_data->guideptr); 
   }

   current_form = scroll_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_string_opt_cb
*
*      Purpose:  This is the callback for the string selections' optional
*		 button. If the selection is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the string selection's optional button 
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_string_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_string_line(database[index], &line_info);

   if (line_info.optional == false) return;
   else 
   {
       /* doing a toggle */
       if (cb_data->doing_toggle == true)
          xvf_do_toggle(widget,cb_data->toggle_start,cb_data);

       /* selection is mutually exclusive */
       else if (cb_data->selptr->mut_excl == true)
    	  xvf_do_mut_exclusion(widget, cb_data);

       /* general case */
       else
       {
          /* show it has been changed */
          cb_data->selptr->modified = true;

          /* reverse colors on widget */
          xvf_reverse_colors(widget);

          /* set the "opt_sel" field in the database line that 
	     describes the string selection is to be used */
          line_info.opt_sel = !line_info.opt_sel;
          cb_data->selptr->opt_selected = line_info.opt_sel; 
	  line_info.selected = true;
          xvf_deparse_string_line(&line_info, database,index);
       }
   }
   current_form = cb_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_input_opt_cb
*
*      Purpose:  This is the callback for the input file selections' optional
*		 button. If the selection is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the input file selection's optional button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_input_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_input_line(database[index], &line_info);

   if (line_info.optional == false) return;
   else
   {
       /* doing a toggle */
       if (cb_data->doing_toggle == true)
          xvf_do_toggle(widget,cb_data->toggle_start,cb_data);

       /* selection is mutually exclusive */
       else if (cb_data->selptr->mut_excl == true)
	     xvf_do_mut_exclusion(widget, cb_data);

       /* general case */
       else
       {
          /* show it has been changed */
          cb_data->selptr->modified = true;

          /* reverse colors on widget */
          xvf_reverse_colors(widget);

          /* set the "opt_sel" field in the database line that 
	     describes the input selection is to be used */
          line_info.opt_sel = !line_info.opt_sel;
          cb_data->selptr->opt_selected = line_info.opt_sel; 
	  line_info.selected = true;
          xvf_deparse_input_line(&line_info, database,index);
       }
   }
   current_form = cb_data->formptr;
}



/************************************************************
*
* Routine Name:  xvf_input_label_cb
*
*      Purpose:  This is the callback for the input file selections' 
*		 label button.  When clicked, the file browser pops up
*		 and lets the user select a file.  If valid, this filename 
*		 then put into the text widget.
*
*        Input:  widget     - the input file selection's label button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

void xvf_input_label_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char *in_filename, *xvf_run_browser();
   char *new_dir, *tmp_dir;
   xvf_selection *sel_ptr;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_input_line(database[index], &line_info);

   new_dir = "./";
   if (XVF_FILE_DIR != NULL)
      new_dir = XVF_FILE_DIR;
   if (line_info.filename != NULL)
   {
      /* strip off directory name */
      tmp_dir = xvf_strip_path(line_info.filename);
      if (tmp_dir != NULL)
	 new_dir = tmp_dir;
   }
   in_filename = xvf_run_browser(NULL, NULL, new_dir);

   if (in_filename != NULL)
   {
       sel_ptr = xvf_sel_search(cb_data->formptr, index);
       if (sel_ptr != NULL)
          sel_ptr->modified = true;

       line_info.selected = true;
       xvf_deparse_input_line(&line_info,database,index);
       xvf_change_input(cb_data->formptr,index,xvf_inputfile_chng,
    		in_filename,0);

       if (line_info.live == true)  
       {
           xvf_update_form_tree(database, cb_data->selptr->index, 
     	 		        cb_data->subformptr);

           cb_data->subformptr->subform_sel = true;

           FORM_DONE = True;
           current_subform = cb_data->subformptr;
           current_form = cb_data->formptr;

           xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr); 
        }
   }

   current_form = cb_data->formptr;
}

/************************************************************
*
* Routine Name:  xvf_output_opt_cb
*
*      Purpose:  This is the callback for the output file selections' optional
*		 button. If the selection is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the output file selection's optional button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_output_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_output_line(database[index], &line_info);

   if (line_info.optional == false) return;
   else 
   {
       /* doing a toggle */
       if (cb_data->doing_toggle == true)
          xvf_do_toggle(widget,cb_data->toggle_start,cb_data);

       /* selection is mutually exclusive */
       else if (cb_data->selptr->mut_excl == true)
    	  xvf_do_mut_exclusion(widget, cb_data);

       /* general case */
       else
       {
          /* show it has been changed */
          cb_data->selptr->modified = true;

          /* reverse colors on widget */
          xvf_reverse_colors(widget);

          /* set the "opt_sel" field in the database line that 
	     describes the output selection is to be used */
          line_info.opt_sel = !line_info.opt_sel;
          cb_data->selptr->opt_selected = line_info.opt_sel; 
	  line_info.selected = true;
          xvf_deparse_output_line(&line_info, database, index);
       }
   }
   current_form = cb_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_output_label_cb
*
*      Purpose:  This is the callback for the output file selections' 
*		 label button.  When clicked, the file browser pops up
*		 and lets the user select a file.  If valid, this filename 
*		 then put into the text widget.
*
*        Input:  widget     - the input file selection's label button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

void xvf_output_label_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char *out_filename, *xvf_run_browser();
   char *new_dir, *tmp_dir;
   xvf_selection *sel_ptr;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_output_line(database[index], &line_info);

   new_dir = "./";
   if (XVF_FILE_DIR != NULL)
      new_dir = XVF_FILE_DIR;
   if (line_info.filename != NULL)
   {
      /* strip off directory name */
      tmp_dir = xvf_strip_path(line_info.filename);
      if (tmp_dir != NULL)
	 new_dir = tmp_dir;
   }
   out_filename = xvf_run_browser(NULL, NULL, new_dir);
   
   if (out_filename != NULL)
   {
       sel_ptr = xvf_sel_search(cb_data->formptr, index);
       if (sel_ptr != NULL)
          sel_ptr->modified = true;

       line_info.selected = true;
       xvf_deparse_output_line(&line_info,database,index);
       xvf_change_input(cb_data->formptr,index,xvf_outputfile_chng,
	                out_filename,0);
       if (line_info.live == true)
       {
           xvf_update_form_tree(database, cb_data->selptr->index,
                                cb_data->subformptr);

           cb_data->subformptr->subform_sel = true;

	   FORM_DONE = True;
           current_subform = cb_data->subformptr;
           current_form = cb_data->formptr;

           xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr);
        }
   }
   current_form = cb_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_ansinfile_label_cb
*
*      Purpose:  This is the callback for the Answer Infile selections' 
*		 label button.  When clicked, the file browser pops up
*		 and lets the user select a file.  If valid, this filename 
*		 then put into the text widget.
*
*        Input:  widget     - the input file selection's label button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

void xvf_ansinfile_label_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char *ans_filename, *xvf_run_browser();
   char *new_dir, *tmp_dir;
   xvf_selection *sel_ptr;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_ansinfile_line(database[index], &line_info);

   new_dir = "./";
   if (XVF_FILE_DIR != NULL)
      new_dir = XVF_FILE_DIR;
   if (line_info.filename != NULL)
   {
      /* strip off directory name */
      tmp_dir = xvf_strip_path(line_info.filename);
      if (tmp_dir != NULL)
	 new_dir = tmp_dir;
   }
   ans_filename = xvf_run_browser(NULL, NULL, new_dir);

   if (ans_filename != NULL)
   {
       sel_ptr = xvf_sel_search(cb_data->formptr, index);
       if (sel_ptr != NULL)
          sel_ptr->modified = true;

       line_info.selected = true;
       xvf_deparse_ansinfile_line(&line_info,database,index);
       xvf_change_input(cb_data->formptr,index, xvf_ansinfile_chng,
    		ans_filename,0);

       xvf_update_form_tree(database, cb_data->selptr->index, 
     	 		        cb_data->subformptr);

       cb_data->subformptr->subform_sel = true;

       FORM_DONE = True;
       current_subform = cb_data->subformptr;
       current_form = cb_data->formptr;

       xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr); 
   }
   current_form = cb_data->formptr;
}



/************************************************************
*
* Routine Name:  xvf_ansoutfile_label_cb
*
*      Purpose:  This is the callback for the Answer Outfile selections' 
*		 label button.  When clicked, the file browser pops up
*		 and lets the user select a file.  If valid, this filename 
*		 then put into the text widget.
*
*        Input:  widget     - the input file selection's label button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Danielle Argiro
*
*************************************************************/

void xvf_ansoutfile_label_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char *out_ansfilename, *xvf_run_browser();
   char *new_dir, *tmp_dir;
   xvf_selection *sel_ptr;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index    = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_ansoutfile_line(database[index], &line_info);

   new_dir = "./";
   if (XVF_FILE_DIR != NULL)
      new_dir = XVF_FILE_DIR;
   if (line_info.filename != NULL)
   {
      /* strip off directory name */
      tmp_dir = xvf_strip_path(line_info.filename);
      if (tmp_dir != NULL)
	 new_dir = tmp_dir;
   }
   out_ansfilename = xvf_run_browser(NULL, NULL, new_dir);
   
   if (out_ansfilename != NULL)
   {
       sel_ptr = xvf_sel_search(cb_data->formptr, index);
       if (sel_ptr != NULL)
          sel_ptr->modified = true;

       line_info.selected = true;
       xvf_deparse_ansoutfile_line(&line_info,database,index);
       xvf_change_input(cb_data->formptr,index,xvf_ansoutfile_chng,
	                out_ansfilename,0);
       xvf_update_form_tree(database, cb_data->selptr->index,
                            cb_data->subformptr);

       cb_data->subformptr->subform_sel = true;

       FORM_DONE = True;
       current_subform = cb_data->subformptr;
       current_form = cb_data->formptr;

       xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr);
   }
   current_form = cb_data->formptr;
}

/************************************************************
*
* Routine Name:  xvf_toggle_opt_cb
*
*      Purpose:  This is the callback for the toggle selections' optional
*		 button. If the selection is optional, the button
*		 will be "off" when it is inactive, "on" when it is active
*		 and the cycle can be changed by the user.  If the 
*		 selection is *not* optional, this button will not exist.  
*
*        Input:  widget     - the toggle selection's optional button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_toggle_opt_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   int    index;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index     = cb_data->selptr->index;

   xvf_clear_line_info(&line_info);
   xvf_parse_toggle_line(database[index], &line_info);

   if (line_info.optional == false) return;
   else 
   {
       /* show it has been changed */
       cb_data->selptr->modified = true;

       /* reverse colors on widget */
       xvf_reverse_colors(widget);

       /* set the "opt_sel" field in the database line that 
	  describes the toggle selection is to be used */
       line_info.opt_sel = !line_info.opt_sel;
       cb_data->selptr->opt_selected = line_info.opt_sel; 
       line_info.selected = true;
       xvf_deparse_toggle_line(&line_info, database, index);
   }
   current_form = cb_data->formptr;
}



/************************************************************
*
* Routine Name:  xvf_master_action_cb
*
*      Purpose:  This is the callback for the action button that resides 
*		 in the master form.  When this button is selected,
*		 the corresponding "selected" field in the UIS line is set 
*		 to a 1 and control is returned to the application.
*
*        Input:  widget     - the master action button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_master_action_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   xvf_sub_form *subform;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->formptr->db;
   subform = cb_data->subformptr;

   xvf_clear_line_info(&line_info);
   xvf_parse_master_action_line(database[subform->button_index], &line_info);
   line_info.selected = true;
   xvf_deparse_master_action_line(&line_info, database, subform->button_index);

   cb_data->subformptr->selected = true;
   cb_data->formptr->form_sel = true;

   FORM_DONE = True;
   current_form = cb_data->formptr;
   current_subform = NULL;
}



/************************************************************
*
* Routine Name:  xvf_subform_action_cb
*
*      Purpose:  This is the callback for the action button that resides 
*		 in a subform.  When this button is selected,
*		 the corresponding "selected" field in the UIS line is set 
*		 to a 1 and control is returned to the application.
*
*        Input:  widget     - the master action button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_subform_action_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   Line_Info line_info;
   char **database;
   xvf_guide_button *guide;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->formptr->db;
   guide = cb_data->guideptr;

   xvf_clear_line_info(&line_info);
   xvf_parse_subform_action_line(database[guide->index], &line_info);

   line_info.selected = true;

   xvf_deparse_subform_action_line(&line_info, database, guide->index);

   cb_data->guideptr->selected = true;
   cb_data->subformptr->subform_sel = true;

   FORM_DONE = True;
   current_subform = cb_data->subformptr;
   current_form = cb_data->formptr;
}



/************************************************************
*
* Routine Name:  xvf_pane_action_cb
* 
*      Purpose:  This is the callback for the action button that resides 
*		 in a pane.  When this button is selected,
*		 the corresponding "selected" field in the UIS line is set 
*		 to a 1 and control is returned to the application.
*
*        Input:  widget     - the master action button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_pane_action_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   int index;
   Callback_Data *cb_data;
   Line_Info line_info;
   xvf_sub_form *subformptr;
   char **database;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   subformptr = cb_data->subformptr;
   index = cb_data->selptr->index;

   /* set the action line to be selected */
   xvf_clear_line_info(&line_info);
   xvf_parse_pane_action_line(database[index], &line_info);
   line_info.selected = true;
   xvf_deparse_pane_action_line(&line_info, database, index);

   xvf_update_form_tree(database, index, subformptr);

   cb_data->subformptr->subform_sel = true;

   FORM_DONE = True;
   current_subform = cb_data->subformptr;
   current_form = cb_data->formptr;

   xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr); 

} /* end xvf_pane_action_cb */


/************************************************************
*
* Routine Name:  xvf_master_help_button_cb
*
*      Purpose:  This is the callback for a help button that resides 
*		 in the master form.  When this button is selected, the
*		 specified help page is displayed.  
*
*        Input:  widget     - the help button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_master_help_button_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   char **database;
   Line_Info line_info;
   xvf_sub_form *subform;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->formptr->db;
   subform  = cb_data->subformptr;

   /* set this line in the database to be selected */
   xvf_clear_line_info(&line_info);

   /* set the action line to be selected */
   xvf_parse_help_line(database[subform->button_index], &line_info);

   xvf_create_online_help(line_info.help_file, "Online Help");
   current_form = cb_data->formptr;
}


/************************************************************
*
* Routine Name:  xvf_subform_help_button_cb
*
*      Purpose:  This is the callback for a help button that resides 
*		 in a subform.  When this button is selected, the
*		 specified help page is displayed.  
*
*        Input:  widget     - the help button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_subform_help_button_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   Callback_Data *cb_data;
   char **database;
   Line_Info line_info;
   xvf_guide_button *guide;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   guide = cb_data->guideptr;

   /* set this line in the database to be selected */
   xvf_clear_line_info(&line_info);

   /* set the action line to be selected */
   xvf_parse_help_line(database[guide->index], &line_info);

   xvf_create_online_help(line_info.help_file, "Online Help");
   current_form = cb_data->formptr;
}



/************************************************************
*
* Routine Name:  xvf_pane_help_button_cb
*
*      Purpose:  This is the callback for a help button that resides 
*		 in a pane.  When this button is selected, the
*		 specified help page is displayed.  
*
*        Input:  widget     - the help button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

   
void xvf_pane_help_button_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
   int	index;
   Callback_Data *cb_data;
   char **database;
   Line_Info line_info;

   /* cast the pointer to the Callback data */
   cb_data = (Callback_Data *) clientData;
   database = cb_data->subformptr->db;
   index = cb_data->selptr->index;

   /* set this line in the database to be selected */
   xvf_clear_line_info(&line_info);

   /* set the action line to be selected */
   xvf_parse_help_line(database[index], &line_info);

   xvf_create_online_help(line_info.help_file, "Online Help");
   current_form = cb_data->formptr;
}

/************************************************************
*
* Routine Name:  xvf_routine_cb
*
*      Purpose:  This is the callback for the routine button.
*		 When this button is selected, the specified command
*		 is forked.  
*
*        Input:  widget     - the routine button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett, Danielle Argiro, Mark Young
*
*************************************************************/


void xvf_routine_cb(widget, clientData, callData)
Widget widget;
caddr_t clientData, callData;
{
	char          *command;
	Callback_Data *cb_data;
	Line_Info     line_info;

	/* cast the pointer to the Callback data */
	cb_data = (Callback_Data *) clientData;

	cb_data->guideptr = xvf_search_sel_guide(cb_data->subformptr);
	xvf_collect_check_data(cb_data->formptr, cb_data->formptr->db, 
			       cb_data->guideptr);

	/* form the command line */
	if (!(command = form2command(cb_data->formptr, cb_data->subformptr,
			NULL)))
	{
	   fprintf(stderr,"xvf_routine_cb:\n");
	   fprintf(stderr,"    ERROR: unable to build command.\n");
	   return;
	}

	xvf_reverse_colors (widget);
	xvf_clear_line_info(&line_info);
	xvf_parse_routine_line(cb_data->formptr->db[cb_data->selptr->index],
			       &line_info);

	/*
	 *  Need to parse the routine line and see if this is a expression
	 *  routine.  If so then we call xvf_expression() to run the routine
	 *  and update the expression parser.  Otherwise we call xvf_system()
	 *  system off the routine.
	 */
	if (line_info.exec_type == 4)
	   xvf_expression(cb_data->formptr, command);
	else
	   xvf_system(command);

	free(command);
	xvf_reverse_colors (widget);
}


/************************************************************
*
* Routine Name:  xvf_glyph_cb
*
*      Purpose:  This is the callback for the glyph button appears at
*		 the upper left of the master form, or the subform if no
*		 master form is used. When this button is selected, the entire
*		 graphical user interface is unmapped and the glyph 
*		 representation of the form is mapped.  
*
*        Input:  widget     - the glyph button
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

void xvf_glyph_cb(widget, clientData, callData)

Widget widget;
caddr_t clientData, callData;
{
	Callback_Data *cb_data = (Callback_Data *) clientData;

	xvf_glyph(cb_data);
}

/************************************************************
*
*  Routine Name:  xvf_unglyph_cb(widget, clientData, callData)
*
*      Purpose:  This is the callback for the glyph button that
*		 is displayed when the graphical user interface is
*		 in glyph state.  When this button is selected, the 
*		 glyph is unmapped and the graphical user interface
*		 is remapped.
*
*        Input:  widget     - the glyph rep. of the graphical user interface
*	         clientData - pointer used to pass cb_data 
*		 callData   - not used 
*
*   Written By:  Stephanie Hallett and Danielle Argiro
*
*
*************************************************************/


void xvf_unglyph_cb(widget, clientData, callData)

Widget widget;
caddr_t clientData, callData;
{
	Callback_Data *cb_data = (Callback_Data *) clientData;

	xvf_unglyph(cb_data);
}


/************************************************************
*
*  MODULE NAME: xvf_glyph_handler
*
*      PURPOSE:
*
*
*        INPUT: widget     -  the widget for the event
*               clientData -  not used
*               event      -  the event
*
*       OUTPUT: none - refresh_animate() does the actual refreshing
*
*   WRITTEN BY:
*
************************************************************/


void xvf_glyph_handler(widget, clientData, event)

Widget  widget;
caddr_t clientData;
XEvent  *event;
{
	Callback_Data *cb_data = (Callback_Data *) clientData;

	int glyph_state;


	if (cb_data->subformptr == NULL)
	   glyph_state = cb_data->formptr->glyph_state;
	else
	   glyph_state = cb_data->subformptr->glyph_state;

	if (event->type == MapNotify && glyph_state == true)
	{
	   xvf_unglyph(cb_data);
	}
	else if (event->type == UnmapNotify && glyph_state == false)
	{
	   xvf_glyph(cb_data);
	}
}

/************************************************************
*
* Routine Name:  xvf_glyph(cb_data)
*
*      Purpose:  This is the routine for the glyph button appears at
*		 the upper left of the master form, or the subform if no
*		 master form is used. When this button is selected, the entire
*		 graphical user interface is unmapped and the glyph 
*		 representation of the form is mapped.  
*
*        Input:  cb_data - the callback data used by xvf_glyph_cb or
*			   xvf_glyph_handler.
*
*   Written By: Danielle Argiro
*
*************************************************************/


xvf_glyph(cb_data)

Callback_Data *cb_data;
{
	xvf_form         *form;
	xvf_sub_form     *subform;
	xvf_guide_button *guide;


	form = cb_data->formptr;
	if (cb_data->subformptr == NULL)
	{
	   /* unmap form */
	   xvf_unmap_form(form);

	   /* change global list to know that this form is glyphed */
	   xvf_change_glyph(form, true);
	   form->glyph_state = true;

	   /* map glyph */
	   xvf_map_form(form);
	}
	else
	{
	   subform = cb_data->subformptr;

	   /* unmap subform */
	   xvf_unmap_subform(subform);

	   /* find active guide and collect and check data */
	   guide = xvf_search_sel_guide(subform);
	   xvf_collect_check_data(form, subform->db, guide);

	   /* change glyph state to show this subform is glyphed */
	   subform->glyph_state = true;

	   /* map glyph */
	   xvf_map_subform(form, subform);
	}
	FORM_DONE = true;
	current_form    = cb_data->formptr;
	current_subform = cb_data->subformptr;
}


/************************************************************
*
*  Routine Name:  xvf_unglyph(cb_data)
*
*      Purpose:  This is the callback for the glyph button that
*		 is displayed when the graphical user interface is
*		 in glyph state.  When this button is selected, the 
*		 glyph is unmapped and the graphical user interface
*		 is remapped.
*
*        Input:  cb_data - the callback data used by xvf_glyph_cb or
*			   xvf_glyph_handler.
*
*   Written By:  Danielle Argiro
*
*
*************************************************************/


xvf_unglyph(cb_data)

Callback_Data *cb_data;
{
	xvf_form         *form;
	xvf_sub_form     *subform;
	xvf_guide_button *guide;

	/*
	 *  Make sure the cb_data is valid.
	 */
	if (cb_data == NULL)
	   return;
	else if (cb_data->formptr == NULL)
	   return;

	/*
	 *  Glyphs can be on either a form or subform.  So if the cb_data
	 *  subform is NULL then we know this is form glyph, otherwise it
	 *  is a subform glyph.
	 */
	form = cb_data->formptr;
	if (cb_data->subformptr == NULL)
	{
	   /* unmap glyph */
	   xvf_unmap_form(form);
   
	   /* change global list to know that this form is not glyphed */
	   xvf_change_glyph(form, false);
	   form->glyph_state = false;	/* form state */

	   /* map form */
	   xvf_map_form(form);
	}
	else
	{
	   subform = cb_data->subformptr;

	   /* unmap glyph */
	   xvf_unmap_subform(subform);

	   /* find active guide and collect and check data */
           guide = xvf_search_sel_guide(subform);
           xvf_collect_check_data(form, subform->db, guide);

	   /* change state in form to know that form is not glyphed */
	   subform->glyph_state = false;

	   /* map form */
	   xvf_map_subform(cb_data->formptr, subform);
	}
	current_form = cb_data->formptr;
	current_subform = cb_data->subformptr;
	FORM_DONE = true;
}


/************************************************************
*
* Routine Name:  xvf_do_toggle()
*
*      Purpose:  This is the subroutine for each of the buttons that make
*		 integer, float, string, infile or outfile selections
*		 part of a toggle.
*
*        Input:  widget       - the widget representing the current toggle item
*	         start_toggle - the selection node containing
*		      	        the root of the toggle.
*		 cb_data      - structure containing callback data
*
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

void xvf_do_toggle(widget,start_toggle,cb_data)
Widget widget;
xvf_selection *start_toggle;
Callback_Data *cb_data;
{
   Line_Info line_info;
   xvf_selection *old_tog, *cur_tog;
   char **database;


   database = cb_data->subformptr->db;

   /* mark toggle changed */
   start_toggle->modified = true;

   /* highlight the current guide button */
   xvf_reverse_colors(widget);

   /* search for the guide button that was selected before */
   old_tog = start_toggle->toggle_next;
   while ((old_tog->opt_selected != true) && (old_tog->next != NULL))
        old_tog = old_tog->next;

   /* found the last selected toggle option */
   if (old_tog->opt_selected == true)
   {
       /* un-highlight that widget */
       xvf_reverse_colors(old_tog->opt_widget);

       /* change the line in the database associated with that widget,
          indicating that it is no longer selected */
       xvf_change_opt_selected(database,old_tog->index,
			       old_tog->opt_widget,false);
       old_tog->opt_selected = false;
   }

   /* change the line in the database associated with the new toggle */
   xvf_change_opt_selected(database,cb_data->selptr->index, widget,true);
   cur_tog = start_toggle->toggle_next;
   while ((cur_tog->opt_widget != widget) && (cur_tog->next != NULL))
       cur_tog = cur_tog->next;
   cur_tog->opt_selected = true;

   /* show that the toggle selection has been touched */
   xvf_clear_line_info(&line_info);
   xvf_parse_toggle_line(database[start_toggle->index], 
	&line_info);
   line_info.selected = true;
   line_info.toggle_val = cur_tog->toggle_int;
   xvf_deparse_toggle_line(&line_info, database,
	start_toggle->index);

   if (line_info.live == true)  
   {
        xvf_update_form_tree(database, cb_data->selptr->index, 
     			     cb_data->subformptr);

        cb_data->subformptr->subform_sel = true;

        FORM_DONE = True;
        current_subform = cb_data->subformptr;
        current_form = cb_data->formptr;

        xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr); 

   }
   current_form = cb_data->formptr;
}

/************************************************************
*
* Routine Name:  xvf_do_mut_exclusion()
*
*      Purpose:  This is the subroutine for each of the buttons that make
*		 integer, float, string, infile or outfile selections
*		 part of a mutually exclusive group.
*
*        Input:  widget       - the widget representing the 
*				currently selected item in the M.E. group
*		 cb_data      - structure containing callback data
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
*************************************************************/

xvf_do_mut_exclusion(widget,cb_data)
Widget widget;
Callback_Data *cb_data;
{
   Line_Info line_info;
   xvf_pane  *paneptr;
   xvf_selection *cur_sel, *opposing_sel;
   int num;
   mut_excl_link *mut_excl_ptr;
   char **database;

   cur_sel = cb_data->selptr;
   database = cb_data->subformptr->db;

   num = cb_data->selptr->mut_excl_id;
   paneptr = cb_data->guideptr->pane;

   mut_excl_ptr = paneptr->mut_exclusion[num];
   while (mut_excl_ptr != NULL)
   {
	 opposing_sel = xvf_sel_search(cb_data->formptr, mut_excl_ptr->index);

	 /* one of the other elements in the mutually exclusive group */
         if (opposing_sel->opt_widget != widget)
	 {
	      /* if that was the one previously selected, turn it off */
              if (opposing_sel->opt_selected == true)
              {
                  xvf_reverse_colors(opposing_sel->opt_widget);

		  opposing_sel->opt_selected = false;
    		  opposing_sel->selected = false;

                  xvf_clear_line_info(&line_info);
		  xvf_gen_parse(database[opposing_sel->index], 
				&line_info);
    		  line_info.selected = false;
    		  line_info.opt_sel = false;
    		  xvf_gen_deparse(&line_info, database, 
				  opposing_sel->index);
              }
	}
	else
 	{
	      /* if the same one was previously selected, dont turn it off */
              if (opposing_sel->opt_selected != true)
	      {
   		   xvf_reverse_colors(widget);
	      }
	}
        mut_excl_ptr = mut_excl_ptr->next;
    }


   /* change the line in the database associated with the new selection */
    cur_sel->opt_selected = true;
    cur_sel->selected = true;
    cur_sel->modified = true;

    xvf_clear_line_info(&line_info);
    xvf_gen_parse(database[cur_sel->index], &line_info);
    line_info.selected = true;
    line_info.opt_sel = true;
    xvf_gen_deparse(&line_info, database, cur_sel->index);

   if (line_info.live == true)  
   {
        xvf_update_form_tree(database, cb_data->selptr->index, 
     			     cb_data->subformptr);

        cb_data->subformptr->subform_sel = true;

	if (line_info.typeflag == LogicOpt)
            FORM_DONE = True; 
        current_subform = cb_data->subformptr;
        current_form = cb_data->formptr;

        xvf_collect_check_data(cb_data->formptr, database, cb_data->guideptr); 

   }
   current_form = cb_data->formptr;
}

/************************************************************
*
* Routine Name:  xvf_change_opt_selected()
*
*      Purpose:  Changes the optional_selected field in
*		 a UIS line to 1 or 0, as specified by "state".
*
*        Input:  database - the database for the form
*		 index - the index into the database for
*			the desired line.
*                widget - the widget corresponding to the 
*			latest toggle selected
*	         state - true(1)/false(0) indicates how to set database line. 
*
*
*   Written By: Stephanie Hallett and Danielle Argiro
*
***************************************************************/

void xvf_change_opt_selected(database,index,widget,state)
char *database[];
int index;
Widget	widget;
int state;
{
   Line_Info line_info;
   int	     flag;

   xvf_clear_line_info(&line_info);

   flag = xvf_get_line_type(database[index]);
   
   switch (flag) {
      case InputFile:
		xvf_parse_input_line(database[index],&line_info);
		line_info.opt_sel = state;
		xvf_deparse_input_line(&line_info,database,index);
		break;
      case OutputFile:
		xvf_parse_output_line(database[index],&line_info);
		line_info.opt_sel = state;
		xvf_deparse_output_line(&line_info,database,index);
		break;
      case IntegerOpt:
		xvf_parse_int_line(database[index],&line_info);
		line_info.opt_sel = state;
		xvf_deparse_int_line(&line_info,database,index);
		break;
      case FloatOpt:
		xvf_parse_float_line(database[index],&line_info);
		line_info.opt_sel = state;
		xvf_deparse_float_line(&line_info,database,index);
		break;
      case LogicOpt:
		xvf_parse_logic_line(database[index],&line_info);
		line_info.opt_sel = state;
		/* change the label in the widget accordingly 
                if (state == true)
                   XtSetArg(arg[0],XtNlabel,"on");
		else
                   XtSetArg(arg[0],XtNlabel,"off");
                XtSetValues(widget,arg,1); */
		xvf_deparse_logic_line(&line_info,database,index);
		break;
      case StringOpt:
		xvf_parse_string_line(database[index],&line_info);
		line_info.opt_sel = state;
		xvf_deparse_string_line(&line_info,database,index);
		break;
      default:
		break;
   }
}

