 /*
  * Khoros: $Id: control.c,v 1.5 1991/12/18 09:00:38 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: control.c,v 1.5 1991/12/18 09:00:38 dkhoros Exp $";
#endif

 /*
  * $Log: control.c,v $
 * Revision 1.5  1991/12/18  09:00:38  dkhoros
 * HellPatch3
 *
  */ 


/*
 *----------------------------------------------------------------------
 *
 * 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 "cantata.h"


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    file name:  control.c                             <<<<
   >>>>                                                       <<<<
   >>>>   description:                                        <<<<
   >>>>                                                       <<<<
   >>>>      routines: 	xvl_run_control_count()               <<<<
   >>>>                 xvl_run_control_while()               <<<<
   >>>>                 xvl_run_control_if()                  <<<<
   >>>>                 xvl_run_control_merge()               <<<<
   >>>>                 xvl_run_control_break()               <<<<
   >>>>                 xvl_run_control_trigger()             <<<<
   >>>>                 xvl_run_control_expr()                <<<<
   >>>>                 xvl_run_control_switch()              <<<<
   >>>>                                                       <<<<
   >>>> modifications:					      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */



/************************************************************
*
* Routine Name:  xvl_run_control_count
*
*      Purpose:  This routine is used to execute the control glyph
*                for a "counting loop" structure.
*
*        Input:  glyph
*
*
*   Written By:  Mark Young and Carla Williams
*
*************************************************************/


xvl_run_control_count(glyph)

