 /*
  * Khoros: $Id: jp.c,v 1.2 1992/03/20 22:47:35 dkhoros Exp $
  */

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

 /*
  * $Log: jp.c,v $
 * Revision 1.2  1992/03/20  22:47:35  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"
#include "jp.h"

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	       Journal Playback Routines                      <<<<
   >>>>                                                       <<<<
   >>>>                jp_initialize()                        <<<<
   >>>>                jp_start_playback()                    <<<<
   >>>>                jp_file_cb()                           <<<<
   >>>>                jp_input_cb()                          <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */



/************************************************************
*
*  Routine Name: jp_initialize
*
*      Purpose:  Initializes the application for journal playback or
*		 journal record.
*
*        Input:  None
*
*       Output:  None
*
*   Written By:  Danielle Argiro, Mark Young, and Stephanie Hallett
*
*************************************************************/


jp_initialize()
{
	unsigned char	type;
	char	 *fullpath, temp[MaxLength];


	/*
	 *  Initialize the journal playback global variables
	 */
	jp_halt = False;
	jp_control = NULL;
	jp_window = NULL;

	/*
	 *  Check to see if the user wants to start journal playback.
	 */
	if (jp_playing)
	{
	   if (play_filename != NULL)
	   {
	      if (!(fullpath = vfullpath(play_filename, NULL, NULL)))
	      {
		 jp_playing = False;
	      }
	      else if (strcmp(fullpath,"-") == 0)
	      {
		 play_file = stdin;
	      }
	      else if (!(play_file = fopen(play_filename, "r")))
	      {
		 (void) fprintf(stderr,"Error! Unable to open journal playback \
file '%s'", play_filename);
		  jp_playing = False;
	      }
	      else
		  fread(&type, 1, 1, play_file);
	   }
	   else
	   {
	      jp_playing = False;
	      xvf_error_wait("Error!  Filename needed for journal playback.",
			NULL, NULL);
	   }

	   if (jp_playing == True)
	   {
	      if (jp_grab == True)
	      {
		 jp_control = xvf_create_jp_control();
		 XtPopup(jp_control, XtGrabNone);
		 jp_window = XtWindow(jp_control);
	      }
	      jp_start_playback();
	   }
	}

	/*
	 *  Check to see if the user wants to start a journal recording.
	 */
	if (jp_recording)
	{
	   if (record_filename != NULL)
	   {
	      if (!(fullpath = vfullpath(record_filename, NULL, NULL)))
	      {
		 jp_recording = False;
	      }
	      else if (strcmp(fullpath,"-") == 0)
	      {
		 record_file = stdout;
	      }
	      else if (!(record_file = fopen(record_filename, "w")))
	      {
		  jp_recording = False;
		 (void) sprintf(temp,"Error! Unable to open journal record \
file '%s'", record_filename);
		  xvf_error_wait(temp, NULL, NULL);
	      }
	      else
	      {
		  type = (unsigned char) machtype(NULL);
		  fwrite(&type, 1, 1, record_file);
	      }
	   }
	   else
	   {
	      jp_recording = False;
	      xvf_error_wait("Error!  Filename needed for journal recording.",
			NULL, NULL);
	   }
	}
}



/************************************************************
*
*  Routine Name: jp_start_playback
*
*      Purpose:  Starts the journal playback mechanism.
*
*        Input:  None
*
*       Output:  None
*
*   Written By:  Danielle Argiro, Mark Young, and Jermey Worley
*
*************************************************************/


jp_start_playback()
{
	/*
	 *  if the file is being readin is a real file then we want
	 *  want to use the jp_file_cb to playback the events, but
	 *  when we are reading from a stream then we want to use
	 *  jp_input_cb and ignore elapsed time associated with
	 *  playing back events.
	 */
	if (play_file != stdin)
	   XtAppAddTimeOut(xvf_app_context, 0, jp_file_cb, NULL);
	else
	   XtAppAddInput(xvf_app_context, fileno(play_file), 
			 (XtPointer) XtInputReadMask, jp_input_cb, NULL);
}



/************************************************************
*
*  Routine Name: jp_file_cb
*
*      Purpose:  This routine is used as the driver to playback
*		 the events out of a file.  First we check to
*		 see if there is an event to be dispatched (if
*		 the data is not NULL).
*
*		 After dispatching the previous event we read the
*		 next event from the file (calls jp_playback()).
*		 Associated with this event is returned the elapsed
*		 time.  We also compute the current elapsed time and
*		 the difference is the time we need to wait before
*		 playing back this event.  We then add a timeout to
*		 call us back after that elapsed time.  At that time
*		 we will dispatch the event and get the next event to
*		 played back.
*
*        Input:  None
*
*       Output:  data  - the data event to be played back, NULL if no event.
*       	 time  - the id for this timeout.
*
*   Written By:  Mark Young and Danielle Argiro
*
*************************************************************/


void jp_file_cb(data, id)

XtPointer	data;
XtIntervalId	id;
{
	XEvent event;
	int    elapsed, dispatch_event;
	static int playback_event = False;


	/*
	 *  If there is an event then dispatch it before getting the next
	 *  one from jp_playback().
	 */
	if (playback_event == True)
	{
	   if (jp_playback(&event) == False)
	      dispatch_event = False;
	   else
	      dispatch_event = True;
	}
	else
	   dispatch_event = False;


	/*
	 *  Get the elapsed time for the next event from jp_elapsed_time().
	 *  If it fails then add a timeout to calls us back immediately,
	 *  otherwise call us back  the original elapsed time .vs. the current
	 *  elapsed.  Then call
	 *  us back to play that event after that amount of elapsed time.
	 */
	if (jp_playing == True && jp_halt == False)
	{
	   if (jp_elapsed_time(&elapsed) == False)
	   {
	      XtAppAddTimeOut(xvf_app_context, 50, jp_file_cb, NULL);
	      playback_event = False;
	   }
	   else
	   {
	      XtAppAddTimeOut(xvf_app_context, (Time)elapsed, jp_file_cb, NULL);
	      playback_event = True;
	   }
	}
	else
	   playback_event = False;

	if (dispatch_event == True)
	   XtDispatchEvent(&event);
}



/************************************************************
*
*  Routine Name: jp_input_cb
*
*      Purpose:  This routine is used as the driver to playback
*		 the events out of a input stream.  First we check to
*		 see if journal playback is still active.  If not then
*		 we delete the input callback and return.  Otherwise we
*		 read the next event from jp_plyback() and dispatch it.
*
*        Input:  None
*
*       Output:  data  - the data event to be played back, NULL if no event.
*       	 time  - the id for this timeout.
*
*   Written By:  Mark Young and Danielle Argiro
*
*************************************************************/


void jp_input_cb(data, id)

XtPointer	data;
XtInputId	id;
{
	XEvent  event;
	int	elapsed;

	/*
	 *  If journal playback is turned off but we were called then abort
	 *  the playback and delete this input callback.
	 */
	if (jp_playing == False || jp_halt == True)
	{
	   XtRemoveInput(id);
	   return;
	}

	/*
	 *  Get the next event from jp_playback().  If it fails then return
	 *  otherwise dispatch the event.
	 */
	if (jp_elapsed_time(&elapsed) == False)
	   return;

	if (jp_playback(&event))
	{
	   XtDispatchEvent(&event);
	}
}
