 /*
  * Khoros: $Id: workspace.c,v 1.2 1991/12/18 09:03:50 dkhoros Exp $
  */

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

 /*
  * $Log: workspace.c,v $
 * Revision 1.2  1991/12/18  09:03:50  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:  workspace.c                           <<<<
   >>>>                                                       <<<<
   >>>>   description:                                        <<<<
   >>>>                                                       <<<<
   >>>>      routines:  xvl_quit_workspace()		      <<<<
   >>>>                 xvl_destroy_workspace()		      <<<<
   >>>>			xvl_clear_workspace()		      <<<<
   >>>>                 xvl_reset_workspace()		      <<<<
   >>>>                 xvl_check_workspace()		      <<<<
   >>>>                 xvl_info_workspace()		      <<<<
   >>>>                                                       <<<<
   >>>> modifications:					      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */



/************************************************************
*
* Routine Name:  xvl_quit_workspace
*
*      Purpose:  This routine is used to quit a workspace.
*		 We prompt the user since quiting the toplevel
*		 workspace exits the program.
*
*        Input:  workspace - the display that the error occured on.
*
*
*   Written By: Carla Williams & Mark Young
*
*************************************************************/


xvl_quit_workspace(workspace)

Workspace	*workspace;
{
	int	     status, done = False;
	char	     *prompt[1], *name[1];


	/*
	 *  If the toplevel workspace is empty or doesn't need to be saved
	 *  then exit the program. We don't need to ask since there is
	 *  nothing to save.
	 */
	if (workspace->glyphs == NULL || workspace->modified == False)
	{
	   xvl_destroy_workspace(workspace);
	   xvl_destroy_workspace(clipboard);
	   exit(0);
	}

	/*
	 *  Since the workspace is not empty we want to prompt the user to
	 *  make sure they really want to exit without saving the program.
	 */
	while (!done)
	{
	   status = xvf_exit_wait("Do you wish to SAVE the workspace \
before quitting?\n\nCANCEL returns to the current workspace", "QUITTING","SAVE",
				      "EXIT", "CANCEL");

	   if (status == 1)                /*  SAVE (YES)  */
	   {
	      prompt[0] = xvf_strcpy("Workspace filename:");
	      name[0] = (char *)malloc(512*sizeof(char));
	      sprintf(name[0],"cantata.wksp");

	      if (xvf_query_wait("Choose filename for workspace to be saved \
under.", prompt, "SAVE", name, 1, 40) != NULL)
	      {
		 if (xvl_save_workspace(workspace, workspace->glyphs, name[0],
				True))
		 {
		    xvl_destroy_workspace(workspace);
		    xvl_destroy_workspace(clipboard);
		    exit(0);
		 }
	      }
	      free(prompt[0]); free(name[0]);
	   }
	   else if (status == 0)            /*  EXIT (NO)  */
	   {
	      xvl_destroy_workspace(workspace);
	      xvl_destroy_workspace(clipboard);
	      exit(0);
	   }
	   else                            /*  CANCEL  */
	      done = True;
	}
	workspace->menuform->form_sel = false;
	workspace->menuform->quit     = false;
	xvf_map_form(workspace->menuform);
}



/************************************************************
*
*  Routine Name:  xvl_destroy_workspace
*
*      Purpose:  Destroy the workspace and all associated
*		 resources.  First we call xvl_clear_workspace
*		 to delete all the glyph's from the workspace.
*		 Then we can destroy the workspace and free
*		 the workspace resources.
*
*	 Input:  
*
*       Output:  
*               
*   Written By:  Mark Young
*
*************************************************************/


xvl_destroy_workspace(workspace)

Workspace *workspace;
{
	Workspace *undo_workspace;


	/*
	 *  Make sure that there is a workspace to be destroyed.  Sometimes
	 *  we will end up destroying the clipboard workspace without looking
	 *  to see if a clipboard workspace exists.
	 */
	if (workspace == NULL)
	   return;

	/*
	 *  Call xvl_clear_workspace to delete all the glyph's in the
	 *  undo_workspace.  Also free the workspace itself.
	 */
	if (workspace->undo_workspace != NULL)
	{
	   undo_workspace = workspace->undo_workspace;
	   xvl_clear_workspace(undo_workspace);
	   xvf_destroy_form(undo_workspace->glyphform);

	   XtFree(workspace->undo_workspace);
	   workspace->undo_workspace = NULL;
	}

	/*
	 *  Call xvl_clear_workspace to delete all the glyph's
	 *  and their resources from the workspace before actually
	 *  destroying the workspace.
	 */
	xvl_clear_workspace(workspace);
	xve_delete_variables((long) workspace->glyphform);
	xvl_destroy_glyphlist(workspace->frontlist);

	/*
	 *  Close and destroy the variable definition command history file.
	 */
	if (workspace->var_file != stderr && workspace->var_file != NULL)
	{
	   fclose(workspace->var_file);
	   unlink(workspace->var_name);
	}
	if (workspace->var_name != NULL) free(workspace->var_name);

	/*
	 *  Call xvf_destroy_form() to destroy the menuform and glyphform.
	 */
	if (workspace->menuform != NULL)
	{
	   xvf_destroy_form(workspace->menuform);
	   workspace->menuform = NULL;
	}

	if (workspace->glyphform != NULL)
	{
	   xvf_destroy_form(workspace->glyphform);
	   workspace->glyphform = NULL;
	}

	/*
	 *  Need to destroy the workspace and free associated memory.
	 */
	if (workspace->attach_canvas == False && workspace->toplevel != NULL)
	{
	   XtUnmapWidget(workspace->toplevel);
	   XtDestroyWidget(workspace->toplevel);
	}

	if (workspace->gc != NULL)
	   XFreeGC(display, workspace->gc);

	if (workspace->geometry != NULL)
	   free(workspace->geometry);

	free(workspace);
}