Glyph	*glyph;
{
	xvf_guide_button *guide;
	xvf_sub_form	 *subform;
	Line_Info        lineinfo;
	xvf_selection    *selection;

	Workspace	 *workspace;
	Node		 *schedule;
	NodeList	 *input, *output;

	long	id;
	int	inum, onum, status;
	char	temp[512], error[1024], input_file[1024], *filename;
	float   value, test_value;
	char	*variable  = NULL,
		*initial   = NULL,
		*increment = NULL,
		*test      = NULL;


	/*
	 *  Do some initial checking to make sure that the control
	 *  glyph is connected and is correctly configured.
	 */
	input  = glyph->input_list;
	output = glyph->output_list;
	inum = xvl_count_nodelist(input);
	onum = xvl_count_nodelist(output);
	if (inum != 2 || onum != 2)
	{
	   (void) sprintf(error,"Error!  'count loop' control glyph requires \
two input & output connections.  Found %d input connections and %d output \
connections.", inum, onum);
	   xvf_error_wait(error, "xvl_run_control_count", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (input->next->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'count loop' control glyph requires \
that the loop input connection be connected before running.");
	   xvf_error_wait(error, "xvl_run_control_count", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (output->next->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'count loop' control glyph requires \
that the loop output connection be connected before running.");
	   xvf_error_wait(error, "xvl_run_control_count", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	/*
	 *  Since the control glyph appears to be correct we now need
	 *  to collect the information from the control glyph subform.
	 */
	subform = glyph->val.subform;
	guide = xvf_search_sel_guide(subform);
	if (guide == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}
	else if (guide->pane == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	xvf_clear_line_info(&lineinfo);
	selection = guide->pane->sel_list;

	while (selection != NULL)
	{
	   xvl_parse_line(subform->db, selection->index, &lineinfo);
	   if (lineinfo.variable != NULL && lineinfo.literal != NULL)
	   {
	      if (strcmp(lineinfo.variable,"lcv") == 0)
		 variable = xvf_strcpy(lineinfo.literal);
	      else if (strcmp(lineinfo.variable,"init") == 0)
		 initial = xvf_strcpy(lineinfo.literal);
	      else if (strcmp(lineinfo.variable,"incr") == 0)
		 increment = xvf_strcpy(lineinfo.literal);
	      else if (strcmp(lineinfo.variable,"test") == 0)
		 test = xvf_strcpy(lineinfo.literal);
	   }
	   selection = selection->next;
	}

	if (variable == NULL || initial == NULL || increment == NULL ||
	    test == NULL)
	{
	   (void) sprintf(error,"Error! Incomplete information found for count \
loop '%s'.", glyph->toplevel_name);
	   xvf_error_wait(error, "xvl_run_control_count", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (glyph->input == input->node || glyph->input == NULL)
	{
	   (void) sprintf(temp,"%s = %s", variable, initial);
	   filename = xvl_get_filename(input->node);
	}
	else
	{
	   (void) sprintf(temp,"%s = %s + %s", variable, variable, increment);
	   filename = xvl_get_filename(input->next->node);
	}

	workspace = glyph->workspace;
	id = (long) workspace->glyphform;
	if (!xve_eval_string(id, filename, input_file, error))
           strcpy(input_file, filename);
	free(filename);

	if (!xve_eval_float(id, temp, &value, error))
	{
	   xvf_error_wait(error, "xvl_run_control_count", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (!xve_eval_float(id, variable, &value, error))
	{
	   xvf_error_wait(error, "xvl_run_control_count", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (!xve_eval_float(id, test, &test_value, error))
	{
	   xvf_error_wait(error, "xvl_run_control_count", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	/*
	 *  Test the count loop
	 */
	if (value <= test_value)
	   schedule = output->next->node;
	else
	   schedule = output->node;

	status = xvl_schedule_control(glyph, input_file, schedule->filename,
				schedule);
	return(status);
}



/************************************************************
*
* Routine Name:  xvl_run_control_while
*
*      Purpose:  This routine is used to execute the control glyph
*                for an "while loop" structure.
*
*        Input:  glyph
*
*
*   Written By:  Mark Young and Carla Williams
*
*************************************************************/

xvl_run_control_while(glyph)

Glyph	*glyph;
{
	xvf_guide_button *guide;
	xvf_sub_form	 *subform;
	Line_Info        lineinfo;
	xvf_selection    *selection;

	Workspace	 *workspace;
	Node		 *schedule;
	NodeList	 *input, *output;

	long	id;
	int	inum, onum, test_value, status;
	char	error[1024], input_file[1024], *filename;
	float   value;
	char	*initial   = NULL,
		*update    = NULL,
		*test      = NULL;


	/*
	 *  Do some initial checking to make sure that the control
	 *  glyph is connected and is correctly configured.
	 */
	input  = glyph->input_list;
	output = glyph->output_list;
	inum = xvl_count_nodelist(input);
	onum = xvl_count_nodelist(output);
	if (inum != 2 || onum != 2)
	{
	   (void) sprintf(error,"Error!  'while loop' control glyph requires \
two input & output connections.  Found %d input connections and %d output \
connections.", inum, onum);
	   xvf_error_wait(error, "xvl_run_control_while", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (input->next->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'while loop' control glyph requires \
that the loop input connection be connected before running.");
	   xvf_error_wait(error, "xvl_run_control_while", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (output->next->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'while loop' control glyph requires \
that the loop output connection be connected before running.");
	   xvf_error_wait(error, "xvl_run_control_while", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	/*
	 *  Since the control glyph appears to be correct we now need
	 *  to collect the information from the control glyph subform.
	 */
	subform = glyph->val.subform;
	guide = xvf_search_sel_guide(subform);
	if (guide == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}
	else if (guide->pane == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	xvf_clear_line_info(&lineinfo);
	selection = guide->pane->sel_list;

	while (selection != NULL)
	{
	   xvl_parse_line(subform->db, selection->index, &lineinfo);
	   if ((lineinfo.variable != NULL) && (lineinfo.opt_sel == True) &&
	        lineinfo.literal != NULL)
	   {
	      if (strcmp(lineinfo.variable,"init") == 0)
		 initial = xvf_strcpy(lineinfo.literal);
	      else if (strcmp(lineinfo.variable,"update") == 0)
		 update = xvf_strcpy(lineinfo.literal);
	      else if (strcmp(lineinfo.variable,"test") == 0)
		 test = xvf_strcpy(lineinfo.literal);
	   }
	   selection = selection->next;
	}

	if (test == NULL)
	{
           (void) sprintf(error,"Error!  'while loop' control glyph requires \
that the Test Condition be specified before running.");
           xvf_error_wait(error, "xvl_run_control_while", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	/* Initial expression */
	workspace = glyph->workspace;
	id = (long) workspace->glyphform;
	if (glyph->input == input->node || glyph->input == NULL)
	{
	   filename = xvl_get_filename(input->node);
	   if (!xve_eval_string(id, filename, input_file, error))
              strcpy(input_file, filename);
	   free(filename);

	   if (initial != NULL)
	   {
	      if (!xve_eval_float(id, initial, &value, error))
	      {
   	         xvf_error_wait(error, "xvl_run_control_while", NULL);
	   	 xvl_restore_glyph(glyph);
	         return(DISPATCH_GLYPH_FAILED);
	      }
	   }
	}
	/* Update expression */
	else
	{
	   filename = xvl_get_filename(input->next->node);
	   if (!xve_eval_string(id, filename, input_file, error))
              strcpy(input_file, filename);
	   free(filename);

	   if (update != NULL)
	   {
	      if (!xve_eval_float(id, update, &value, error))
	      {
	         xvf_error_wait(error, "xvl_run_control_while", NULL);
	   	 xvl_restore_glyph(glyph);
	         return(DISPATCH_GLYPH_FAILED);
	      }
	   }
	}


	/* Evaluate test expression */

	if (!xve_eval_int(id, test, &test_value, error))
	{
	   xvf_error_wait(error, "xvl_run_control_while", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	/*
	 *  Test the while loop
	 */
	if (test_value)
	   schedule = output->next->node;
	else
	   schedule = output->node;

	status = xvl_schedule_control(glyph, input_file, schedule->filename,
				schedule);
	return(status);
}



/************************************************************
*
* Routine Name:  xvl_run_control_if
*
*      Purpose:  This routine is used to execute the control glyph
*                for an "if then else" structure.
*
*        Input:  glyph
*
*
*   Written By:  Mark Young and Carla Williams
*
*************************************************************/

xvl_run_control_if(glyph)

Glyph	*glyph;
{
	xvf_guide_button *guide;
	xvf_sub_form	 *subform;
	Line_Info        lineinfo;
	xvf_selection    *selection;

	Workspace	 *workspace;
	Node		 *schedule;
	NodeList	 *input, *output;

	long	id;
	int	inum, onum, value, status;
	char	error[1024], input_file[1024], *filename;
	char	*condition = NULL;


	/*
	 *  Do some initial checking to make sure that the control
	 *  glyph is connected and is correctly configured.
	 */
	input  = glyph->input_list;
	output = glyph->output_list;
	inum = xvl_count_nodelist(input);
	onum = xvl_count_nodelist(output);
	if (inum != 1 || onum != 2)
	{
	   (void) sprintf(error,"Error!  'if then else' control glyph requires \
one input & 2 output connections.  Found %d input connections and %d output \
connections.", inum, onum);
           xvf_error_wait(error, "xvl_run_control_if", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (input->node->selected == False )
	{
	   (void) sprintf(error,"Error!  'if then else' control glyph requires \
that the input be connected before running.");
           xvf_error_wait(error, "xvl_run_control_if", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (output->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'if then else' control glyph requires \
that the first output be connected before running.");
           xvf_error_wait(error, "xvl_run_control_if", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	/*
	 *  Since the control glyph appears to be correct we now need
	 *  to collect the information from the control glyph subform.
	 */
	subform = glyph->val.subform;
	guide = xvf_search_sel_guide(subform);
	if (guide == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}
	else if (guide->pane == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	xvf_clear_line_info(&lineinfo);
	selection = guide->pane->sel_list;

	while (selection != NULL)
	{
	   xvl_parse_line(subform->db, selection->index, &lineinfo);
	   if (lineinfo.variable != NULL)
	   {
	      if (strcmp(lineinfo.variable,"condition") == 0 ||
		 strcmp(lineinfo.variable,"cond") == 0)
		 condition = xvf_strcpy(lineinfo.literal);
	   }
	   selection = selection->next;
	}

	if (condition == NULL )
	{
	   (void) sprintf(error,"Error!  'if then else' control glyph requires \
that the conditional expression be specified before running.");
           xvf_error_wait(error, "xvl_run_control_if", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	workspace = glyph->workspace;
	id = (long) workspace->glyphform;

	filename = xvl_get_filename(input->node);
	if (!xve_eval_string(id, filename, input_file, error))
           strcpy(input_file, filename);
	free(filename);

	if (!xve_eval_int(id, condition, &value, error))
        {
           xvf_error_wait(error, "xvl_run_control_if", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
        }

	/*
	 *  Test the comparison value
	 */
	if (value)
	   schedule = output->node;
	else
	   schedule = output->next->node;

	status = xvl_schedule_control(glyph, input_file, schedule->filename,
				schedule);
	return(status);
}



/************************************************************
*
* Routine Name:  xvl_run_control_merge
*
*      Purpose:  This routine is used to execute the control glyph
*                for a merge operation
*
*        Input:  glyph
*
*
*   Written By:  Mark Young and Carla Williams
*
*************************************************************/

xvl_run_control_merge(glyph)

Glyph	*glyph;
{
	Node		 *schedule;
	NodeList	 *input, *output;

	int	inum, onum, status;
	char	error[1024], *filename;


	/*
	 *  Do some initial checking to make sure that the control
	 *  glyph is connected and is correctly configured.
	 */
	input  = glyph->input_list;
	output = glyph->output_list;
	inum = xvl_count_nodelist(input);
	onum = xvl_count_nodelist(output);
	if (inum != 2 || onum != 1)
	{
	   (void) sprintf(error,"Error!  'merge' control glyph requires two \
input & one output connections.  Found %d input connections and %d output \
connections.", inum, onum);
           xvf_error_wait(error, "xvl_run_control_merge", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (input->node->selected == False )
	{
	   (void) sprintf(error,"Error!  'merge' control glyph requires that \
the first input be connected before running.");
           xvf_error_wait(error, "xvl_run_control_merge", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (output->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'merge' control glyph requires that \
the output be connected before running.");
           xvf_error_wait(error, "xvl_run_control_merge", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (glyph->input == input->node || glyph->input == NULL)
	{
	   filename = xvl_get_filename(input->node);
	}
	else if (glyph->input == input->next->node && 
	         input->next->node->selected == True)
	{
	   filename = xvl_get_filename(input->next->node);
	}
	else
	{
	   (void) sprintf(error,"Error!  'merge' control glyph did not receive \
a valid input.");
           xvf_error_wait(error, "xvl_run_control_merge", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	schedule = output->node;
	status = xvl_schedule_control(glyph, filename, schedule->filename,
				schedule);
	free(filename);
	return(status);
}



/************************************************************
*
* Routine Name:  xvl_run_control_break
*
*      Purpose:  This routine is used to execute the control glyph
*                for a break operation
*
*        Input:  glyph
*
*
*   Written By:  Mark Young
*
*************************************************************/


xvl_run_control_break(glyph)

Glyph	*glyph;
{
	NodeList   *input;

	int	inum;
	char	error[1024];


	/*
	 *  Do some initial checking to make sure that the control
	 *  glyph is connected and is correctly configured.
	 */
	input  = glyph->input_list;
	inum = xvl_count_nodelist(input);
	if (inum != 1)
	{
	   (void) sprintf(error, "Error!  'break' control glyph requires one \
input connections.  Found %d input connections.", inum);
           xvf_error_wait(error, "xvl_run_control_break", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (input->node->selected == False )
	{
	   (void) sprintf(error, "Error!  'break' control glyph requires that \
the input be connected before running.");
           xvf_error_wait(error, "xvl_run_control_break", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}
	xvl_restore_glyph(glyph);
	return(DISPATCH_GLYPH_FAILED);
}



/************************************************************
*
* Routine Name:  xvl_run_control_trigger
*
*      Purpose:  This routine is used to execute the control glyph
*                for a trigger operation
*
*        Input:  glyph
*
*
*   Written By:  Mark Young
*
*************************************************************/

xvl_run_control_trigger(glyph)

Glyph	*glyph;
{
	Node		 *schedule;
	NodeList	 *input, *output;

	int	inum, onum, status;
	char	error[1024], *filename;


	/*
	 *  Do some initial checking to make sure that the control
	 *  glyph is connected and is correctly configured.
	 */
	input  = glyph->input_list;
	output = glyph->output_list;
	inum = xvl_count_nodelist(input);
	onum = xvl_count_nodelist(output);
	if (inum != 2 || onum != 1)
	{
	   (void) sprintf(error,"Error!  'trigger' control glyph requires two \
input & one output connections.  Found %d input connections and %d output \
connections.", inum, onum);
           xvf_error_wait(error, "xvl_run_control_merge", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (input->node->selected == False ||
	    input->next->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'trigger' control glyph requires that \
the both input be connected before running.");
           xvf_error_wait(error, "xvl_run_control_trigger", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (output->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'trigger' control glyph requires that \
the output be connected before running.");
           xvf_error_wait(error, "xvl_run_control_trigger", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}
	filename = xvl_get_filename(input->node);
	schedule = output->node;
	status = xvl_schedule_control(glyph, filename, schedule->filename,
				schedule);
	free(filename);
	return(status);
}



/************************************************************
*
* Routine Name:  xvl_run_control_expr
*
*      Purpose:  This routine is used to execute the control glyph
*                for an "expr" structure.
*
*        Input:  glyph
*
*
*   Written By: Mathew Yeates 
*
*************************************************************/

xvl_run_control_expr(glyph)

Glyph	*glyph;
{
	xvf_guide_button *guide;
	xvf_sub_form	 *subform;
	Line_Info        lineinfo;
	xvf_selection    *selection;

	Workspace	 *workspace;
	Node		 *schedule;
	NodeList	 *input, *output;

	long	id;
	float   value;
	int	inum, onum, status;
	char	error[1024], input_file[1024], *filename;
	char	*expression = NULL;


	/*
	 *  Do some initial checking to make sure that the control
	 *  glyph is connected and is correctly configured.
	 */
	input  = glyph->input_list;
	output = glyph->output_list;
	inum = xvl_count_nodelist(input);
	onum = xvl_count_nodelist(output);
	if (inum != 1 || onum != 1)
	{
	   (void) sprintf(error,"Error!  'expr' control glyph requires \
one input & one output connection.  Found %d input connections and %d output \
connections.", inum, onum);
           xvf_error_wait(error, "xvl_run_control_expr", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (input->node->selected == False )
	{
	   (void) sprintf(error,"Error!  'expr' control glyph requires \
that the input be connected before running.");
           xvf_error_wait(error, "xvl_run_control_expr", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	/*
	 *  Since the control glyph appears to be correct we now need
	 *  to collect the information from the control glyph subform.
	 */
	subform = glyph->val.subform;
	guide = xvf_search_sel_guide(subform);
	if (guide == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}
	else if (guide->pane == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	xvf_clear_line_info(&lineinfo);
	selection = guide->pane->sel_list;

	while (selection != NULL)
	{
	   xvl_parse_line(subform->db, selection->index, &lineinfo);
	   if (lineinfo.variable != NULL)
	   {
	      if (strcmp(lineinfo.variable,"expression") == 0)
		 expression = xvf_strcpy(lineinfo.literal);
	   }
	   selection = selection->next;
 	}

	if (expression == NULL )
	{
	   (void) sprintf(error,"Error!  'expr' control glyph requires \
that the expression be specified before running.");
           xvf_error_wait(error, "xvl_run_control_expr", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	workspace = glyph->workspace;
	id = (long) workspace->glyphform;

	filename = xvl_get_filename(input->node);
	if (!xve_eval_string(id, filename, input_file, error))
           strcpy(input_file, filename);
	free(filename);

	if (!xve_eval_float(id, expression, &value, error))
        {
           xvf_error_wait(error, "xvl_run_control_expr", NULL);
	   xvl_restore_glyph(glyph);
	   free(expression);
	   return(DISPATCH_GLYPH_FAILED);
        }
	free(expression);

        schedule = output->node;
	status = xvl_schedule_control(glyph, input_file, schedule->filename,
				schedule);
	return(status);
}



/************************************************************
*
* Routine Name:  xvl_run_control_switch
*
*      Purpose:  This routine is used to execute the control glyph
*                for a switch operation
*
*        Input:  glyph
*
*
*   Written By:  Mathew Yeates
*
*************************************************************/

xvl_run_control_switch(glyph)

Glyph	*glyph;
{
	xvf_guide_button *guide;
	xvf_sub_form	 *subform;
	Line_Info        lineinfo;
	xvf_selection    *selection;

	Workspace	 *workspace;
	Node		 *schedule;
	NodeList	 *input, *output;

	long	id;
	int	inum, onum,value, status;
        char    *condition = NULL;
	char	error[1024], *filename;



	/*
	 *  Do some initial checking to make sure that the control
	 *  glyph is connected and is correctly configured.
	 */
	input  = glyph->input_list;
	output = glyph->output_list;
	inum = xvl_count_nodelist(input);
	onum = xvl_count_nodelist(output);
	if (inum != 3 || onum != 1)
	{
	   (void) sprintf(error,"Error!  'switch' control glyph requires three \
input & one output connections.  Found %d input connections and %d output \
connections.", inum, onum);
           xvf_error_wait(error, "xvl_run_control_switch", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (input->node->selected == False ||
            input->next->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'switch' control glyph requires that \
the both required inputs be connected before running.");
           xvf_error_wait(error, "xvl_run_control_switch", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	if (output->node->selected == False)
	{
	   (void) sprintf(error,"Error!  'switch' control glyph requires that \
the output be connected before running.");
           xvf_error_wait(error, "xvl_run_control_switch", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}


	/*
	 *  Since the control glyph appears to be correct we now need
	 *  to collect the information from the control glyph subform.
	 */
	subform = glyph->val.subform;
	guide = xvf_search_sel_guide(subform);
	if (guide == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}
	else if (guide->pane == NULL)
	{
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	xvf_clear_line_info(&lineinfo);
	selection = guide->pane->sel_list;

	while (selection != NULL)
	{
	   xvl_parse_line(subform->db, selection->index, &lineinfo);
	   if (lineinfo.variable != NULL)
	   {
	      if (strcmp(lineinfo.variable,"condition") == 0)
		 condition = xvf_strcpy(lineinfo.literal);
	   }
	   selection = selection->next;
 	}

	if (condition == NULL )
	{
	   (void) sprintf(error,"Error!  'switch' control glyph requires \
that the expression be specified before running.");
           xvf_error_wait(error, "xvl_run_control_switch", NULL);
	   xvl_restore_glyph(glyph);
	   return(DISPATCH_GLYPH_FAILED);
	}

	workspace = glyph->workspace;
	id = (long) workspace->glyphform;
	if (!xve_eval_int(id, condition, &value, error))
        {
           xvf_error_wait(error, "xvl_run_control_expr", NULL);
	   xvl_restore_glyph(glyph);
	   free(condition);
	   return(DISPATCH_GLYPH_FAILED);
        }
	free(condition);

        if (value)
	   filename = xvl_get_filename(input->node);
        else
	   filename = xvl_get_filename(input->next->node);

        schedule = output->node;
	status = xvl_schedule_control(glyph, filename, schedule->filename,
				schedule);
	free(filename);
	return(status);
}
