 /*
  * Khoros: $Id: answer.c,v 1.4 1992/03/20 22:48:32 dkhoros Exp $
  */

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

 /*
  * $Log: answer.c,v $
 * Revision 1.4  1992/03/20  22:48:32  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"

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>       filename: actions.c			      <<<<
   >>>>                                                       <<<<
   >>>>		       Action Routines                        <<<<
   >>>>                                                       <<<<
   >>>>       These are the XtActionProc's that are called    <<<<
   >>>>       when the user hits <CR> in a parameter box      <<<<
   >>>>       of an AnswerInfile or AnswerOutfile selection   <<<<
   >>>>                                                       <<<<
   >>>>            xvf_update_forms_from_answerfile()         <<<<
   >>>>            xvf_update_answerfile_from_forms()         <<<<
   >>>>                                                       <<<<
   >>>>            xvf_read_answerfile()            	      <<<<
   >>>>            xvf_write_answerfile()  	              <<<<
   >>>>            get_toggle_number()  	              <<<<
   >>>>            get_toggle_value()  	              	      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
 

/************************************************************
*
* Routine Name:  xvf_update_forms_from_answerfile
*
*      Purpose:  This is the XtActionProc that is initiated when 
*	 	 the user enters a filename in the AnswerInfile
*		 parameter box (asciiString widget) and hits <CR>.  
*		 It updates the values in the forms according to
*		 the answer file.
*
*        Input:  widget - the value widget of the input file selection
*		 event  -  the event that initiated this Action Procedure (<cr>)
*	         params -  can't figure out how to use this properly.
*		 num_params -  see params
*
*   Written By: Danielle Argiro
*
*************************************************************/

void xvf_update_forms_from_answerfile(widget, event, params, num_params)
Widget widget;
XEvent *event;
String *params;
Cardinal *num_params;
{

   Callback_Data *live_data;
   xvf_live_sel_link *live_sel_ptr;
   xvf_selection *current;
   Line_Info  line_info;
   char **database;
   int    index;


   /*
    * find the correct live_sel_data info for this answer file selection
    */
   live_sel_ptr = live_sel_list;
   if (live_sel_ptr == NULL)
   {
       fprintf(stderr, "xvf_update_forms_from_answerfile: \n");
       fprintf(stderr, "   ERROR: something awful wrong; linking struct NULL\n");
       return;
   }
   while (live_sel_ptr->value_widget != widget)
        live_sel_ptr = live_sel_ptr->next;
   live_data = live_sel_ptr->live_data;

   /*
    *  update the database line for this answer file selection,
    *  update the form tree, set the current form and current subform,
    *  collect & check the data from the current pane, and indicate FORM_DONE
    */
   database = live_data->formptr->db;
   index    = live_data->selptr->index;
   xvf_clear_line_info(&line_info);
   xvf_parse_ansinfile_line(database[index], &line_info);
   current = xvf_sel_search(live_data->formptr, index);
   if (!(xvf_collect_ansinfile(live_data->formptr,database, current)))
         return;

   line_info.selected = true;
   line_info.filename = xvf_strcpy(current->buffer);
   line_info.literal = xvf_strcpy(current->buffer);
   xvf_deparse_ansinfile_line(&line_info, database, index);

   xvf_read_answerfile(live_data->formptr, line_info.filename);

   xvf_update_form_tree(database, index, live_data->subformptr);
   xvf_collect_check_data(live_data->formptr, database, live_data->guideptr);

}


/************************************************************
*
* Routine Name:  xvf_update_answerfile_from_forms
*
*      Purpose:  This is the XtActionProc that is initiated when 
*	 	 the user enters a filename in the AnswerOutfile
*		 parameter box (asciiString widget) and hits <CR>.  
*		 It creates an answer file based on the values 
*		 currently found in the forms.
*
*        Input:  widget - the value widget of the input file selection
*		 event  -  the event that initiated this Action Procedure 
*			   (<cr>)
*	         params -  can't figure out how to use this properly.
*		 num_params -  see params
*
*   Written By: Danielle Argiro
*
*************************************************************/

