 /*
  * Khoros: $Id: restore.c,v 1.4 1992/03/20 22:43:28 dkhoros Exp $
  */

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

 /*
  * $Log: restore.c,v $
 * Revision 1.4  1992/03/20  22:43:28  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 "cantata.h"

static int restore_workspace();
static int restore_connection_list();
static int parse_glyphinfo();
static int restore_variables(); 
static int restore_environment();
static int restore_glyph_connections();
static int restore_connection();
static void reset_glyphs();
static void read_line();

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    file name:  restore.c                             <<<<
   >>>>                                                       <<<<
   >>>>   description:                                        <<<<
   >>>>                                                       <<<<
   >>>>      routines:  xvl_restore_workspace()               <<<<
   >>>>                 restore_variables()                   <<<<
   >>>>                 restore_environment()                 <<<<
   >>>>                 restore_connection_list()             <<<<
   >>>>                 xvl_restore_files()                   <<<<
   >>>>                                                       <<<<
   >>>> modifications:					      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */



static void close_file(file, compress)

FILE	*file;
int	compress;
{
	if (compress)
	   xvf_pclose(file);
	else
	   fclose(file);
}


static FILE *open_file(filename, compress)

char	*filename;
int	*compress;
{
	int	i;
	FILE	*file, *xvf_popen();
	char	workname[512], temp[512];


	i = xvf_strlen(filename);
	if (filename == NULL || i == 0)
	   return(NULL);

	/*
	 *  See if the filename is currently specified as being in compressed
	 *  format.
	 */
	if (i >= 2)
	{
	   if (strncmp(&filename[i-2],".Z",2) == 0)
	      *compress = True;
	   else
	      *compress = False;
	}
	else
	   *compress = False;

	sprintf(workname,"%s",filename);
	if (*compress == False)
	{
	   if (access(workname, 0) == -1)
	   {
	      *compress = True;
	      sprintf(workname, "%s.Z", filename);
	   }
	   else if (!(file = fopen(workname, "r")))
	   {
	      sprintf(temp, "Unable to open %s for restoring workspace",
		      filename);
	      xvf_error_wait(temp, "xvl_restore_workspace", NULL);
	      return(NULL);
	   }
	}

	if (*compress == True)
	{
	   if (access(workname, 0) == -1)
	   {
	      return(NULL);
	   }
	   else
	   {
	      sprintf(temp,"uncompress -c %s", workname);
	      if (!(file = xvf_popen(temp, "r")))
	      {
	         sprintf(temp, "Error! Cannot find 'uncompress' command for \
uncompressing workspace file (%s).", filename);
		 xvf_error_wait(temp, "xvl_restore_workspace", NULL);
		 return(NULL);
	      }
	   }
	}
	return(file);
}



/************************************************************
*
*  Routine Name:  xvl_restore_workspace
*
*      Purpose:   Restore an cantata workspace.  This routine
*		  restores an cantata workspace by recreating
*		  the forms, connections, and glyphs stored
*		  in the filename.  xvl_restore_workspace
*		  also calls xvl_restore_files to restore
*		  the temporary files associated with the
*		  workspace at the time it was saved.
*
*		  The idea is to get each of the user interface
*		  specifications (database), create the forms,
*		  subforms, and glyphs until end of file is reached.
*		  Since more than one workspace can be restored
*		  we must make sure we have unique filenames for
*		  each input and output connection.
*
*		  Then restore_connection_list is called to
*		  reconnect all the form's input and output
*		  specifications.  And the temporary files are
*		  restored if the restore_files flag is True.
*
*	 Input:   1.  filename -  the name of the saved workspace file
*
*		  2.  save_files - a flag indicating if we should try to
*				   restore the temporary files.
*
*       Output:   returns 1 if able to restore the cantata session,
*		  otherwise returns 0.
*
*
*   Written By:   Mark Young & Carla Williams
*
*************************************************************/


int xvl_restore_workspace(workspace, filename, restore_files)

