 /*
  * Khoros: $Id: createtree.c,v 1.5 1992/03/20 22:47:41 dkhoros Exp $
  */

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

 /*
  * $Log: createtree.c,v $
 * Revision 1.5  1992/03/20  22:47:41  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"

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>             file name: createtree.c                   <<<<
   >>>>                                                       <<<<
   >>>>		       Form  Creation Routines                <<<<
   >>>>                                                       <<<<
   >>>>       These routines create the managing form tree    <<<<
   >>>>       structure in which all info about               <<<< 
   >>>>       the forms is stored & maintained.               <<<<
   >>>>                                                       <<<<
   >>>>                xvf_create_form()                      <<<<
   >>>>                xvf_build_form()                       <<<<
   >>>>                xvf_fill_in_subform()                  <<<<
   >>>>                xvf_fill_in_master()                   <<<<
   >>>>                xvf_fill_in_guide()                    <<<<
   >>>>                xvf_fill_in_pane()                     <<<<
   >>>>                xvf_fill_in_toggle()                   <<<<
   >>>>                                                       <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  */



/************************************************************
*
* Routine Name:  xvf_create_form
*
*      Purpose: Simply a front end for the form creation routines, it
*		calls xvf_read_database() to read the user interface 
*		specification indicated by "filename", and hands off
*		the correct parameters to xvf_build_form() to create
*		the forms.
*
*        Input: filename    - name of the database file
*		argv & argc - program arguments
*		glyph_type  - type of glyph associated with this form
*		callback_routine- optional callback routine for this form 
*	        x, y	    - location to place the newly created form. If
*				 -1 then ignore the placement setting.
*
*       Output: returns a pointer to the xvf_form structure 
*
*   Written By: Danielle Argiro and Stephanie Hallett
*
*     Comments: This is the main driver for the routines that create
*		the form, both physically (the graphical user interface
*	        made up of widgets) and internally (the abstract data structure
*		referred to as a form tree).  
*
*
*************************************************************/

xvf_form *xvf_create_form(filename, argv, argc, glyph_type, 
			  callback_routine, x, y)

char 		*filename;	/* name of database file 		*/
char 		**argv;		/* program arguments			*/
unsigned int  	argc;		/* number of program arguments 		*/
int		glyph_type;	/* simple or in_out glyph 		*/
void		(* callback_routine)();	/* callback for form if desired */
int		x, y;
{
	FILE		*file;
	char		*fullpath, **database, temp[MaxLength];
	xvf_form 	*form;
	int 	        line_num, db_size;

	if (!(fullpath = vfullpath(filename, NULL, NULL)))
	{
	   sprintf(temp, "Unable to expand '%s' in order to read user interface\
 specification file",filename);
           xvf_error_wait(temp, "xvf_create_form", NULL);
           return(NULL);
	}

	if (!(file = fopen(fullpath, "r")))
        {
           sprintf(temp, "Unable to open '%s' to read user interface specification", fullpath);
           xvf_error_wait(temp, "xvf_create_form", NULL);
           return(NULL);
        }

	database = xvf_read_database(file, &line_num, &db_size);
	if (database == NULL)
	{
	   fclose(file); free(fullpath);
	   return(NULL);
	}

	form = xvf_build_form(database, line_num, db_size, argv, argc,
			      glyph_type, callback_routine, x, y);
	fclose(file); free(fullpath);
	return(form);

}  /* end xvf_create_form */



/************************************************************
*
*  Routine Name:  xvf_build_form
*
*     Purpose: This is the main driver for the routines that create
*		the form, both physically (the graphical user interface
*	        made up of widgets) and internally (the abstract data structure
*		referred to as a form tree).  
*
*        Input: 1) database:     database or user interface description
*		2) line_num:     num of lines for the database
*		3) db_size:      allocated size of the database (>= num)
*		4) argv & argc:  program arguments
*		5) glyph_type:   type of glyph associated with this form
*		6) callback_routine: optional callback routine for this form 
*	        7) x, y:	 location to place the newly created form. If
*				 (-1,-1), let user do manual placement.
*
*       Output: returns a pointer to the xvf_form structure (see forms.h)
*
*   Written By: Danielle Argiro and Stephanie Hallett
*
*     Comments: This is the 'driver' for the routines that create
*		the form.  At this top level, only four types of lines
*		from the database should be encountered; these types of 
*		lines are:  
*
*		(-F)  Start Form :   first line of data base, 
*			    	     indicates that start of form
*
*		(-S)  Start Master:  indicates that we will be having a "master"
*				     form, with buttons on it to bring up
*				     subforms, (the master can also have "master
*				     action" buttons, Help, and Quit).
*				     
*		(-M)  Start Subform: indicates the beginning of a subform
*				     definition:  with at least one pane,
*				     and optionally with a Guide Pane with
*				     guide buttons that will bring up the
*				     appropriate pane.
*
*		(-E)  End:  	     flags the end of the entire form definition
*		
*         Date: 5/25/89
*
*
*************************************************************/

extern int last_subform_index;

xvf_form *xvf_build_form(database, line_num, db_size, argv, argc, glyph_type,
			 callback_routine, x, y)