void xvf_update_answerfile_from_forms(widget, event, params, num_params)
Widget widget;
XEvent *event;
String *params;
Cardinal *num_params;
{

   Callback_Data *live_data;
   xvf_live_sel_link *live_sel_ptr;
   xvf_selection *current;
   Line_Info  line_info;
   char **database;
   int    index;


   /*
    * find the correct live_sel_data info for this answer file selection
    */
   live_sel_ptr = live_sel_list;
   if (live_sel_ptr == NULL)
   {
       fprintf(stderr, "xvf_update_forms_from_answerfile: \n");
       fprintf(stderr, "   ERROR: something awful wrong; linking struct NULL\n");
       return;
   }
   while (live_sel_ptr->value_widget != widget)
        live_sel_ptr = live_sel_ptr->next;
   live_data = live_sel_ptr->live_data;

   /*
    *  update the database line for this Answer Outfile selection,
    *  update the form tree, set the current form and current subform,
    *  collect & check the data from the current pane, write to answer file
    */
   database = live_data->formptr->db;
   index    = live_data->selptr->index;
   xvf_clear_line_info(&line_info);
   xvf_parse_ansoutfile_line(database[index], &line_info);

   current = xvf_sel_search(live_data->formptr, index);
   if (!(xvf_collect_ansinfile(live_data->formptr,database, current)))
         return;

   line_info.selected = true;
   line_info.filename = xvf_strcpy(current->buffer);
   line_info.literal = xvf_strcpy(current->buffer);

   xvf_deparse_ansoutfile_line(&line_info, database, index);
   xvf_update_form_tree(database, index, live_data->subformptr);
   xvf_collect_check_data(live_data->formptr, database, live_data->guideptr);

   if (!(xvf_write_answerfile(live_data->formptr, live_data->guideptr, 
                              line_info.filename))) return;

}



/************************************************************
*
* Routine Name:  xvf_read_answerfile
*
*      Purpose:  updates the forms according to the 
*		 input answer file provided
*
*        Input:  formptr - pointer to the form tree
*		 filename - name of the answer file to output
*
*   Written By: Danielle Argiro
*
************************************************************/