Workspace *workspace;
char	  *filename;
int	  restore_files;
{
	FILE	 *file;
	char	 temp[512], command[512];
	int	 compress;
	static   GlyphList *glyphs;


	/*
	 *  open the file that contains the workspace.
	 */
	if (!(file = open_file(filename, &compress)))
	   return(False);

	/*
	 *  Look for the BeginWorkspace definition.
	 */
	while (!feof(file))
	{
	   if (!fgets(temp, 512, file))
	      break;

	   if (sscanf(temp," # %s", command) == 1)
	   {
	      if (strcmp("BeginWorkspace", command)==0)
	      {
		 if (restore_workspace(workspace, file, &glyphs) == False)
		 {
		    (void) close_file(file, compress);
		    return(False);
		 }
		 else
		    break;
	      }
	   }
	}

	if (feof(file))
	{
	   fprintf(stderr,"\nrestore_workspace:\n");
	   fprintf(stderr,"End of file encountered before restoring the \
workspace.\n");
	   return(False);
	}

	/*
	 *  We have loaded and created all the glyphs.  Now we need to restore
	 *  the connections to those glyphs.
	 */
	restore_files = restore_connection_list(glyphs, file, restore_files);

	/*
	 *  Restore temporary files if any exist?
	 */
	if (restore_files == True)
	   (void) xvl_restore_files(glyphs, filename);


	/*
	 *  Cleanup.  Close the restore file and destroy the temporary
	 *  glyphlist.
	 */
	(void) close_file(file, compress);
	xvl_destroy_glyphlist(glyphs);

	return(True);
}

static int restore_workspace(workspace, file, glyphlist)

Workspace *workspace;
FILE	  *file;
GlyphList **glyphlist;
{
	Position     x, y;
	xvf_form     *form;
	xvf_sub_form *subform, *new_sub;

	Workspace    *macro;
	Glyph	     *glyph;
	GlyphList    *glyphs = NULL;

	int	     i, xpos, ypos, num_lines, db_size, modified, type,
		     copy_subform;
	char	     **database, temp[512], command[512], label_str[512],
		     restore_name[512], remote_machine[512];


	/*
	 *  Read the database specifications and build the forms and glyphs
	 */
	if ((database = xvf_read_database(file, &num_lines, &db_size)) == NULL)
	{
	   xvf_error_wait("Unable to read the database for the workspace to be \
restored.  Therefore the rest of the workspace will not be restored.",
			  "restore_workspace", NULL);
	   return(False);
	}
	else
	{
	   for (i = 0; i < num_lines; i++)
	   {
	      read_line(database[i]);
 	   }
	}

        /* Build the form for the database.  */
	if ((form = xvf_build_form(database, num_lines, db_size, NULL, 0, NONE,
			   xvl_glyph_menu_cb, -1, -1)) == NULL)
	{
	   xvf_error_wait("Unable to re-create the glyph's user interface \
specifications.  Therefore the rest of the workspace will not be restored.",
			  "restore_workspace", NULL);
	   return(False);
	}

	if (workspace->glyphs == NULL)
	{
	   copy_subform = False;
	   xvf_destroy_form(workspace->glyphform);
	   workspace->glyphform = form;
	   xvf_change_routine(workspace->glyphform, xvl_glyph_menu_cb,
			(caddr_t) workspace);
	}
	else
	   copy_subform = True;


	subform = form->subform;
	while (!feof(file))
	{
	   if (fgets(temp, 512, file))
	   {
	      if (parse_glyphinfo(temp, label_str, &type, &modified,
			restore_name, remote_machine, &xpos, &ypos) == True)
	      {
		 x = xpos;
		 y = ypos;

		 if (type == PROCEDURE)
		 {
		    if ((glyph = xvl_build_glyph(workspace, type,
				(caddr_t) label_str, True, x, y)) == NULL)
		    {
		       xvl_destroy_glyphlist(glyphs);
		       return(False);
		    }
		    macro = glyph->val.macro;
		    if (!restore_workspace(macro, file, NULL))
		    {
		       xvl_destroy_glyphlist(glyphs);
		       return(False);
		    }
		 }
		 else
		 {
		    if (copy_subform)
		    {
		       if (!(new_sub = xvl_copy_subform(workspace->glyphform,
					subform)))
		       {
			  xvl_destroy_glyphlist(glyphs);
			  return(False);
		       }
		    }
		    else new_sub = subform;

		    if ((glyph = xvl_build_glyph(workspace, type,
				(caddr_t) new_sub, True, x, y)) == NULL)
		    {
		       xvl_destroy_glyphlist(glyphs);
		       return(False);
		    }
		    subform = subform->next_subform;
		 }
		 glyph->restore_name   = xvf_strcpy(restore_name);
		 glyph->machine = xvl_get_machine(remote_machine);
		 glyph->modified = modified;
	         xvl_update_modified(glyph);

		 /*
		  *  Add the glyph to the glyphlist.  This will be used
		  *  later when restoring the connection list.
		  */
		 glyphs = xvl_add_to_glyphlist(glyph, glyphs);
	      }
	      else if (sscanf(temp, " # %s", command) == 1)
	      {
		 if (strcmp("BeginVariables", command) == 0)
		    restore_variables(workspace, file);
		 else if (strcmp("BeginEnvironment", command) == 0)
		    restore_environment(workspace, file);
		 else if (strcmp("EndWorkspace", command) == 0)
		    break;
	      }
	      else
	      {
		 fprintf(stderr,"restore_workspace:\n");
		 fprintf(stderr,"Error parsing the following line.\n'%s'\n",
			    temp);
	      }
	   }
	}

	/*
	 *  Destroy the temporary form if we copied the subforms.
	 */
	if (copy_subform)
	{
	   xvf_destroy_form(form);
	   if (!(xvf_adjust_form_indices(workspace->glyphform)))
	   {
	      xvl_destroy_glyphlist(glyphs);
	      return(False);
	   }
	}
	if (glyphlist != NULL) *glyphlist = glyphs;
	return(True);
}