char 		**database;	/* database or user interface description */
int		line_num;	/* number of lines for the database	*/
int		db_size;	/* allocated size of the database	*/
char 		**argv;		/* program arguments			*/
unsigned int  	argc;		/* number of program arguments 		*/
int		glyph_type;	/* simple or in_out glyph 		*/
void		(* callback_routine)();	/* callback for form if desired */
int		x, y;
{
	xvf_form 	*form;
	xvf_sub_form    *subform;
	int 	        i, done, flag, balance; 
	Line_Info 	line_info;
	int		subform_num = 0, subform_button_num = 0, 
		        master_button_num = 0, xvf_index = 0; 
	Arg		args[MaxArgs];
	char		geometry[MaxLength], name[MaxLength];
static  int count = 0;


	done = false;
	xvf_x = x;  xvf_y = y;
	last_subform_index = 0;

	xvf_clear_line_info(&line_info);

	if (database == NULL)
	{
	   fprintf(stderr, "xvf_build_form:\n");
	   fprintf(stderr, "   ERROR: Apparently empty UIS found.\n");
	   fprintf(stderr, "          Unable to create forms.\n");
	   return(NULL);
	}

	/* allocate room for the form structure & return on failure */
	if (!(form = (xvf_form *) calloc(1,sizeof (xvf_form)))) 
	{
	    fprintf(stderr, "xvf_build_form: \n");
	    fprintf(stderr, "   ERROR: Could not allocate room\n");
	    fprintf(stderr, "          for internal form structure\n");	
	    fprintf(stderr, "          Unable to create forms.\n");
	    return(NULL);
    	}

	/* set miscellaneous form pointer fields */
	form->db = database;  	    /* save pointer to database */
	form->line_num = line_num;  /* number of lines in the database */
	form->db_size  = db_size;   /* allocated size of the database */
	form->form_sel= 0;          /* form has not set FORM_DONE yet */
	form->count = 0; 	    /* form is being created so count = 0 */
	form->quit  = false;	     


	/**** start with (-F) flag: create form pointer & set fields  ****/

        flag = xvf_get_line_type(database[xvf_index]);
	if (flag != StartForm)
	{
	    fprintf(stderr, "xvf_build_form:\n");
	    fprintf(stderr, "   ERROR: UIS form definition must begin with [-F]\n");
	    fprintf(stderr, "          Unable to create forms.\n");
            return(NULL);
	}

	/* parse the Start Form line */
        if (!(xvf_parse_startform_line(database[xvf_index],&line_info)))
		return(NULL);
	form->form_name = xvf_strcpy(line_info.variable);

	/* note kludge to number cantata widgets */
	if (client_cantata)
            sprintf(name,"%s_form_%d", line_info.variable, count++);
	else	
            sprintf(name,"%s_form", line_info.variable);

	form->toplevel_name = xvf_strcpy(name);

	i = 0;
	XtSetArg(args[i], XtNscreen, xvf_screen); 	  i++;
	XtSetArg(args[i], XtNargc, xvf_ac); 	          i++;
	XtSetArg(args[i], XtNargv, xvf_av);               i++; 
	XtSetArg(args[i], XtNinput, true);                i++; 
	XtSetArg(args[i], XtNcursor, xvf_cursor);         i++; 
	XtSetArg(args[i], XtNtitle, line_info.variable);  i++; 
	XtSetArg(args[i], XtNx, 0); 		          i++;
	XtSetArg(args[i], XtNy, 0);	 	          i++;
	XtSetArg(args[i], XtNallowShellResize, True);	  i++;
	XtSetArg(args[i], XtNwinGravity, StaticGravity);  i++; 
	if (x != -1 && y != -1)
	{
	   (void) sprintf(geometry,"+%d+%d", x, y);
	   XtSetArg(args[i], XtNgeometry, geometry);	  i++; 
	}
	if (xvf_visual != NULL)
	{
	   XtSetArg(args[i], XtNvisual, xvf_visual);		      i++; 
	}
	if (xvf_colormap != NULL)
	{
	   XtSetArg(args[i], XtNcolormap, xvf_colormap);	i++; 
	}
	form->toplevel = XtAppCreateShell(name, xvf_cap_first_letter(name), 
			  applicationShellWidgetClass, xvf_display, args, i);   

	/* create the backplane of the form */
        form->back = xvf_create_backplane(&(form->label),
				&line_info, form->toplevel,
				&(form->back_name),&(form->label_name), true);

	/* check if form back successfully created */
        if (form->back == NULL) 
	{
            fprintf(stderr, "xvf_build_form:\n");
            fprintf(stderr, "   ERROR: Could not create form backplane\n");
            fprintf(stderr, "          Aborting form creation\n");
            return(NULL);
        }

	/* set up glyphs for form */
	form->glyph_type = glyph_type;
	if (glyph_type != NONE)
	{
	   /* create the glyph button and glyph for the form */
 	   form->glyph_wid = xvf_form_create_glyph_sel(form);
	   if (form->glyph_wid == NULL)
	      form->glyph_info = NULL;
	   else
	      form->glyph_info = xvf_create_form_glyph(form, argv, argc,
						       glyph_type);
	}
	else
	{
	   form->glyph_wid = NULL;
	   form->glyph_info = NULL;
	   form->glyph_toplevel = NULL;
	}
	xvf_add_entry(form, callback_routine, NULL);


	/* set remaining formptr fields except subform struct */
        form->index = xvf_index;
        xvf_index++;
        flag = xvf_get_line_type(database[xvf_index]);

	/*
	 *  Check to see if this is an empty form.  If so then we are done,
	 *  since there is nothing left to fill in or check.
	 */
	if (flag == End)
	   return(form);


	/**** next is the (-S) flag (if there is a master) or (-M) flag ****/

	if ((flag != StartMaster) && (flag != StartSubForm))
	{
	    fprintf(stderr, "xvf_build_form:\n");
	    fprintf(stderr, "   ERROR:  StartForm line [-F] in UIS must be \n");
	    fprintf(stderr, "           followed by either a [-S] UIS line \n");
	    fprintf(stderr, "           indicating the start of a master \n");
	    fprintf(stderr, "           form definition, or by a [-M] UIS\n");
	    fprintf(stderr, "           line indicating the start of a \n"); 
	    fprintf(stderr, "           single subform definition.\n");
            return(NULL);
	}


	/**** (-S) flag: they have defined a Master Form *****/

	if (flag == StartMaster)
	{
	     /* parse the Start Master line */
	     if (!(xvf_parse_startmaster_line(database[xvf_index], &line_info)))
		  return(NULL);

	     form->mut_excl = line_info.logical_val;

	     xvf_index++;

	     /* fill in the master form w/ form buttons, etc */
	     if (!(xvf_fill_in_master(database, form, argv, argc, 
				      form->back, &xvf_index,  
				      &subform_button_num, &master_button_num)))
                    return(NULL);
             xvf_realize_widget(form->toplevel);

	}
	else
	{
	     XtDestroyWidget(form->toplevel);
	     form->toplevel = NULL;
	     form->label = NULL;
	     form->back = NULL;
        }


	/*****  now a series of (-M) subform definitions should follow *****/

	subform = form->subform;
	while (!done)
	{
             flag = xvf_get_line_type(database[xvf_index]);
	
	     if (flag == StartSubForm)
	     {
		/* 
		 * if there is no StartMaster line, the form->subform struct
		 * will not have been allocated in xvf_fill_in_master.
		 * There will be only a single subform on the form--
		 * Create an "empty subform" for the sake of bookkeeping
		 */
		if (form->subform == NULL)
		{
		   /* allocate room for the subform structure */
		   if (!(form->subform = (xvf_sub_form *) 
		           calloc(1,sizeof (xvf_sub_form)))) 
		   {
	    	      fprintf(stderr, "xvf_build_form: \n");
	    	      fprintf(stderr, "   ERROR: Could not allocate room\n");
		      fprintf(stderr, "          for internal subform structure\n");	
                      fprintf(stderr, "          Aborting form creation\n");
	    	      return(NULL);
		   }
		   form->subform->button = NULL;
		   form->subform->quit = false;
		   form->subform->button_index = -1;
		   form->subform->type = SubFormButton;
		   form->subform->next_subform = NULL;
		   form->subform->db = form->db;
		   form->subform->selected = true;
		   subform = form->subform;
		}

		/*
		 *  search thru subform list looking form a "true" subform
		 *  that has not had it's toplevel widget allocated yet
		 *  (ie, the sub form has not yet been created)
		 */
		subform_num++;
		while (subform != NULL)
		{
		   if (subform->type == SubFormButton ||
		       subform->type == PsuedoSubForm)
		      break;
		   else
		      subform = subform->next_subform;
		}

		if (subform == NULL) 
                {
                   fprintf(stderr, "xvf_build_form: \n");
                   fprintf(stderr, "   ERROR: Number of SubForm definitions");
                   fprintf(stderr, "          exceeds the number of subform buttons\n");
                   fprintf(stderr, "          Aborting form creation\n");
                   return(NULL);
                }


		if (subform->type == PsuedoSubForm)
		{
		   xvf_parse_startsubform_line(database[xvf_index], &line_info);
		   subform->subform_name = xvf_strcpy(line_info.variable);
		   subform->index = xvf_index;
		   balance = 1;
		   while (balance != 0)
       		   {
           	      flag  = xvf_get_line_type(database[xvf_index++]);
           	      switch (flag)
           	      {
                	 case StartPane:        balance++; break;
                	 case StartGuide:       balance++; break;
                	 case Toggle:           balance++; break;
                	 case MutExcl:          balance++; break;

                	 case End:              balance--; break;
           	      }
        	   }
		}
		else
		{
		   /* still need to parse the StartSubForm (-M) line:
	              don't increment xvf_index before creating subform */
		   if (!(xvf_fill_in_subform(database, form, subform, argv,argc,
					   &xvf_index)))
		        return(NULL);

		}
		subform = subform->next_subform;
		 
	     }  /* end if */
	
	     /*** flag (-E)  should be the end of the form definiton ***/

	     else if (flag == End)  
	     {
		/* error check: if # SubForms = # "true" subform buttons */
                if ((subform_button_num != 0) && 
		    (subform_num != subform_button_num))
                {
                    fprintf(stderr, "xvf_build_form:\n");
                    fprintf(stderr, "   WARNING: UIS file specified has\n");
                    fprintf(stderr, "            %d subforms definitions ");
		    fprintf(stderr, "[-M -- -E] sets,\n", subform_num);
		    fprintf(stderr, "            but %d subform buttons ");
		    fprintf(stderr, "(-d lines).\n", subform_button_num); 
                }
                done = true;
		
	     }  /* end else */

	     /* database line out of place */
	     else 
	     {
	        fprintf(stderr, "xvf_build_form:\n");
		fprintf(stderr, "   ERROR: UIS line out of place:\n");
		fprintf(stderr, " '%s'\n", database[xvf_index]);
		return(NULL);
	     }
	}  /* end while */

	form->subform_num = subform_num;
	subform = form->subform;
	while(subform != NULL)
	{
	   if ((subform->selected == TRUE) && (subform->type == SubFormButton)
		&& (subform->button != NULL))
		  xvf_reverse_colors(subform->button);

	   subform = subform->next_subform;
	}
	return(form);

}  /* end xvf_create_form */