xvf_read_answerfile(formptr, filename)
xvf_form *formptr;
char *filename;
{
   int fid, status;
   xvf_selection *selection;
   xvf_guide_button *guide;
   xvf_sub_form *subform;
   Line_Info line_info;
   char temp[MaxLength], option[MaxLength];
   char *stringval;
   int  intval, optval;
   float floatval;
   int  countfound = 0;


   if ((fid = open(filename, O_RDONLY, 0666))== -1)
   {
      sprintf(temp, "Cannot open answer file %s", filename);
      xvf_error_wait(temp, "xvf_read_answerfile", NULL);
      return;
   }
   else
   {
      /* kludge to be able to load multiple answer files (John Salas) */
      init_afile_args(fid);
   }

   xvf_clear_line_info(&line_info);

   subform = formptr->subform;
   while (subform != NULL)
   {
	guide = subform->guide_button;
        while (guide != NULL)
        {
            if (guide->pane != NULL)
            {
                selection = guide->pane->sel_list;
                while (selection != NULL)
                {
		   xvf_gen_parse(formptr->db[selection->index], 
				           &line_info);
		    switch(line_info.typeflag)
		    {
			case InputFile:
			     sprintf(option, "-%s", line_info.variable);
			     status = vget_infile(fid, False, option, 
					 line_info.description, &(stringval));
			     if (status == 1)
			     {
			        xvf_change_input(formptr, selection->index,
					      xvf_inputfile_chng, stringval, 0);
			 	countfound++;
			     }
			     if (line_info.optional == 1)
				change_opt_sel(fid, formptr, selection->index, 
					       option, line_info.description);
			     break;
			     
			case OutputFile:
			     sprintf(option, "-%s", line_info.variable);
			     status = vget_outfile(fid, False, option, 
					 line_info.description, &(stringval));
			     if (status == 1)
			     {
			        xvf_change_input(formptr, selection->index,
					      xvf_outputfile_chng, 
					      stringval, 0);
				countfound++;
			     }
			     if (line_info.optional == 1)
				change_opt_sel(fid, formptr, selection->index, 
					       option, line_info.description);
			     break;
			     
			case IntegerOpt:
			     sprintf(option, "-%s", line_info.variable);
			     status = vget_int(fid, False, option, 
				      line_info.description,
			              &intval, line_info.int_val, 
				      line_info.lower_int, 
				      line_info.upper_int);
			     if (status == 1)
			     {
			        sprintf(temp, "%d", intval);
			        xvf_change_input(formptr, selection->index,
					      xvf_intval_chng, temp, 0);
				countfound++;
			     }
			     if (line_info.optional == 1)
				change_opt_sel(fid, formptr, selection->index, 
					       option, line_info.description);
			     break;
			     
			case StringOpt:
			     sprintf(option, "-%s", line_info.variable);
			     status = vget_string(fid, False, option, 
				        line_info.description,
			                &(stringval), line_info.string_val);
			     if (status == 1)
			     {
			         xvf_change_input(formptr, selection->index,
					      xvf_stringval_chng, 
					      stringval, 0);
				 countfound++;
			     }
			     if (line_info.optional == 1)
				change_opt_sel(fid, formptr, selection->index, 
					       option, line_info.description);
			     break;
			     
			case FloatOpt:
			     sprintf(option, "-%s", line_info.variable);
			     status = vget_float(fid, False, option, 
					line_info.description, &floatval, 
				        line_info.float_val,
				 	line_info.lower_float, 
				        line_info.upper_float);
			     if (status == 1)
			     {
			        sprintf(temp, "%g", floatval);
			        xvf_change_input(formptr, selection->index,
			   		      xvf_floatval_chng, temp, 0);
				countfound++;
			     }
			     if (line_info.optional == 1)
				change_opt_sel(fid, formptr, selection->index, 
					       option, line_info.description);
			     break;

			case LogicOpt:
			     sprintf(option, "-%s", line_info.variable);
			     status = vget_logic(fid, False, option, 
					line_info.description,
			                &intval, line_info.logical_val);
			     if (status == 1)
			     {
			         sprintf(temp, "%d", intval);
			         xvf_change_input(formptr, selection->index,
				    	      xvf_logicalval_chng, temp, 0);
				 countfound++;
			     }
			     if (line_info.optional == 1)
				change_opt_sel(fid, formptr, selection->index, 
					       option, line_info.description);
			     break;
			     
			case Cycle:
			     sprintf(option, "-%s", line_info.variable);
			     status = vget_int(fid, False, option, 
				      line_info.description,
			              &intval, line_info.cycle_val,
				      1, 50);
			     if (status == 1)
			     {
			        sprintf(temp, "%d", intval);
			        xvf_change_input(formptr, selection->index,
			   		      xvf_cycleval_chng, temp, 0);
				countfound++;
			     }
			     if (line_info.optional == 1)
				change_opt_sel(fid, formptr, selection->index, 
					       option, line_info.description);
			     break;
			     
		        case Toggle:
			     sprintf(option, "-%s", line_info.variable);
			     intval = get_toggle_number(fid, formptr, selection,
							option, line_info);
			     if (intval > 0)
			     {
			         sprintf(temp, "%d", intval);
			         xvf_change_input(formptr, selection->index,
					          xvf_toggleval_chng, temp, 0);
				 countfound++;
			     }
			     if (line_info.optional == 1)
				change_opt_sel(fid, formptr, selection->index, 
					       option, line_info.description);
			     break;
			     
	            }
		    selection = selection->next;
	        }
	    }
	    guide = guide->next_button;
        }
	subform = subform->next_subform;
   }

   if (countfound == 0)
   {
       sprintf(temp, "Unable to update graphical user interface from file %s;  not a valid answer file for this pane.", filename);
       xvf_error_wait(temp, "xvf_read_answerfile", NULL);
   }
   close_afile(fid);
}


/************************************************************
*
* Routine Name:  xvf_write_answerfile
*
*      Purpose:  writes out the answer file according to values 
*		 in forms
*
*        Input:  formptr - pointer to the form tree
*		 filename - name of the answer file to output
*
*   Written By: Danielle Argiro
*
************************************************************/