static int parse_glyphinfo(string, label_str, type, modified, restore_name,
		remote_machine, xpos, ypos)

char *string, *label_str, *restore_name, *remote_machine;
int  *type, *modified, *xpos, *ypos;
{

	/*
	 *  Crude, rude, and kludge parsing of the glyph information from
	 *  the scan line.  There is currently three different parsing
	 *  scenario:
	 *
	 *  For Khoros 0.9 Beta:
	 *	# put_update 2 1 put_update7_glyph 100+60
	 *
	 *  For Khoros 1.0 (thru patch 2):
	 *	# 'put_update' 2 1 'put_update7_glyph' 100+60
	 *
	 *  For Khoros 1.0 (patch 3) has optional remote machine name:
	 *	# 'put_update' 2 1 'put_update7_glyph' 'bullwinkle' 100+60
	 *
	 */
	if (sscanf(string," # %*[']%[^']%*['] %d %d %*[']%[^']%*['] %d+%d",
		label_str, type, modified, restore_name, xpos, ypos) == 6)
	{
	   remote_machine[0] = '\0';
	   return(True);
	}
	else if (sscanf(string," # %*[']%[^']%*['] %d %d %*[']%[^']%*['] \
%*[']%[^']%*['] %d+%d", label_str, type, modified, restore_name,
		remote_machine, xpos, ypos) == 7)
	{
	   return(True);
	}
	else if (sscanf(string," # %s %d %d %s %d+%d", label_str, type,
		modified, restore_name, xpos, ypos) == 6)
	{
	   remote_machine[0] = '\0';
	   return(True);
	}
	return(False);
}



/************************************************************
*
*  Routine Name:  read_line
*
*      Purpose:  This routine is supposed to read the user interface line
*		 from the workspace and then correct it for carriage
*		 returns, but since xvf_read_database() doesn't do this
*		 we use read_line as a post process after reading the
*		 user-interface specification.
*
*	 Input:  line - the user interface line to be corrected.
*
*       Output:  restores the variables
*
*
*   Written By:   Mark Young
*
*************************************************************/


static void read_line(line)