/*****************************************************************************
*
*  Routine Name:  xvf_fill_in_master
*
*      Purpose:  Controlling routine that fills in the master form with 
*		 subform buttons, master action buttons, help, quit, workspace
*		 widgets, etc.  Simultaneously, creates the list of subforms
*		 whose header is form->subform.
*
*        Input: database    - pointer to xvform description
*		form	    - pointer to the form tree
*		argv	    - command line arguments
*		argc	    - number of command line arguments
*               parent      - the parent widget (backplane of the master)
*		xvf_index   - xvf_index into the database of current line
*
*       Output: true on success, false on failure
*		subform_button_num - number of buttons specified on the master
*				     that will bring up sub-forms
*		master_button_num  - total number of buttons specified on the 
*				     master form
*    Called By: xvf_create_form()
*
*   Written By: Danielle Argiro and Stephanie Hallett
*		
*****************************************************************************/


int 
xvf_fill_in_master(database, form, argv, argc, parent, xvf_index, 
		    subform_button_num, master_button_num)

char        *database[];
xvf_form    *form;
char 	   **argv;		
unsigned int argc;	
Widget      parent;
int         *xvf_index;
int	    *subform_button_num;
int	    *master_button_num;

{
	Line_Info    line_info;
	Widget	     submenu_parent;
	xvf_sub_form *current, *last;
	int	     done, flag, submenu; 
	int	     quit_num = 0, help_num = 0;
	int	     blank_num=0;

	/* initialization */
	done = submenu = false;
             
	*subform_button_num = 0;
	xvf_clear_line_info(&line_info);

	while (!done) 
	{
	    /* 
	     *	see what type of line we have
 	     */
	    flag = xvf_get_line_type(database[*xvf_index]);
	    
	    switch (flag)
	    {
		case StartSubMenu:

		     /*
		      *  (-D)  indicates a submenu button on the master 
		      */
		     submenu_parent = xvf_create_master_submenu(form, database,
					xvf_index, parent);
		     submenu = True;
		     (*xvf_index)++;
		     break;

		case SubFormButton:

		     /*
		      *  (-d)  indicates a subform button on the master 
		      */

		     /* allocate room for the subform structure */
		     if (!(current = (xvf_sub_form *) 
				             calloc(1,sizeof (xvf_sub_form)))) 
		     {
	    	         fprintf(stderr, "xvf_fill_in_master: \n");
	    	         fprintf(stderr, "   ERROR: Could not allocate room\n");
			 fprintf(stderr, "          for internal subform structure\n");	
                         fprintf(stderr, "          Aborting form creation\n");
	    	         return(NULL);
	    	     }

		     /* set fields of subform that can be set now */
		     current->db = form->db;
		     current->button_index = *xvf_index; 	    
		     current->count = 0; 	    
		     current->quit = false; 	    
		     current->subform_sel = 0; 	    
                     current->guide_button = NULL; 
		     current->type = SubFormButton;
		     current->next_subform = NULL;
		     current->submenu = submenu;

		     /* parse the line */
		     if (!(xvf_parse_subformbutton_line(database[*xvf_index], 
			   		  &line_info))) return(NULL);

		      current->selected = line_info.selected;

		      if (submenu)
		         current->button = xvf_create_subform_sel(form, current,
				 	database, xvf_index, submenu_parent,
					&(current->button_name), True);
		      else
		         current->button = xvf_create_subform_sel(form, current,
				 	database, xvf_index, parent,
					&(current->button_name), False);

		      /* link into the list of master buttons */
		      if (form->subform == NULL)
		      {
			 form->subform = current;
			 last = current;
		      }
		      else
		      {
			 last->next_subform = current;
			 last = current;
		      }
		      (*subform_button_num)++; 
		      (*master_button_num)++;
		      (*xvf_index)++;
		      break; 

		case PsuedoSubForm:
		     
                     /*
                      *  (-u)  indicates a psuedo subform button on the master
                      */
		      
		     /* allocate room for the subform structure */
		     if (!(current = (xvf_sub_form *) 
				             calloc(1,sizeof (xvf_sub_form)))) 
		     {
	    	         fprintf(stderr, "xvf_fill_in_master: \n");
	    	         fprintf(stderr, "   ERROR: Could not allocate room\n");
			 fprintf(stderr, "          for internal subform structure\n");	
                         fprintf(stderr, "          Aborting form creation\n");
	    	         return(NULL);
	    	     }

		     /* set fields of subform that can be set now */
		     current->db = form->db;
		     current->button_index = *xvf_index; 	    
		     current->count = 0; 	    
		     current->quit = false; 	    
		     current->subform_sel = 0; 	    
                     current->guide_button = NULL; 
		     current->type = PsuedoSubForm;
		     current->next_subform = NULL;
		     current->submenu = submenu;

		     /* parse the line */
		     if (!(xvf_parse_psuedosubform_line(database[*xvf_index], 
			   		  &line_info))) return(NULL);
		      current->selected = line_info.selected;

		      if (submenu)
		         current->button = xvf_create_psuedosubform_sel(form, 
					current, database, xvf_index, 
					submenu_parent,
					&(current->button_name), True);
		      else
		         current->button = xvf_create_psuedosubform_sel(form, 
					current, database, xvf_index, parent,
					&(current->button_name), False);

		      /* link into the list of master buttons */
		      if (form->subform == NULL)
		      {
			 form->subform = current;
			 last = current;
		      }
		      else
		      {
			 last->next_subform = current;
			 last = current;
		      }
		      (*subform_button_num)++; 
		      (*master_button_num)++;
		      (*xvf_index)++;
		      break; 


		 case MasterAction:

		      /*
		       *  (-n)  Master Action  button on master form
		       */

		      /* Allocate room for the subform structure */
		      if (!(current = (xvf_sub_form *)
					 calloc(1,sizeof (xvf_sub_form))))
		      {
			 fprintf(stderr, "xvf_fill_in_master: \n");
	    	         fprintf(stderr, "   ERROR: Could not allocate room\n");
			 fprintf(stderr, "          for internal subform structure\n");	
                         fprintf(stderr, "          Aborting form creation\n");
			 return(NULL);
		      }

		      /* create the button widget */
		      if (submenu)
		         current->button = xvf_create_master_action_sel(form,
					current, database, xvf_index,
					submenu_parent, &(current->button_name),
					True);
		      else
		         current->button = xvf_create_master_action_sel(form,
					current, database, xvf_index,
					parent, &(current->button_name),
					False);

		      /* error check */
		      if (current->button == NULL) 
		      {
			 fprintf(stderr,"xvf_fill_in_master:\n");
			 fprintf(stderr,"   ERROR: Couldn`t create quit ");
			 fprintf(stderr,"button widget\n");
			 fprintf(stderr,"          Aborting form creation\n");
			 return(false);
		      }

		      xvf_clear_line_info(&line_info);
		      if (!(xvf_parse_master_action_line (database[*xvf_index],
						&line_info))) return(NULL);
			 
		      /* fill in button struct type, line, & next */
		      current->db = form->db;
		      current->type = MasterAction;
		      current->button_index = *xvf_index;
		      current->index = -1;
		      current->quit = false;
		      current->selected = line_info.selected; 
		      current->guide_button = NULL; 
		      current->next_subform = NULL;
		      current->submenu = submenu;

		      /* link into the list of master buttons */
		      if (form->subform == NULL)
		      {
		         form->subform = current;
		         last = current;
		      }
		      else
		      {
		         last->next_subform = current;
		         last = current;
		      }
		      (*xvf_index)++; 
		      (*master_button_num)++;
		      break;

	        case QuitForm:

		     /*
		      *  (-Q)  quit the master form
		      */

		     /* Allocate room for the subform structure */
		     if (!(current = (xvf_sub_form *) 
					calloc(1,sizeof (xvf_sub_form)))) 
		     {
			fprintf(stderr, "\nxvf_fill_in_master: \n");
	    	         fprintf(stderr, "   ERROR: Could not allocate room\n");
			 fprintf(stderr, "          for internal subform structure\n");	
                         fprintf(stderr, "          Aborting form creation\n");
			return(NULL);
		     }

		     current->button = xvf_create_quit_master_sel(form, current,
					 database, xvf_index, parent, quit_num,
					 &(current->button_name));

		     /* error check */
		     if (current->button == NULL) 
		     {
			fprintf(stderr,"xvf_fill_in_master:\n");
			fprintf(stderr,"   ERROR: Couldn't create quit");
			fprintf(stderr," button widget\n");
			fprintf(stderr,"          Aborting form creation\n");
			return(false);
		     }
		     quit_num++;

		     /* fill in button struct type, line, & next */
		     current->db = form->db;
		     current->type = QuitForm;
		     current->button_index = *xvf_index;
		     current->index = -1;
		     current->quit = false;
		     current->next_subform = NULL;
		     current->selected = false; 
		     current->guide_button = NULL; 

		     /* link into the list of master buttons */
		     if (form->subform == NULL)
		     {
		        form->subform = current;
		        last = current;
		     }
		     else
		     {
		        last->next_subform = current;
		        last = current;
		     }
		     (*xvf_index)++; 
		     (*master_button_num)++;
		     break; 

		case HelpSel:

		     /*
		      * (-H) Help selection for access to on-line help
		      */

		     /* Allocate room for the subform structure */
		     if (!(current = (xvf_sub_form *) 
					 calloc(1,sizeof (xvf_sub_form)))) 
		     {
			fprintf(stderr, "\nxvf_fill_in_master: \n");
	    	        fprintf(stderr, "   ERROR: Could not allocate room\n");
			fprintf(stderr, "          for internal subform structure\n");	
                        fprintf(stderr, "          Aborting form creation\n");
			return(NULL);
		     }

		     if (submenu)
		        current->button = xvf_create_help_sel(form, current,
				NULL, NULL, database, xvf_index, submenu_parent,
				help_num, &(current->button_name),
				1, True);
		     else
		        current->button = xvf_create_help_sel(form, current,
				NULL, NULL, database, xvf_index, parent,
				help_num, &(current->button_name),
				1, False);

		     /* error check */
		     if (current->button == NULL) 
		     {
			fprintf(stderr, "xvf_fill_in_master:\n");
			fprintf(stderr, "   ERROR: Couldn't create help button\n");
			fprintf(stderr, "          Aborting form creation\n");
			return(false);
		     }
		     help_num++;

		     current->db = form->db;
		     current->type = HelpSel;
		     current->button_index = *xvf_index;
		     current->index = -1;
		     current->next_subform = NULL;
		     current->selected = false;
		     current->quit = false;
		     current->guide_button = NULL;
		     current->submenu = submenu;

		     /* link into the list of master buttons */
		     if (form->subform == NULL)
		     {
			form->subform = current;
			last = current;
		     }
		     else
		     {
			last->next_subform = current;
			last = current;
		     }
		     (*xvf_index)++;
		     (*master_button_num)++;
		     break;

		case WorkWidget:

		     /*
		      * (-w) WorkWidget selection for use by application
		      */

		     /* Allocate room for the subform structure */
		     if (!(current = (xvf_sub_form *) 
					 calloc(1,sizeof (xvf_sub_form)))) 
		     {
			fprintf(stderr, "\nxvf_fill_in_master: \n");
	    	        fprintf(stderr, "   ERROR: Could not allocate room\n");
			fprintf(stderr, "          for internal subform structure\n");	
                        fprintf(stderr, "          Aborting form creation\n");
			return(NULL);
		     }

		     if (submenu)
		        current->button = 
			  xvf_create_workspace_sel(database, xvf_index, 
						   current, NULL, NULL,
						   submenu_parent);
		     else
		        current->button = 
		 	   xvf_create_workspace_sel(database, xvf_index, 
						    current, NULL, NULL,
						    parent);

		     /* error check */
		     if (current->button == NULL) 
		     {
			fprintf(stderr,"xvf_fill_in_master:\n");
			fprintf(stderr,"   ERROR: Couldn't create workspace\n");
			fprintf(stderr,"          Aborting form creation\n");
			return(false);
		     }

		     current->db = form->db;
		     current->type = WorkWidget;
		     current->button_index = *xvf_index;
		     current->index = -1;
		     current->next_subform = NULL;
		     current->selected = false;
		     current->guide_button = NULL;
		     current->submenu = submenu;

		     /* link into the list of master buttons */
		     if (form->subform == NULL)
		     {
			form->subform = current;
			last = current;
		     }
		     else
		     {
			last->next_subform = current;
			last = current;
		     }
		     (*xvf_index)++;
		     (*master_button_num)++;
		     break;

		case Blank:
		     /*
		      * a Blank (or Label) selection to provide a space
		      * or a label in the form.
		      */

		     /* Allocate room for the subform structure */
		     if (!(current = (xvf_sub_form *) 
					 calloc(1,sizeof (xvf_sub_form)))) 
		     {
			fprintf(stderr, "\nxvf_fill_in_master: \n");
	    	        fprintf(stderr, "   ERROR: Could not allocate room\n");
			fprintf(stderr, "          for internal subform structure\n");	
                        fprintf(stderr, "          Aborting form creation\n");
			return(NULL);
		     }

			/* not linking in the blank line */
		     if (submenu)
		        current->button = xvf_create_blank_sel(database, xvf_index,
			     submenu_parent,blank_num, &(current->button_name), 1);
		     else
		        current->button = xvf_create_blank_sel(database, xvf_index,
			     parent,blank_num, &(current->button_name), 2);

		     current->db = form->db;
                     current->type = Blank;
                     current->button_index = *xvf_index;
                     current->index = -1;
                     current->next_subform = NULL;
                     current->selected = false;
                     current->quit = false;
                     current->guide_button = NULL;
                     current->submenu = submenu;

		     /* link into the list of master buttons */
		     if (form->subform == NULL)
		     {
			form->subform = current;
			last = current;
		     }
		     else
		     {
			last->next_subform = current;
			last = current;
		     }
		     blank_num++;
		     (*xvf_index)++;
		     break;


		case End:

		     /*
		      * (-E) At the end of this master form description
		      */ 
		    if (submenu == True)
		       submenu = False;
		    else
		       done = true;

		    (*xvf_index)++;
		    break;

                default:
		    fprintf(stderr, "xvf_fill_in_master:\n");
		    fprintf(stderr, "   ERROR: UIS line out of place:\n");
		    fprintf(stderr, "'%s'\n",database[*xvf_index]);
		    (*xvf_index)++;
		    break;
	    }

	} /* end while */
	return(true);

} /* end xvf_fill_in_master() */

    