/************************************************************
*
*  Routine Name:  xvl_clear_workspace
*
*      Purpose:   Deletes all glyph's from the workspace, without
*		  destroying the workspace itself.  This is done
*		  by calling xvl_destroy_glyph for each of the
*		  glyph's in the workspace list.
*
*	 Input:  workspace - the workspace to be cleared
*
*       Output:  
*               
*   Written By:  Mark Young
*
*************************************************************/


int  xvl_clear_workspace(workspace)

Workspace *workspace;
{
	long	    id;
	Glyph	    *glyph;
	GlyphList   *glyphlist;


	/*
	 *  Loop thru the glyph list destroying the workspace
	 *  glyph's and their associated resources.
	 */
	glyphlist = workspace->glyphs;
	while (glyphlist != NULL)
	{
	   glyph = glyphlist->glyph;
	   glyphlist = glyphlist->next;
	   xvl_destroy_glyph(glyph, False);
	}
	xvl_destroy_glyphlist(workspace->glyphs);
	workspace->glyphs = NULL;
	xvf_destroy_form(workspace->glyphform);
	workspace->glyphform = xvf_begin_form();
	xvf_change_routine(workspace->glyphform, xvl_glyph_menu_cb,
			(caddr_t) workspace);

	/*
	 *  delete the variables used in the current workspace.
	 */
	id = (long) workspace->glyphform;
	xve_clear_variables(id);
}



/************************************************************
*
* Routine Name:  xvl_reset_workspace
*
*      Purpose:  This routine is used to reset a workspace.  It
*		 initialize all glyphs to be modified.  For control
*		 glyphs it initializes the "count" and "while" control
*		 loops to their initial values and sets the glyph
*		 to modified so that it will be run again.
*
*        Input:  workspace
*
*
*   Written By:  Mark Young and Carla Williams
*
*************************************************************/


xvl_reset_workspace(workspace)

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


	glyphlist = workspace->glyphs;
	while (glyphlist != NULL)
	{
	   glyph = glyphlist->glyph;

	   /*
	    *  Check to see if the glyph is blinking, also check to
	    *  see if the glyph has an error file associated with it.
	    *  If so then unlink the file and reset the glyph's errorfile.
	    *  
	    */
	   xvl_unblink_glyph(glyph);
	   XtUnmapWidget(glyph->error);
	   if (glyph->errorfile != NULL)
	   {
	      unlink(glyph->errorfile);
	      free(glyph->errorfile);
	      glyph->errorfile = NULL; 
	   }

	   glyph->modified = True;
	   xvl_update_modified(glyph);

	   if (glyph->type == CONTROL)
	      xvl_reset_control(glyph);
	   else if (glyph->type == PROCEDURE)
	      xvl_reset_workspace(glyph->val.macro);

	   glyphlist = glyphlist->next;
	}
}



/************************************************************
*
* Routine Name:  xvl_check_workspace
*
*      Purpose:  This routine is used to check a workspace.  It
*		 goes thru the entire workspace making sure that
*		 required inputs and outputs have been specified.
*
*        Input:  workspace
*
*
*   Written By:  Mark Young and Carla Williams
*
*************************************************************/


xvl_check_workspace(workspace)

Workspace *workspace;
{
	Glyph	  *glyph;
	GlyphList *glyphlist, *blinklist;

	Node	  *node;
	NodeList  *nodelist;


	blinklist = NULL;
	glyphlist = workspace->glyphs;
	while (glyphlist != NULL)
	{
	   glyph = glyphlist->glyph;

	   /*
	    *  Go thru the glyph's input list looking for selected input
	    *  nodes with no input filename.  This is how we know when a
	    *  input node is required but not specified.
	    */
	   nodelist = glyph->input_list;
	   while (nodelist != NULL)
	   {
	      node = nodelist->node;
	      if (node->selected == True && node->filename == NULL)
	      {
	         XtMapWidget(glyph->error);
		 xvl_blink_glyph(glyph);
		 blinklist = xvl_add_to_glyphlist(glyph, blinklist);
	      }
	      nodelist = nodelist->next;
	   }

	   /*
	    *  Go thru the glyph's output list looking for selected output
	    *  nodes with no output filename.  This is how we know when a
	    *  output node is required but not specified.
	    */
	   nodelist = glyph->output_list;
	   while (nodelist != NULL)
	   {
	      node = nodelist->node;
	      if (node->selected == True && node->filename == NULL)
	      {
	         XtMapWidget(glyph->error);
		 xvl_blink_glyph(glyph);
		 blinklist = xvl_add_to_glyphlist(glyph, blinklist);
	      }
	      nodelist = nodelist->next;
	   }
	   glyphlist = glyphlist->next;
	}

	if (blinklist != NULL)
	{
	   xvf_error_wait("Unspecified Input and/or Output connections found! \
The glyphs currently blinking have required connections that have not been \
specified.  The current network will not run to completion without all required\
 connections being specified.", "xvl_check_workspace", NULL);

	   glyphlist = blinklist;
	   while (glyphlist != NULL)
	   {
	      glyph = glyphlist->glyph;
	      xvl_unblink_glyph(glyph);
	      XtUnmapWidget(glyph->error);

	      glyphlist = glyphlist->next;
	   }
	   xvl_destroy_glyphlist(blinklist);
	}
        else
        {
           xvf_error_wait(" ***** CHECK is OK!! ***** \n\n All required Input/\
Output connections have been specified. \n Click on OK to continue.", 
"xvl_check_workspace", NULL);
        }
}