char *line;
{
	int	i = 0;
	char	data[MaxLength], *temp;


	if (line == NULL)
	   return;

	if (strchr(line, '\\') == NULL)
	   return;

	temp = line;
	while (*temp != '\0')
	{
	   if (i == MaxLength)
	   {
	      strncpy(line, data, MaxLength);
	      line += MaxLength; i = 0;
	   }

	   if (temp[0] == '\\' && temp[1] == 'n')
	   {
	      data[i] = '\n';
	      temp++;
	   }
	   else
	      data[i] = *temp;

	   temp++; i++;
	}
	data[i] = '\0';
	strcpy(line, data);
}



/************************************************************
*
*  Routine Name:  restore_variables
*
*      Purpose:  Reads the variables for the given workspace and
*		 sends them to parser.
*
*	 Input:  workspace - the workspace to work from
*		 file	   - the file to read the connection information from
*
*       Output:  restores the variables
*
*
*   Written By:   Mark Young
*
*************************************************************/


static int restore_variables(workspace, file)

Workspace *workspace;
FILE	  *file;
{
	long    id;
	float	value;
	char	temp[512], command[512], error[1024];


	id   = (long) workspace->glyphform;
	while (!feof(file))
	{
	   if (fgets(temp, 512, file))
	   {
	      if (sscanf(temp, " # %s", command) == 1)
	      {
		 if (strcmp("EndVariables", command) == 0)
		    break;
	      }
	      else
	      {
		 if (xve_eval_float(id, temp, &value, error) == False)
		    xvf_error_wait(error, "xvl_eval_variables", NULL);
	      }
	   }
	}
}



/************************************************************
*
*  Routine Name:  restore_environment
*
*      Purpose:  Reads the environment information for the given
*		 workspace and sends them to parser.
*
*	 Input:  workspace - the workspace to restore the
*			     environment information.
*		 file	   - the file to read the environment
*			     information from
*
*       Output:  restores the environment information
*
*
*   Written By:   Mark Young
*
*************************************************************/


static int restore_environment(workspace, file)

Workspace *workspace;
FILE	  *file;
{
	int	num, restore;
	char	temp[512], command[512];


	/*
	 *  If the glyph list is not empty then prompt to see if
	 *  user wants to override the workspace's current environment
	 *  settings with the saved ones.
	 */
	if (workspace->glyphs != NULL)
	{
	   restore = xvf_warn_wait("Do you wish to override the current \
workspace's environment settings with those saved in the restore file?",
				 "RESTORE Environment - Warning", "YES", "NO");
	}
	else
	   restore = True;

	while (!feof(file))
	{
	   if (fgets(temp, 512, file))
	   {
	      if ((sscanf(temp, " # %s %d", command, &num) == 2) &&
		       (restore == True))
	      {
		 if (strcmp(command,"Grid") == 0)
		    workspace->show_grid = num;
		 else if (strcmp(command,"GridSize") == 0)
		    workspace->grid_size = num;
		 else if (strcmp(command,"SmallGlyph") == 0)
		    workspace->small_glyphs = num;
		 else if (strcmp(command,"RubberBand") == 0)
		    workspace->rubberband = num;
		 else if (strcmp(command,"Viewport") == 0)
		    workspace->view_port = num;
		 else if (strcmp(command,"AttachCanvas") == 0)
		    workspace->attach_canvas = num;
		 else if (strcmp(command,"ShowDav") == 0)
		    workspace->show_dav = num;
		 else if (strcmp(command,"ShowModified") == 0)
		    workspace->show_modified = num;
		 else if (strcmp(command,"ShowClipboard") == 0)
		    workspace->show_clipboard = num;
		 else if (strcmp(command,"EchoRoutine") == 0)
		    workspace->echo_exec = num;
		 else if (strcmp(command,"GlyphPlacement") == 0)
		    workspace->glyph_placement = num;
		 else if (strcmp(command,"InheritAttributes") == 0)
		    workspace->inherit_attributes = num;
		 else if (strcmp(command,"GlobalVariables") == 0)
		    workspace->global_variables = num;
		 else if (strcmp(command,"DemandDriven") == 0)
		    workspace->demand_driven = num;
		 else if (strcmp(command,"LeaveGlyph") == 0)
		    workspace->leave_glyph = num;
		 else if (strcmp(command,"AutoPlacement") == 0 ||
			  strcmp(command,"Placement") == 0)
		    workspace->auto_placement = num;
		 else if (strcmp(command,"Parallel") == 0 ||
			  strcmp(command,"ParallelExec") == 0)
		    workspace->parallel = num;
		 else if (strcmp(command,"RemoteExec") == 0)
		    workspace->remote_execution = num;
		 else if (strcmp(command,"StreamExec") == 0)
		    workspace->stream_execution = num;
	      }
	      else if (sscanf(temp, " # %s", command) == 1)
	      {
		 if (strcmp("EndEnvironment", command) == 0)
		    break;
	      }
	   }
	}

	/*
	 *  If we are to restore then call xvl_init_environment to set
	 *  the current environment information.
	 */
	if (restore)
	{
	   xvl_init_environment(workspace, workspace->menuform, cantata);
	   xvl_set_attributes(workspace);
	}
}