/************************************************************
*
*  Routine Name: xvf_fill_in_subform()
*
*      Purpose: Fills in the xvf_subform structure
*
*        Input: database - pointer to xvform description
*		form     - pointer to the form tree
*		subform  - pointer to this subform branch
*		argc	 - number of command line arguments
*		xvf_index- index to current line of the database
*
*       Output: true on success, false on failure
*
*   Written By: Danielle Argiro and Stephanie Hallett
*
*    Called By: xvf_create_form()
*
*     Comments: This is the controlling routine that fills in the empty 
*		subform backplane with widgets that make up the guide pane
*		and the different panes of the subform. Simultaneously, the
*		subform branch of form tree that represents this subform is
*		created.  Possible lines that are encountered here include:
*	
*		    1) StartSubForm: start of this subform
*		    2) StartGuide:   start of a guide pane section of the form
*		    3) StartPane:    start of a pane on the subform
*		    4) End:          flags end of the pane, guide, or subform
*
*************************************************************/

int xvf_fill_in_subform(database, form, subform, argv, argc, xvf_index)

char		**database;
xvf_form	*form;
xvf_sub_form    *subform;
char 		**argv;
unsigned int  	argc;
int		*xvf_index;	
{
	int 	         i, done, flag, pane_count = 0; 
	int              xvf_guide_num=0, xvf_button_num=0; 
	Line_Info 	 line_info;
	xvf_pane 	 *pane;
	xvf_guide_button *guide;
	char 		 dummy_name[512];

	done = false;

	xvf_clear_line_info(&line_info);

	/**** make sure we're starting with a (-M) StartSubForm line *****/

	flag = xvf_get_line_type(database[*xvf_index]);
	if (flag != StartSubForm)
	{
	    fprintf(stderr, "xvf_fill_in_subform:\n");
	    fprintf(stderr, "   ERROR: UIS subform definition must\n");
	    fprintf(stderr, "          begin with [-M]\n");
            fprintf(stderr, "          Aborting form creation\n");
	    return(false);
	}

	/* parse the StartSubForm line */
	if (!(xvf_parse_startsubform_line(database[*xvf_index], &line_info))) 
	      return(false);

	/* set the subforms's database to be the same as the form's */
	subform->db = form->db;
	subform->subform_name = xvf_strcpy(line_info.variable);
	subform->index = *xvf_index;
	(*xvf_index)++;


	/**** next is the (-G) flag (if a guide pane) or (-P) flag ***/

	flag = xvf_get_line_type(database[*xvf_index]);

	if ((flag != StartGuide) && (flag != StartPane))
	{
	     fprintf(stderr, "xvf_fill_in_subform:\n");
	     fprintf(stderr, "   ERROR: StartSubForm line [-M] in UIS must\n");
             fprintf(stderr, "           be followed by either a [-G] line \n");
             fprintf(stderr, "           indicating the start of a guide\n");
             fprintf(stderr, "           pane definition, or by a [-P] line\n");
             fprintf(stderr, "           indicating the start of a single\n");
             fprintf(stderr, "           pane definition.\n");
	     return(false);
	}

	/**** (-G) flag: they have defined a Guide Pane on the Subform *****/

	if (flag == StartGuide)
	{
	    /* parse the StartGuide Line (-G) line */
	    if (!(xvf_parse_startguide_line(database[*xvf_index], &line_info))) 
		    return(false);

 	    /* create the backplane of the guide pane */
	    subform->guide_index = *xvf_index;
	    (*xvf_index)++;

	    if (!(xvf_fill_in_guide(database, form, subform, xvf_index, 
				    &xvf_guide_num, &xvf_button_num))) 
	        return(false);

	}

	/*****  now a series of (-P) pane definitions should follow *****/

	while (!done) 
	{

	   flag = xvf_get_line_type(database[*xvf_index]);

	   if (flag == StartPane)
	   {
		   /* 
		    *	if there is no StartGuide line, this implies that
		    *	there will be only a single pane on the form.
		    *	Create an "empty guidebutton" for the sake of 
		    *	bookkeeping 
		    */

		   if (subform->guide_button == NULL) 
		   {
			subform->guide_back = NULL;
			if (!(subform->guide_button = (xvf_guide_button *)
						calloc(1,sizeof(xvf_guide_button))))
			{
			    fprintf(stderr, "xvf_fill_in_subform: \n");
	    	            fprintf(stderr, "   ERROR: Could not allocate room\n");
			    fprintf(stderr, "          for internal guide structure\n");	
                            fprintf(stderr, "          Aborting form creation\n");
			}
			subform->guide_button->button = NULL;
			subform->guide_button->type   = GuideButton;
			subform->guide_button->selected = true;
			subform->guide_button->index = -1;
			subform->guide_button->guide_num = 1;
			subform->guide_button->pane = NULL;
			subform->guide_button->next_button = NULL;

	               /* parse the StartPane Line (-P) line */
	                xvf_parse_startpane_line(database[*xvf_index], 
					&line_info);
			line_info.selected = true;
		        xvf_deparse_startpane_line(&line_info, database,
						   *xvf_index);

   			sprintf(dummy_name,"%s_guide_button", 
					line_info.variable);
   			subform->guide_button->button_name = 
					xvf_strcpy(dummy_name);
		   }

		  /* 
		   *  search thru guide looking for a "true" guide button
		   *  that has not had it's pane structure allocated yet - 
		   *  doing this in order of how it appears in database 
		   */

		   guide = subform->guide_button;
		   while ((!((guide->type == GuideButton) && 
			   (guide->pane == NULL))) && 
			   (guide->next_button != NULL)) 
			    guide = guide->next_button;

		    if ((guide->pane != NULL) || 
			(guide->type != GuideButton))
		    { 
			fprintf(stderr, "xvf_fill_in_subform: \n");
			fprintf(stderr, "   ERROR: Number of Pane definitions ");
			fprintf(stderr, "          exceeds number of guide buttons\n");
			fprintf(stderr, "          Aborting form creation\n");
			return(false);
		    }

		    /* Allocate room for the guide_button structure */
		    if (!(guide->pane = (xvf_pane *)calloc(1,sizeof(xvf_pane))))
		    {
			fprintf(stderr, "xvf_fill_in_subform: \n");
	    	        fprintf(stderr, "   ERROR: Could not allocate room\n");
			fprintf(stderr, "          for internal pane structure\n");	
                        fprintf(stderr, "          Aborting form creation\n");
			return(false);
		    }

	            xvf_parse_startpane_line(database[*xvf_index], &line_info);
   		    sprintf(dummy_name,"%s_guide_button", line_info.variable);
   		    guide->button_name = xvf_strcpy(dummy_name);

		    pane = guide->pane;
		    pane->guide_num = guide->guide_num; 
		    pane->index	= *xvf_index;
		    pane->count	= 0;

		    /* mark the guide button on the pane */
		    pane->guide = guide->button;
		    pane->sel_list = NULL;
		    (*xvf_index)++; pane_count++;

		    /* initialize array for mutual exclusion lists */
		    for(i= 0; i < 20; i++)
		        pane->mut_exclusion[i] = NULL;

		    if (!(xvf_fill_in_pane(database, form, subform, pane, 
					   guide, xvf_index)))
			  return(false);


	   }  /* end if */


	   /*** flag (-E)  should be the end of the pane definiton ***/

	   else if (flag == End)
	   {
	    
	        /* error check: if # panes = # "true" guide buttons */
	   	if ((xvf_guide_num != 0) && (pane_count != xvf_guide_num))
		{
		    fprintf(stderr, "xvf_fill_in_subform:\n");
		    fprintf(stderr, "   WARNING: UIS file specified has\n");
		    fprintf(stderr, "            %d guide buttons, but %d panes.\n",
				    xvf_guide_num, pane_count);
		 }
		 done = true;
		 (*xvf_index)++;

	   }  /* end else */ 

	   /* database line out of place */
	   else
	   {
	      fprintf(stderr, "xvf_fill_in_subform:\n");
	      fprintf(stderr, "   ERROR: UIS line out of place:\n");
	      fprintf(stderr, "'%s'\n", database[*xvf_index]);
	      return(false);
	   }

	} /* end while */

    	return(true);

} /* end xvf_fill_in_subform() */

    