xvf_write_answerfile(formptr, guide, filename)
xvf_form *formptr;
xvf_guide_button *guide;
char *filename;
{
   FILE *file, *tmpfile;
   xvf_selection *selection;
   Line_Info line_info;
   char temp[MaxLength];
   char *toggle_value, *get_toggle_value();
   int  status;

   if (tmpfile = fopen(filename, "r"))
   {
       sprintf(temp, "\nOverwrite file '%s'?: ",filename);
       status = xvf_warn_wait(temp, NULL, "Yes", "No");
       if (status == 0)
       {
           fclose(tmpfile);
           return;
       }
       else
           fclose(tmpfile);
   }

   if ((file = fopen(filename, "w")) == NULL)
   {
      sprintf(temp, "Cannot write to answer file %s", filename);
      xvf_error_wait(temp, "xvf_write_answerfile", NULL);
      return;
   }

   xvf_clear_line_info(&line_info);

   if (guide->pane != NULL)
   {
                selection = guide->pane->sel_list;
                while (selection != NULL)
                {
		    status = xvf_gen_parse(formptr->db[selection->index], 
			     &line_info);
		    switch(line_info.typeflag)
		    {
			case InputFile:
			     if ((status > 0) && (line_info.filename != NULL))
			     {
			        fprintf(file, "-%s %s\n", line_info.variable,
				     line_info.filename);
				if (line_info.optional == 1)
				   fprintf(file, "-%s_opt %d\n", 
					line_info.variable, line_info.opt_sel);
			     }
			     break;
			     
			case OutputFile:
			     if ((status > 0) && (line_info.filename != NULL))
			     {
			        fprintf(file, "-%s %s\n", line_info.variable,
				     line_info.filename);
				if (line_info.optional == 1)
				   fprintf(file, "-%s_opt %d\n", 
					line_info.variable, line_info.opt_sel);
			     }
			     break;
			     
			case IntegerOpt:
			     if (status > 0)
			     {
			        fprintf(file, "-%s %d\n", line_info.variable,
				     line_info.int_val);
				if (line_info.optional == 1)
				   fprintf(file, "-%s_opt %d\n", 
					line_info.variable, line_info.opt_sel);
			     }
			     break;
			     
			case StringOpt:
			     if (status > 0)
			     {
			        fprintf(file, "-%s %s\n", line_info.variable,
				     line_info.string_val);
				if (line_info.optional == 1)
				   fprintf(file, "-%s_opt %d\n", 
					line_info.variable, line_info.opt_sel);
			     }
			     break;
			     
			case FloatOpt:
			     if (status > 0)
			     {
			        fprintf(file, "-%s %g\n", line_info.variable,
				     line_info.float_val);
				if (line_info.optional == 1)
				   fprintf(file, "-%s_opt %d\n", 
					line_info.variable, line_info.opt_sel);
			     }
			     break;

			case LogicOpt:
			     if (status > 0)
			     {
			        fprintf(file, "-%s %d\n", line_info.variable,
				     line_info.logical_val);
				if (line_info.optional == 1)
				   fprintf(file, "-%s_opt %d\n", 
					line_info.variable, line_info.opt_sel);
			     }
			     break;
			     
			case Cycle:
			     if (status > 0)
			     {
			        fprintf(file, "-%s %d\n", line_info.variable,
				     line_info.cycle_val);
				if (line_info.optional == 1)
				   fprintf(file, "-%s_opt %d\n", 
					line_info.variable, line_info.opt_sel);
			     }
			     break;
			     
		        case Toggle:
			     /* toggle_value = get_toggle_value(formptr, 
					     selection, line_info.toggle_val);
			      */
			     if (status > 0)
			     {
			        fprintf(file, "-%s %d\n", line_info.variable,
				     line_info.toggle_val);
				if (line_info.optional == 1)
				   fprintf(file, "-%s_opt %d\n", 
					line_info.variable, line_info.opt_sel);
			     }
			     break;
			     
	            }
		    if (status == 0)
		       xvf_error_wait("Omitting line from answer file",
				      "xvf_write_answer_file", NULL);
		    selection = selection->next;
	        }
	    }
   fclose(file);
   sprintf(temp, "Answer file written to file %s", filename);
   xvf_error_wait(temp, "xvf_write_answerfile", NULL);
}


/************************************************************
*
* Routine Name:  get_toggle_number
*
*      Purpose:  gets the number of the toggle member whose
*		 default value is to be used to update forms
*
*        Input:  fid - file descriptor of open answer file
*		 formptr - pointer to the form tree
*		 selection - selection node pointing to toggle
*		 option - command line argument assoc w/ toggle 
*		 line_info - Line_Info struct describing toggle
*
*   Written By: Danielle Argiro
*
************************************************************/