/************************************************************
*
*  Routine Name:  restore_connection_list
*
*      Purpose:  Need to go thru the restored glyphs and reconnect
*		 the glyph connections.  This connection information
*		 is important since it is used by cantata to visually
*		 show which glyphs are connected.  It is also used
*		 by auto run in computing the topology for automatic
*		 execution of cantata.
*
*	 Input:  glyphs    - the glyph list to read from
*		 file	   - the file to read the connection information from
*		 restored  - a flag used to indicate if the temporary files are
*			     to be restored.
*
*       Output:  1. reconnects the glyhps
*
*
*   Written By:   Mark Young
*
*************************************************************/


static int restore_connection_list(glyphs, file, restored)

GlyphList *glyphs;
FILE	  *file;
int	  restored;
{
	Glyph   *glyph;
	int	status;
	char	temp[512], glyph_name[512];


	while (!feof(file))
	{
	   if (fgets(temp, 512, file))
	   {
	      
	      if ((status = sscanf(temp," # GlyphBegin %*[']%[^']%*[']",
			glyph_name)) != 1)
	      {
	         status = sscanf(temp, " # GlyphBegin %s", glyph_name);
	      }

	      if (status == 1)
	      {
		 if (!(glyph = xvl_find_glyph(glyphs, glyph_name)))
		 {
		    fprintf(stderr,"\nrestore_connection_list:\n");
		    fprintf(stderr,"Unable to find glyph '%s'.  Therefore no \
connections for this glyph will be restored.\n", glyph_name);
		 }
		 else
		 {
		    if (restored == False)
		    {
		       glyph->modified = True;
		       xvl_update_modified(glyph);
		    }
		    restore_glyph_connections(file, glyph, glyphs, restored);
	         }
	      }
	   }
	}
	return(True);
}


static int restore_glyph_connections(file, glyph, glyphs, restored)

FILE	  *file;
Glyph	  *glyph;
GlyphList *glyphs;
int	  restored;
{
	Node	 *onode;
	NodeList *output_list;
	char	 temp[512], command[512];


	/*
	 *  Get the output list.
	 */
	output_list = glyph->output_list;

	while (!feof(file))
	{
	   if (fgets(temp, 512, file))
	   {
	      if (sscanf(temp, " # %s", command) == 1)
	      {
	         if (strcmp("GlyphEnd", command) == 0)
	         {
		    return(True);
		 }
	         else if (strcmp("ConnectionBegin", command) == 0)
		 {
		    if (output_list == NULL)
		    {
		       fprintf(stderr,"\nrestore_glyph_connections:\n");
		       fprintf(stderr,"Error restoring the output connections \
for glyph '%s'.  End of output list encountered but output connection \
information still remains.", glyph->restore_name);
		       return(False);
		    }
		    onode = output_list->node;
		    (void) restore_connection(glyphs, file, onode, restored);
		    output_list = output_list->next;
		 }
	      }
	   }
	}
	return(False);
}

static int restore_connection(glyphs, file, onode, restored)