/************************************************************
*
*  Routine Name:  xvf_fill_in_guide
*
*      Purpose:  fills in the guiding pane of the form with selections
*
*        Input: database      - pointer to xvform description
*		form          - pointer to the form tree
*		subform       - pointer to this subform branch
*               parent        - the parent widget
*		xvf_index     - xvf_index into the database of current line
*
*       Output: true on success, false on failure
*		xvf_guide_num - returns number of guide buttons specified
*				in database with "-g" flags
*		xvf_button_num - returns total number of buttons on guide pane
*
*    Called By: xvf_fill_in_subform
*
*   Written By: Danielle Argiro and Stephanie Hallett
*
*     Comments: This is the controlling routine that fills in the empty 
*		guide-pane backplane with widgets that allow the user to
*		control the guiding pane of the form. Possible lines from
*		the database could indicate the need for a guide button,
*		an subform action button, a help page, a label, or a "quit" 
*		button.
*
*		
*************************************************************/


int 
xvf_fill_in_guide(database, form, subform, xvf_index, 
		  xvf_guide_num, xvf_button_num)
char         *database[];
xvf_form     *form;
xvf_sub_form *subform;
int          *xvf_index;
int	     *xvf_guide_num;
int	     *xvf_button_num;

{
	int done, flag;
	Line_Info line_info;
	xvf_guide_button *current, *last;

	done = false;
	xvf_clear_line_info(&line_info);

	/* 
	 * current is our most current guide button structure.
	 */

	while (!done) 
	{
	    /* 
	     *	see what type of line we have
	     */
	     flag = xvf_get_line_type(database[*xvf_index]);
		
	     switch (flag) {

		    /* 
		     * depending on the type of line, call the appropriate
		     * parsing routine and the appropriate "create widget selection"
		     * routine.
		     */

		    case GuideButton:
			 /* 
			  * A Guide Button allows the user to control which 
			  * pane is placed within the form
			  */

			 /* Allocate room for the guide_button structure */
			 if (!(current = (xvf_guide_button *) 
						  calloc(1,sizeof(xvf_guide_button))))
			 {
			    fprintf(stderr, "xvf_fill_in_guide: \n");
	    	            fprintf(stderr, "   ERROR: Could not allocate room\n");
			    fprintf(stderr, "          for internal guide structure\n");	
                            fprintf(stderr, "          Aborting form creation\n");
			    return(false);
			 }

			 xvf_clear_line_info(&line_info);
			 if (!(xvf_parse_guide_line(database[*xvf_index],
			      &line_info))) return(NULL);

			 current->type = GuideButton;
			 current->index = *xvf_index;
			 current->guide_num = *xvf_button_num; /* starts at 0 */
			 current->next_button = NULL;
			 current->selected = line_info.selected;
			 
			 /* the pane for this guide button has not been
			    created yet */
			 current->pane = NULL;
			 if (subform->guide_button == NULL) 
			 { 
			    subform->guide_button = current;
			    last = current;
			 }
			 else
			 {
			     last->next_button = current;
			     last = current;
			 }
			 (*xvf_guide_num)++; (*xvf_button_num)++; (*xvf_index)++;
			 
			 break;

		    case QuitForm:

			 /* 
			  * a Quit Form button allows the user to exit from the
			  * form: always a popular option
			  */

			 /* Allocate room for the guide_button structure */
			 if (!(current = (xvf_guide_button *) 
						  calloc(1,sizeof(xvf_guide_button))))
			 {
			    fprintf(stderr, "xvf_fill_in_guide: \n");
	    	            fprintf(stderr, "   ERROR: Could not allocate room\n");
			    fprintf(stderr, "          for internal guide structure\n");	
                            fprintf(stderr, "          Aborting form creation\n");
			    return(false);
			 }
			 current->type = QuitForm;
			 current->index = *xvf_index;
			 current->guide_num = *xvf_button_num; /* starts at 0 */
			 current->next_button = NULL;
			 current->pane = NULL; /* no pane with QUIT button */
			 current->selected = false; /* no pane with QUIT button */

			 if (subform->guide_button == NULL) 
			 { 
			    subform->guide_button = current;
			    last = current;
			 }
			 else
			 {
			     last->next_button = current;
			     last = current;
			 }
			 (*xvf_button_num)++; (*xvf_index)++;

			 break;
		
		    case SubformAction:

			 /* 
			  * an Subform Action button provides a way to let the
			  * guide pane on a subform control a particular action;
			  */

			 /* Allocate room for the guide_button structure */
			 if (!(current = (xvf_guide_button *) 
						  calloc(1,sizeof(xvf_guide_button))))
			 {
			    fprintf(stderr, "xvf_fill_in_guide: \n");
	    	            fprintf(stderr, "   ERROR: Could not allocate room\n");
			    fprintf(stderr, "          for internal guide structure\n");	
                            fprintf(stderr, "          Aborting form creation\n");
			    return(false);
			 }

		         xvf_clear_line_info(&line_info);
		         if (!(xvf_parse_subform_action_line(database[*xvf_index],
			      &line_info))) return(NULL);

		         /* fill in guide_button struct */
		         current->type = SubformAction;
		         current->index = *xvf_index;
		         current->guide_num = *xvf_button_num; /* starts at 0 */
		         current->next_button = NULL;
		         current->pane = NULL; /* no pane with QUIT button */
               	         current->selected = line_info.selected;

		         if (subform->guide_button == NULL) 
		         {     
			    subform->guide_button = current;
			    last = current;
		         }
		         else
		         {
		             last->next_button = current;
			     last = current;
		         }
		         (*xvf_button_num)++; (*xvf_index)++;
		         break;

		case HelpSel:
		     /* 
		      * an Help selection provides a way to let the user have
		      * access to on-line help
		      */

		     /* Allocate room for the guide_button structure */
	             if (!(current = (xvf_guide_button *) 
					      calloc(1,sizeof(xvf_guide_button))))
		     {
	    	        fprintf(stderr, "xvf_fill_in_guide: \n");
	    	        fprintf(stderr, "   ERROR: Could not allocate room\n");
			fprintf(stderr, "          for internal guide structure\n");	
                        fprintf(stderr, "          Aborting form creation\n");
	                return(false);
	             }

		     /* fill in guide_button struct */
		     current->type = HelpSel;
		     current->index = *xvf_index;
		     current->guide_num = *xvf_button_num; /* starts at 0 */
		     current->next_button = NULL;
		     current->pane = NULL; /* no pane with QUIT button */
		     current->selected = false; 

		     if (subform->guide_button == NULL) 
		     { 
			subform->guide_button = current;
			last = current;
		     }
		     else
		     {
		         last->next_button = current;
			 last = current;
		     }
		     (*xvf_button_num)++; (*xvf_index)++;

		     break;

		case WorkWidget:
		     /* 
		      * an WorkWidget selection provides the application 
		      * with access to a widget to do whatever with
		      */

		     /* Allocate room for the guide_button structure */
	             if (!(current = (xvf_guide_button *) 
					      calloc(1,sizeof(xvf_guide_button))))
		     {
	    	        fprintf(stderr, "\nxvf_fill_in_guide: \n");
	    	        fprintf(stderr, "   ERROR: Could not allocate room\n");
			fprintf(stderr, "          for internal guide structure\n");	
                        fprintf(stderr, "          Aborting form creation\n");
	                return(false);
	             }

		     /* fill in guide_button struct values type, line, & next */
		     current->type = WorkWidget;
		     current->index = *xvf_index;
		     current->guide_num = *xvf_button_num; /* starts at 0 */
		     current->next_button = NULL;
		     current->pane = NULL; /* no pane with QUIT button */
		     current->selected = false; 

		     if (subform->guide_button == NULL) 
		     { 
			subform->guide_button = current;
			last = current;
		     }
		     else
		     {
		         last->next_button = current;
			 last = current;
		     }
		     (*xvf_button_num)++; (*xvf_index)++;
		     break;

		case Blank:
		     /*
		      * a Blank (or Label) selection to provide a space
		      * or a label in the form.
		      */
		     /* Allocate room for the guide_button structure */
	             if (!(current = (xvf_guide_button *) 
					      calloc(1,sizeof(xvf_guide_button))))
		     {
	    	        fprintf(stderr, "xvf_fill_in_guide: \n");
	    	        fprintf(stderr, "   ERROR: Could not allocate room\n");
			fprintf(stderr, "          for internal guide structure\n");	
                        fprintf(stderr, "          Aborting form creation\n");
	                return(false);
	             }

		     /* fill in guide_button struct */
		     current->type = Blank;
		     current->index = *xvf_index;
		     current->guide_num = *xvf_button_num; /* starts at 0 */
		     current->next_button = NULL;
		     current->pane = NULL; /* no pane with blank */
		     current->selected = false; 
		     if (subform->guide_button == NULL) 
		     { 
			subform->guide_button = current;
			last = current;
		     }
		     else
		     {
		         last->next_button = current;
			 last = current;
		     }
		     (*xvf_index)++;
		     break;

		case LibCall:
		     /* 
		      * library call definition
		      */
		     (*xvf_index)++;
		     break;

	    
		case End:
		     /* 
		      * at the end of the description of the guiding pane
		      */
		     (*xvf_index)++;
		     done = true;
		     break;

                default:
		     fprintf(stderr, "xvf_fill_in_guide:\n");
		     fprintf(stderr, "   ERROR: UIS line out of place:\n");
		     fprintf(stderr, "'%s'\n",database[*xvf_index]);
		     (*xvf_index)++;
		     break;

	    }  /* end switch  */

	} /* end while */

	return(true);

}  /* end xvf_fill_in_guide() */
	    

	
 