int get_toggle_number(fid, formptr, selection, option, line_info)
xvf_form *formptr;
xvf_selection *selection;
char *option;
Line_Info line_info;
{
	char *stringval;
	int toggle_type, intval, count, status;
	float floatval;
	Line_Info tmp_line_info;

	xvf_clear_line_info(&tmp_line_info);

	if (!(xvf_gen_parse(formptr->db[selection->index+1], &tmp_line_info)))
	   return(false);
	toggle_type = tmp_line_info.typeflag;
	count = 0;

	switch(toggle_type)
	{
	    case InputFile:
		 status = vget_infile(fid, False, option,
                             line_info.description, &(stringval));
		 if (status == 1)
		 {
		 selection = selection->toggle_next;
		 while (selection != NULL)
		 {
		     xvf_gen_parse(formptr->db[selection->index], 
				   &tmp_line_info);
	             if (VStrcmp(stringval, tmp_line_info.filename)!=0) 
		     {
			selection = selection->next;
			count++;
		     }
		     else return(count+1);
	         }
		 }
		 break;

 	    case OutputFile:
	         status = vget_outfile(fid, False, option,
                              line_info.description, &(stringval));
		 if (status == 1)
		 {
		 selection = selection->toggle_next;
		 while (selection != NULL)
		 {
		     xvf_gen_parse(formptr->db[selection->index], 
				   &tmp_line_info);
	             if (VStrcmp(stringval, tmp_line_info.filename)!=0) 
		     {
			selection = selection->next;
			count++;
		     }
		     else return(count+1);
	         }
		 }
	         break;

	    case IntegerOpt:
	         status = vget_int(fid, False, option, line_info.description,
			  &intval, line_info.toggle_def, 1, 50);
		 if (status == 1)
		    count = intval;
	         break;

	    case LogicOpt:
	         status = vget_int(fid, False, option, line_info.description,
			  &intval, line_info.toggle_def, 1, 50);
		 if (status == 1)
		    count = intval;
	         break;

            case FloatOpt:
	         status = vget_float(fid, False, option, line_info.description,
			  &floatval, line_info.toggle_def, 1, 50);
		 if (status == 1)
		 {
		 selection = selection->toggle_next;
		 while (selection != NULL)
		 {
		     xvf_gen_parse(formptr->db[selection->index], 
				   &tmp_line_info);
	             if (tmp_line_info.float_val != floatval) 
		     {
			selection = selection->next;
			count++;
		     }
		     else return(count+1);
	         }
		 }
		 break;

            case StringOpt:
 	         status = vget_string(fid, False, option, line_info.description,
                             &(stringval), line_info.string_def);
		 if (status == 1)
		 {
		 selection = selection->toggle_next;
		 while (selection != NULL)
		 {
		     xvf_gen_parse(formptr->db[selection->index], 
				   &tmp_line_info);
	             if (VStrcmp(stringval, tmp_line_info.string_val)!=0) 
		     {
			selection = selection->next;
			count++;
		     }
		     else return(count+1);
	         }
		 }
		 break;

	}

	return(count);
}


/************************************************************
*
* Routine Name:  get_toggle_value
*
*      Purpose:  gets the value of the toggle member 
*		 that is currently selected, returns it in string form
*
*        Input:  formptr - pointer to the form tree
*		 selection - selection node pointing to toggle
*		 item_selected - number of the selected toggle item
*
*   Written By: Danielle Argiro
*
************************************************************/

char *get_toggle_value(formptr, selection, item_selected)
xvf_form *formptr;
xvf_selection *selection;
int       item_selected;
{
	char temp[MaxLength];
	char **database;
	int toggle_type, count;
	float floatval;
	Line_Info line_info;

	xvf_clear_line_info(&line_info);
	database = formptr->db;

	xvf_gen_parse(database[selection->index+1], &line_info);
	toggle_type = line_info.typeflag;
	count = 1;
	item_selected += selection->index;

	switch(toggle_type)
	{
	    case InputFile:
		 xvf_parse_input_line(formptr->db[item_selected], 
				      &line_info);
		 sprintf(temp, "%s", line_info.file_def);
		 break;

 	    case OutputFile:
		 xvf_parse_output_line(formptr->db[item_selected], 
				      &line_info);
		 sprintf(temp, "%s", line_info.file_def);
	         break;

	    case IntegerOpt:
		 xvf_parse_int_line(formptr->db[item_selected], 
				      &line_info);
		 sprintf(temp, "%d", line_info.int_def);
	         break;

	    case LogicOpt:
		 sprintf(temp, "%d", item_selected-selection->index);
	         break;

            case FloatOpt:
		 xvf_parse_float_line(formptr->db[item_selected], 
				      &line_info);
		 sprintf(temp, "%g", line_info.float_def);
		 break;

            case StringOpt:
		 xvf_parse_string_line(formptr->db[item_selected], 
				      &line_info);
		 sprintf(temp, "%s", line_info.string_def);
		 break;
	}
	return(xvf_strcpy(temp));
}

change_opt_sel(fid, formptr, index, option, desc)
int fid;
xvf_form *formptr;
int  index;
char *option;
char *desc;
{
	char temp[MaxLength];
	int  status, optval;

	sprintf(temp, "%s_opt", option);
	status = vget_logic(fid, False, temp, desc, &optval, 1);
	if (status == 1)
	{
	    sprintf(temp, "%d", optval);
	    xvf_change_input(formptr, index, xvf_optsel_chng, temp, 0);
         }
}