GlyphList *glyphs;
FILE	  *file;
Node	  *onode;
{
	Glyph    *input_glyph;
	Node	 *inode;
	NodeList *input_list;
	int	 i, match, temp_file, selected, num, index;
	char	 *machine, temp[MaxLength], name[MaxLength],machname[MaxLength];


	while (!feof(file))
	{
	   if (fgets(temp, 512, file))
	   {
	      if ((sscanf(temp, " # %*[']%[^']%*['] %d %d", name, &temp_file,
			&selected) == 3) || (sscanf(temp, " # %s %d %d", name,
			&temp_file, &selected) == 3))
	      {
	         onode->temp_file = temp_file;
	         onode->selected  = selected;

		 if (temp_file)
		 {
		    machine = xvl_get_machname(onode->glyph, machname);
		    onode->filename = xvl_tempnam(name, NULL, machine);
		    if (restored)
		       onode->restore_name = xvf_strcpy(name);
		    else
		    {
		       onode->dav = False;
		       onode->glyph->modified = True;
		    }
		 }
		 else
		 {
		    onode->dav = True;
		    onode->filename = xvf_strcpy(name);
		 }
		 xvl_update_filename(onode);
		 xvl_update_dav(onode);
		 xvl_update_modified(onode->glyph);
	         break;
	      }
	      else if (sscanf(temp, " # %s", name) == 1)
	      {
	         if (strcmp("ConnectionEnd", name) == 0)
	         {
		    return(True);
	         }
	      }
	   }
	}

	while (!feof(file))
	{
	   if (fgets(temp, 512, file))
	   {
	      if (((match = sscanf(temp, " # %*[']%[^']%*['] %d %d", name,
			&index, &num)) >= 2) || ((match = sscanf(temp,
			" # %s %d %d",name, &index, &num)) >= 2))
	      {
		 if (!(input_glyph = xvl_find_glyph(glyphs, name)))
		 {
		    fprintf(stderr,"restore_connection:\n");
		    fprintf(stderr,"Unable to find input glyph '%s'. Therefore \
the connection between %s -> %s will not be restored for (%s).\n", name,
onode->glyph->restore_name, name, onode->filename);
		 }
		 else
		 {
		    /*
		     *  The following is a kludge to allow both restore
		     *  connection type restores.
		     */
		    input_list = input_glyph->input_list;
		    if (match == 3 && num != -1)
		    {
		       for (i = 0; i < num && input_list != NULL; i++)
		           input_list = input_list->next;
		    }
		    else
		    {
		       while (input_list != NULL)
		       {
			  if (input_list->node->selection->index == index)
			     break;
		          else
			     input_list = input_list->next;
		       }
		    }

		    if (input_list != NULL)
		    {
		       inode = input_list->node;
		       xvl_build_connection(inode, onode);
		    }
		    else
		    {
		       fprintf(stderr,"restore_connection:\n");
		       fprintf(stderr,"Unable to find input connection for \
the current output connection.  Therefore the connection between %s -> %s will \
not be restored for (%s).\n", onode->glyph->restore_name, name,
 onode->filename);
		    }
		 }
	      }
	      else if (sscanf(temp, " # %s", name) == 1)
	      {
		 if (strcmp("ConnectionEnd", name) == 0)
		 {
		    return(True);
		 }
	      }
	   }
	}
	return(False);
}



/************************************************************
*
*  Routine Name:  xvl_restore_files
*
*      Purpose:  to restore all temporary files associated with
*                a workspace (using the old names)
*
*	 Input:  glyphs    -  the glyphlist that contains the new
*			      filenames for the temporary output
*			      connections.
*	         filename  -  under which temp files were saved
*
*       Output:  True  if save was successful
*                False if could not open file
*
*
*   Written By:   Mark Young & Carla Williams
*
*************************************************************/


int xvl_restore_files(glyphs, filename)