/************************************************************
*
*  Routine Name:  xvf_fill_in_pane
*
*      Purpose:   fills in the pane with selections
*
*
*        Input: database - pointer to xvform description
*		form     - pointer to the form tree
*		subform  - pointer to this subform branch
*		pane     - pointer to this guide_button branch
*		guide    - pointer to this guide_button branch
*		xvf_index- xvf_index into the database of current line
*
*       Output: true on success, false on failure
*
*    Called By: xvf_fill_in_subform
*
*   Written By: Danielle Argiro and Stephanie Hallett
*
*     Comments: This is the controlling routine that fills in the empty 
*		pane backplane with widgets that provide the
*		bulk of the user interface controlled by the form. 
*		Simultaneously, it creates the list of selections that drops
*		from the xvf_pane structure's selection header, sel_list.
*		Possible lines from the database (form description) could 
*		indicate the any of the following selections: pane action 
*		button, input file, output file, integer, float, logical, 
*		string, toggle, a certain routine, text window, blank line, 
*		or a help page.
*
*		
*************************************************************/

int xvf_fill_in_pane (database, form, subform, pane, guide, xvf_index)
char     	 *database[];
xvf_sub_form 	 *subform;
xvf_form	 *form;
xvf_pane 	 *pane;
xvf_guide_button *guide;
int      	 *xvf_index;
{
	int       done, flag, sels_guide_num, sel_count = 0;
	Line_Info line_info;
	xvf_selection *current, *last;
	int       mutual_exclusion, mut_excl_count;
	mut_excl_link *mut_excl_ptr, *tmp_ptr;

	done = false;
	mutual_exclusion = false;
	mut_excl_count = 0;
	sels_guide_num = pane->guide_num;
	tmp_ptr = (mut_excl_link *) malloc (sizeof(mut_excl_link));

 	xvf_clear_line_info(&line_info);

	pane->mut_exclusion[0] = (mut_excl_link *) 
				      malloc (sizeof (mut_excl_link));
	mut_excl_ptr = pane->mut_exclusion[0];

	while (!done) 
	{
	    /* 
	     *	see what type of line we have
 	     */
	    flag = xvf_get_line_type(database[*xvf_index]);

	     /* allocate selection structure */
	    if (!(current = (xvf_selection *) calloc(1,sizeof(xvf_selection))))
	    {
	    	fprintf(stderr, "xvf_fill_in_pane: \n");
	    	fprintf(stderr, "   ERROR: Could not allocate room\n");
		fprintf(stderr, "          for internal pane structure\n");	
                fprintf(stderr, "          Aborting form creation\n");
	        return(false);
	   }

	    switch (flag) {

		/* 
		 * depending on the type of line, call the appropriate
		 * parsing routine and the appropriate "create widget selection"
		 * routine.
		 */

		case InputFile:

		     /* create the selection widget */
		     if (mutual_exclusion) 
		     {
			if (!(xvf_create_mut_excl_link(database, xvf_index,
						 mut_excl_ptr))) return(false);
			tmp_ptr = mut_excl_ptr;
			mut_excl_ptr = mut_excl_ptr->next;
			current->mut_excl = true;
			current->mut_excl_id = mut_excl_count;
		     }

		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;

		     break;

		case AnswerInfile:

		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;
		     break;

		case AnswerOutfile:

		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;
		     break;


		case OutputFile:

		     /* create the selection widget */
		     if (mutual_exclusion) 
		     {
			if (!(xvf_create_mut_excl_link(database, xvf_index,
					 mut_excl_ptr))) return(false);
			tmp_ptr = mut_excl_ptr;
			mut_excl_ptr = mut_excl_ptr->next;
			current->mut_excl = true;
			current->mut_excl_id = mut_excl_count;
		     }

		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;

		     break;

	 	case IntegerOpt:

		     /* create the selection widget */
		     if (mutual_exclusion) 
		     {
			if (!(xvf_create_mut_excl_link(database, xvf_index,
					 mut_excl_ptr))) return(false);
			tmp_ptr = mut_excl_ptr;
			mut_excl_ptr = mut_excl_ptr->next;
			current->mut_excl = true;
			current->mut_excl_id = mut_excl_count;
		     }

		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;

		     break;

		case FloatOpt:
		     if (mutual_exclusion) 
		     {
			if (!(xvf_create_mut_excl_link(database, xvf_index,
					 mut_excl_ptr))) return(false);
			tmp_ptr = mut_excl_ptr;
			mut_excl_ptr = mut_excl_ptr->next;
			current->mut_excl = true;
			current->mut_excl_id = mut_excl_count;
		     }

		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;
		     break;

		case StringOpt:

		     if (mutual_exclusion) 
		     {
			if (!(xvf_create_mut_excl_link(database, xvf_index,
					 mut_excl_ptr))) return(false);
			tmp_ptr = mut_excl_ptr;
			mut_excl_ptr = mut_excl_ptr->next;
			current->mut_excl = true;
			current->mut_excl_id = mut_excl_count;
		     }
		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;

		     break;

		case LogicOpt:

		     if (mutual_exclusion) 
		     {
			if (!(xvf_create_mut_excl_link(database, xvf_index,
					 mut_excl_ptr))) return(false);
			tmp_ptr = mut_excl_ptr;
			mut_excl_ptr = mut_excl_ptr->next;
			current->mut_excl = true;
			current->mut_excl_id = mut_excl_count;
		     }
		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;

		     break;

		case Routine:

		     /* fill in other fields */
		     current->opt_widget = NULL;
		     current->opt_selected = -1;
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->toggle_int = -1;
		     current->modified = false;
		     break;

		case Cycle:

		     /* fill in other fields */
		     current->opt_widget = NULL;
		     current->opt_selected = -1;
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->toggle_int = -1;
		     current->modified = false;
		     break;

		case List:

		     /* fill in other fields */
		     current->opt_widget = NULL;
		     current->opt_selected = -1;
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->toggle_int = -1;
		     current->modified = false;
		     break;

		case Toggle:

		     if (mutual_exclusion) 
		     {
			if (!(xvf_create_mut_excl_link(database, xvf_index,
					 mut_excl_ptr))) return(false);
			tmp_ptr = mut_excl_ptr;
			mut_excl_ptr = mut_excl_ptr->next;
			current->mut_excl = true;
			current->mut_excl_id = mut_excl_count;
		     }
		     /* fill in other fields */
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->modified = true;

		     (*xvf_index)++;

		     /* fill in rest of toggle options */
		     if (!(xvf_fill_in_toggle(database,current,xvf_index,
			form, subform, guide)))
			  return(false);

		     (*xvf_index)--;

		     break;

		case MutExcl:
		     mutual_exclusion = true;
		     break;

		case HelpSel:
		     current->opt_widget = NULL;
		     current->opt_selected = -1;
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->toggle_int = -1;
		     current->modified = false;
		     break;

		case WorkWidget:
		     current->opt_widget = NULL;
		     current->opt_selected = -1;
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->toggle_int = -1;
		     current->modified = false;
		     break;

		case PaneAction:
		     current->opt_widget = NULL;
		     current->opt_selected = -1;
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->toggle_int = -1;
		     current->modified = false;

		     break;

		case Blank:
		     current->opt_widget = NULL;
		     current->opt_selected = -1;
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = sels_guide_num;
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->toggle_int = -1;
		     current->modified = false;

		     break;


		case QuitForm:
		     /* fill in other fields */
		     current->opt_widget = NULL;
		     current->opt_selected = -1;
		     current->next = NULL;
		     current->index = *xvf_index;
		     current->guide_num = sels_guide_num; /* starts at 0 */
		     current->sel_num = sel_count; sel_count++;
		     current->toggle_next = NULL;
		     current->toggle_int = -1;
		     current->modified = false;

		     break;

		case End:
		     if (mutual_exclusion == true)
		     {
			mutual_exclusion = false;
			mut_excl_count++;
			tmp_ptr->next = NULL;
	                pane->mut_exclusion[mut_excl_count] = 
		  	    (mut_excl_link *) malloc (sizeof (mut_excl_link));
			mut_excl_ptr = pane->mut_exclusion[mut_excl_count];
		     }
		     else
		     {
		        current = NULL;
		        done = true;
		     }
		     break;

                default:
		     fprintf(stderr, "xvf_fill_in_pane:\n");
		     fprintf(stderr, "UIS line out of place:\n");
		     fprintf(stderr, "'%s'\n",database[*xvf_index]);
		     break;

	    }  /* end switch */

	    /* link up the list of selections */

	    if ((flag != MutExcl) && (flag != End))
	    {
	        if (pane->sel_list == NULL) 
	        { 
		    pane->sel_list = current;
		    last = current;
	        }
	        else
	        {
	            last->next = current;
		    last = current;
	        }
	    }

	    (*xvf_index)++;

	} /* end while */

	return(true);

}  /* end xvf_fill_in_pane()  */
	