GlyphList *glyphs;
char	  *filename;
{
	FILE	 *file;
	int	 i, compress, fid, num_bytes;
	char	 *data, *tempfile, workfile[512], temp[512], datafile[256];

	Node	 *onode;


	i = xvf_strlen(filename);
	if (i >= 2)
	{
	   if (strncmp(&filename[i-2],".Z",2) == 0)
	   {
	      strncpy(workfile, filename, i-2);
	      workfile[i-2] = '\0';
	      strcat(workfile,".files");
	   }
	   else
	      sprintf(workfile,"%s.files",filename);
	}
	else if (i <= 0)
	{
	   reset_glyphs(glyphs);
	   return(False);
	}
	else
	   sprintf(workfile,"%s.file",filename);

	if (!(file = open_file(workfile, &compress)))
	{
	   reset_glyphs(glyphs);
	   return(False);
	}

	while (!feof(file))
	{
	   if (!fgets(temp, 512, file))
	      break;

	   i = 0;
	   while ((temp[i] == ' ' || temp[i] == '\t') && i < 512)
	      i++;

	   if (temp[i] != '#' && temp[i] != '!' && temp[i] != '%')
	   {
	      if (sscanf(temp,"%s %d", datafile, &num_bytes) != 2)
	      {
	         sprintf(temp, "Error in restoring information from the \
cantata temporary workspace file (%s).", workfile);
	         xvf_error_wait(temp, "xvl_restore_files", NULL);

	         close_file(file, compress);
		 reset_glyphs(glyphs);
	         return(False);
	      }

	      /*
	       *  Malloc space to read the data into, so that we can
	       *  restore the temporary files.
	       */
	      if (!(data = (char *) kmalloc(num_bytes)))
	      {
	         (void) sprintf(temp,"Not enough memory!  Tried to malloc %d \
bytes.   No more temporary files will be restored.", num_bytes);
	         xvf_error_wait(temp, "xvl_restore_files", NULL);

	         close_file(file, compress);
		 reset_glyphs(glyphs);
	         return(False);
	      }

	      /*
	       *  Read data from saved workspace file.
	       */
	      if (fread(data, 1, num_bytes, file) != num_bytes)
	      {
	         (void) sprintf(temp, "Unable to read data from (%s) for \
restoring temporary files", workfile);
	         xvf_error_wait(temp, "xvl_save_files", NULL);

	          close_file(file, compress);
	          free(data);
		  reset_glyphs(glyphs);
	          return(False);
	      }

	      /*
	       *  
	       */
	      if ((onode = xvl_find_onode(datafile, glyphs)) != NULL)
	      {
	         if (onode->filename != NULL)
	         {
		    tempfile = onode->filename;
	         }
	         else
		    tempfile = datafile;

	         free(onode->restore_name);
	         onode->restore_name = NULL;
	      }
	      else
		 tempfile = datafile;

	      /*
	       *  Open the temporary file so that we can restore the data
	       *  to it.
	       */
	      if ((fid = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0644)) <= 0)
	      {
	         (void) sprintf(temp,"Unable to open temporary file %s to \
restore", tempfile);
	         xvf_error_wait(temp, "xvl_restore_files", NULL);
	      }
	      else
	      {
	         if (write(fid, data, num_bytes) != num_bytes)
	         {
		    sprintf(temp,"Unable to restore data for temp file %s",
		   	       tempfile);
		    xvf_error_wait(temp, "xvl_restore_files", NULL);
	         }
	         close(fid);
	         free(data);
	      }
	   }
	}
	close_file(file, compress);
        return(True);
}



/************************************************************
*
*  Routine Name:  reset_glyphs
*
*      Purpose:  race thru the list of glyphs and update the
*		 glyph to be modified.
*
*	 Input:  glyphs    -  the glyphlist that contains the
*			      glyphs that will be modified
*
*       Output:  none
*
*   Written By:   Mark Young
*
*************************************************************/


static void reset_glyphs(glyphlist)

GlyphList *glyphlist;
{
	Glyph     *glyph;
	Workspace *procedure;

	while (glyphlist != NULL)
	{
	   glyph = glyphlist->glyph;
	   glyph->modified = True;
	   xvl_update_modified(glyph);

	   if (glyph->type == PROCEDURE)
	   {
	      procedure = glyph->val.macro;
	      reset_glyphs(procedure->glyphs);
	   }
	   glyphlist = glyphlist->next;
	}
}