/************************************************************
*
*  Routine Name:  xvf_fill_in_toggle
*
*      Purpose:   fills in the toggle with items
*
*
*        Input: database     - pointer to xvform description
*		toggle_start - the pointer to the list of toggle items
*		xvf_index    - xvf_index into the database of current line
*		form 	     - pointer to the form tree
*		subform      - pointer to this subform branch
*		guide        - pointer to this guide_button branch
*
*       Output: true on success, false on failure
*
*    Called By: xvf_fill_in_pane
*
*   Written By: Danielle Argiro 
*
*     Comments: 
*
*	This is the controlling routine that fills in the toggle 
*	backplane with widgets that make up the toggle items.
*	Simultaneously, it creates the toggle list for this toggle, dropped
*	off of the list of selections for this pane from the xvf_selection node
*	that holds the [-T] line.  Possible lines from the database could 
*	indicate the any of the following selections, as long as
*	all toggle items are of the same type: 
*	input files, output files, integers, floats, logicals, 
*	or strings.  
*
*	====> toggle_start is the xvf_selection containing the [-T] 
*	      line, NOT the first toggle item.  toggle_start->next 
*	      is the next item following the entire toggle list specified 
*	      by [-T to -E], while toggle_start->toggle_next starts the 
*	      list of selections in the toggle.  
*		
*************************************************************/

int xvf_fill_in_toggle(database, toggle_start, xvf_index,
		       form, subform, guide)

char		*database[];
xvf_selection   *toggle_start;
int		*xvf_index;
xvf_form	*form;
xvf_sub_form	*subform;
xvf_guide_button *guide;
{
	int count=1;
	int done=false;
	xvf_selection *old, *current;
	int flag;

	old = toggle_start;

	while (!done)
	{
	    flag = xvf_get_line_type(database[*xvf_index]);

	    current = (xvf_selection *)calloc(1,sizeof(char)*
			sizeof(xvf_selection));
	    current->modified = false;


	    switch (flag) {

		case InputFile:
		case OutputFile:
	 	case IntegerOpt:
		case FloatOpt:
		case StringOpt:
		case LogicOpt:
		     current->next = NULL;
		     current->index = *xvf_index; 
		     current->guide_num = toggle_start->guide_num;
		     current->sel_num = toggle_start->sel_num; 
		     current->toggle_next = NULL;
		     current->toggle_int = count;

		     break;

		case Blank:
		     if (current != NULL)
			free(current);
		     current = NULL;
		     break;

		case End:
	
		     if (current != NULL)
		        free(current);
		     current = NULL;
		     done = true;
		     break;

                default:
		     fprintf(stderr, "xvf_fill_in_toggle:\n");
		     fprintf(stderr, "UIS line out of place:\n");
		     fprintf(stderr, "'%s'\n",database[*xvf_index]);
		     break;

	    }  /* end switch */

	    if (count == 1)
	    {
	       	toggle_start->toggle_next = current;
	    }
  	    else
	    {
		old->next = current;
 	    }
	    old = current;
	    count++;
	    *xvf_index = *xvf_index+1;
	}

	return(true);
}

int xvf_create_mut_excl_link(database, xvf_index, mut_excl_ptr)
char **database;
int   *xvf_index;
mut_excl_link *mut_excl_ptr;
{
	Line_Info line_info;

	xvf_clear_line_info(&line_info);
	xvf_gen_parse(database[*xvf_index], &line_info);
	if (line_info.optional != true) 
	{
	    fprintf(stderr, "xvf_create_mutual_exclusive_link:\n");
	    fprintf(stderr, "   ERROR: the following line must have its\n"); 
	    fprintf(stderr, "          'optional' field set to 1 (TRUE)\n");
	    fprintf(stderr, "          since it is part of a mutually ");
	    fprintf(stderr, "          exclusive group:\n");
	    fprintf(stderr, "'%s'\n",database[*xvf_index]);
	    return(false);
	}
	mut_excl_ptr->type = MutExcl;
	mut_excl_ptr->index = *xvf_index;
	mut_excl_ptr->next  =  (mut_excl_link *) 
			       malloc (sizeof (mut_excl_link));
	return(true);
}
