 /*
  * Khoros: $Id: jp_record.c,v 1.2 1991/12/18 09:11:27 dkhoros Exp $
  */

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

 /*
  * $Log: jp_record.c,v $
 * Revision 1.2  1991/12/18  09:11:27  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 "forms.h"
#include "jp.h"

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	       Journal Record Routines                        <<<<
   >>>>                                                       <<<<
   >>>>                jp_record()                            <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */


/************************************************************
*
*  Routine Name: jp_record
*
*      Purpose:  This routine is used to record an event.  When
*		 we are in record mode, xvf_process_event() calls
*		 jp_record() to write the event and the window name
*		 into the record file.
*
*		 The current window and display is stored within the
*		 XEvent structure.   The current window is used to 
*		 lookup the window name, which must be written out
*		 along with the event.
*
*        Input:  event  - the event to be recorded.
*		 name   - name of the window
*		 type   - type of window (window or widget)
*		 toplevel - whether the window is a toplevel or not
*
*       Output:  Outputs the event to the record file
*
*   Written By:  Danielle Argiro, Mark Young, and Stephanie Hallett
*
*************************************************************/


jp_record(event, name, type, toplevel)

XEvent	*event;
char	*name;
int	type, toplevel;
{
	Time	 time;
	int	 elapsed;
	static   Time otime = 0;

	unsigned int mask;
	Window   window, wdummy;
	int	 x, y, rx, ry, dummy;

	XKeyEvent *xkey;
	KeySym    keysym;
	char	  temp[MaxLength], *string;



	/*
	 *  Check to see if this event is one we want to ignore.
	 */
	if (event->type == Expose || event->type == GraphicsExpose ||
	    event->type == DestroyNotify || event->type == NoExpose ||
	    event->xany.send_event == True)
	{
	   return;
	}

	/*
	 * Compute the elapsed time for recording of events.
	 */
	time = XtLastTimestampProcessed(xvf_display);
	if (otime == 0 || time == 0)
	   elapsed = 0;
	else
	   elapsed = time - otime;

	/*
	 *  Write out the name, type of event, & and event.  The type of event
	 *  is either XVF_WIDGET or XVF_WINDOW.
	 */
	window = event->xany.window;
	fprintf(record_file,"%d\n'%s' %d\n", elapsed, name, type);

#ifdef DEBUG
fprintf(stderr,"elapsed %d  old %d  new %d\n", elapsed, otime, time);
#endif

	if (event->type == ConfigureNotify && toplevel)
	{
	   XTranslateCoordinates(xvf_display, window,  XRootWindow(xvf_display,
			    xvf_screen_num), 0, 0, &x, &y, &wdummy);
	   event->xconfigure.x = x;
	   event->xconfigure.y = y;
	}
	else if (event->type == MotionNotify && event->xmotion.is_hint)
	{
	   XQueryPointer(xvf_display, event->xany.window, (Window *) &dummy, 
		 (Window *) &dummy, &rx, &ry, &x, &y, &mask);

	   event->xmotion.x = x;
	   event->xmotion.y = y;
	   event->xmotion.x_root = rx;
	   event->xmotion.y_root = ry;
	   event->xmotion.is_hint = False;
	}

	if (event->type == KeyPress || event->type == KeyRelease)
	{
	   xkey = (XKeyEvent *) &(event->xkey);
	   (void) XLookupString(xkey, temp, MaxLength, &keysym, NULL);
	}

	if (!record_event(event, record_file))
	   return;

	if (event->type == KeyPress || event->type == KeyRelease)
	{
	   string = XKeysymToString(keysym);

	   if (string == NULL)
	      fputs("\n", record_file);
	   else
	   {
	      fputs(string, record_file);
	      fputs("\n", record_file);
	   }
	}

	otime = time;
	if (record_file == stdout)
	   fflush(record_file);
}

int uncast_jp_int(value, num)

int value;
jp_int	num;
{
	char	*temp;
	int	status;
	static  char *array = NULL;
	static  int  dimension = -1;
	static  int  elem_size, new_elem_size, src_type;


	if (dimension == -1)
	{
	   dimension = 1;
	   elem_size = sizeof(int);
	   new_elem_size = sizeof(jp_int);
	   src_type = machtype(NULL);
	}

	if (array == NULL)
	{
	   if ((array = (char *) malloc(sizeof(elem_size))) == NULL)
	   {
	      fprintf(stderr,"uncast_jp_int: Out of memory!\n");
	      return(-1);
	   }
	}
	bcopy((char *) &value, (char *) array, elem_size);
	temp = array;
	status = cast_data((unsigned char **)&(array),
			       (unsigned int)dimension,
			       (unsigned int)VFF_TYP_4_BYTE,
			       (unsigned int)src_type,
			       (unsigned int)VFF_DEP_NSORDER);
	bcopy((char *) array, (char *) num, new_elem_size);

	if (elem_size > new_elem_size)
	{
	   free(array);
	   array = NULL;
	}
	return(0);
}

int uncast_jp_long(value, num)

long value;
jp_long	num;
{
	char	*temp;
	int	status;
	static  char *array = NULL;
	static  int  dimension = -1;
	static  int  elem_size, new_elem_size, src_type;


	if (dimension == -1)
	{
	   dimension = 1;
	   elem_size = sizeof(long);
	   new_elem_size = sizeof(jp_long);
	   src_type = machtype(NULL);
	}

	if (array == NULL)
	{
	   if ((array = (char *) malloc(sizeof(elem_size))) == NULL)
	   {
	      fprintf(stderr,"uncast_jp_long: Out of memory!\n");
	      return(-1);
	   }
	}
	bcopy((char *) &value, (char *) array, elem_size);
	temp = array;
	status = cast_data((unsigned char **)&(array),
			       (unsigned int)dimension,
			       (unsigned int)VFF_TYP_4_BYTE,
			       (unsigned int)src_type,
			       (unsigned int)VFF_DEP_NSORDER);
	bcopy((char *) array, (char *) num, new_elem_size);

	if (elem_size > new_elem_size)
	{
	   free(array);
	   array = NULL;
	}
	return(0);
}

int uncast_jp_short(value, num)

short value;
jp_short num;
{
	char	 *temp;
	int	 status;
	static   char *array = NULL;
	static   int  dimension = -1;
	static   int  elem_size, new_elem_size, src_type;


	if (dimension == -1)
	{
	   dimension = 1;
	   elem_size = sizeof(short);
	   new_elem_size = sizeof(jp_short);
	   src_type = machtype(NULL);
	}

	if (array == NULL)
	{
	   if ((array = (char *) malloc(sizeof(elem_size))) == NULL)
	   {
	      fprintf(stderr,"uncast_jp_short: Out of memory!\n");
	      return(-1);
	   }
	}
	bcopy((char *) &value, (char *) array, elem_size);
	temp = array;
	status = cast_data((unsigned char **)&(array),
			       (unsigned int)dimension,
			       (unsigned int)VFF_TYP_4_BYTE,
			       (unsigned int)src_type,
			       (unsigned int)VFF_DEP_NSORDER);
	bcopy((char *) array, (char *) num, new_elem_size);

	if (elem_size > new_elem_size)
	{
	   free(array);
	   array = NULL;
	}
	return(0);
}

int record_event(event, play_file)

XEvent *event;
FILE   *play_file;
{
	JPEvent jp;
	static  int xsize = sizeof(XEvent);
	static  int jpsize = sizeof(JPEvent);


	if (jpsize == xsize && machtype(NULL) == VFF_DEP_NSORDER)
	{
	   if (!fwrite((char *) event, xsize, 1, play_file))
	   {
	      fprintf(stderr, "jp_record:\n");
	      fprintf(stderr, "couldn't write event to journal playback \
file\n");
	      return(False);
	   }
	}
	else
	{
	   bzero((char *) &jp, jpsize);
	   uncast_jp_long(event->xany.type, jp.xany.type);
	   uncast_jp_long(event->xany.serial, jp.xany.serial);
	   uncast_jp_int(event->xany.send_event, jp.xany.send_event);

	   switch(event->type)
	   {
	      case KeyPress:
	      case KeyRelease:
		   uncast_jp_long(event->xkey.time, jp.xkey.time);
		   uncast_jp_int(event->xkey.x, jp.xkey.x);
		   uncast_jp_int(event->xkey.y, jp.xkey.y);
		   uncast_jp_int(event->xkey.x_root, jp.xkey.x_root);
		   uncast_jp_int(event->xkey.y_root, jp.xkey.y_root);
		   uncast_jp_int(event->xkey.state, jp.xkey.state);
		   uncast_jp_int(event->xkey.keycode, jp.xkey.keycode);
		   uncast_jp_int(event->xkey.same_screen, jp.xkey.same_screen);
		   break;

	      case ButtonPress:
	      case ButtonRelease:
		   uncast_jp_long(event->xbutton.time, jp.xbutton.time);
		   uncast_jp_int(event->xbutton.x, jp.xbutton.x);
		   uncast_jp_int(event->xbutton.y, jp.xbutton.y);
		   uncast_jp_int(event->xbutton.x_root, jp.xbutton.x_root);
		   uncast_jp_int(event->xbutton.y_root, jp.xbutton.y_root);
		   uncast_jp_int(event->xbutton.state, jp.xbutton.state);
		   uncast_jp_int(event->xbutton.button, jp.xbutton.button);
		   uncast_jp_int(event->xbutton.same_screen,
				jp.xbutton.same_screen);
		   break;

	      case MotionNotify:
		   uncast_jp_long(event->xmotion.time, jp.xmotion.time);
		   uncast_jp_int(event->xmotion.x, jp.xmotion.x);
fprintf(stderr, "x = %d, ", event->xmotion.x);
		   uncast_jp_int(event->xmotion.y, jp.xmotion.y);
fprintf(stderr, "y = %d\n", event->xmotion.y);
		   uncast_jp_int(event->xmotion.x_root, jp.xmotion.x_root);
		   uncast_jp_int(event->xmotion.y_root, jp.xmotion.y_root);
		   uncast_jp_int(event->xmotion.state, jp.xmotion.state);
		   uncast_jp_int(event->xmotion.same_screen,
				jp.xmotion.same_screen);

		   jp.xmotion.is_hint = event->xmotion.is_hint;
		   break;

	      case EnterNotify:
	      case LeaveNotify:
		   uncast_jp_long(event->xcrossing.time, jp.xcrossing.time);
		   uncast_jp_int(event->xcrossing.x, jp.xcrossing.x);
		   uncast_jp_int(event->xcrossing.y, jp.xcrossing.y);
		   uncast_jp_int(event->xcrossing.x_root, jp.xcrossing.x_root);
		   uncast_jp_int(event->xcrossing.y_root, jp.xcrossing.y_root);
		   uncast_jp_int(event->xcrossing.mode, jp.xcrossing.mode);
		   uncast_jp_int(event->xcrossing.detail, jp.xcrossing.detail);
		   uncast_jp_int(event->xcrossing.same_screen,
				jp.xcrossing.same_screen);
		   uncast_jp_int(event->xcrossing.focus, jp.xcrossing.focus);
		   uncast_jp_int(event->xcrossing.state, jp.xcrossing.state);
		   break;

	      case FocusIn:
	      case FocusOut:
		   uncast_jp_int(event->xfocus.mode, jp.xfocus.mode);
		   uncast_jp_int(event->xfocus.detail, jp.xfocus.detail);
		   break;

	      case KeymapNotify:
		   bcopy(jp.xkeymap.key_vector, event->xkeymap.key_vector, 32);
		   break;

	      case Expose:
		   uncast_jp_int(event->xexpose.x, jp.xexpose.x);
		   uncast_jp_int(event->xexpose.y, jp.xexpose.y);
		   uncast_jp_int(event->xexpose.width, jp.xexpose.width);
		   uncast_jp_int(event->xexpose.height, jp.xexpose.height);
		   uncast_jp_int(event->xexpose.count, jp.xexpose.count);
		   break;

	      case GraphicsExpose:
		   uncast_jp_int(event->xgraphicsexpose.x,
				jp.xgraphicsexpose.x);
		   uncast_jp_int(event->xgraphicsexpose.y,
				jp.xgraphicsexpose.y);
		   uncast_jp_int(event->xgraphicsexpose.width,
				jp.xgraphicsexpose.width);
		   uncast_jp_int(event->xgraphicsexpose.height,
				jp.xgraphicsexpose.height);
		   uncast_jp_int(event->xgraphicsexpose.count,
				jp.xgraphicsexpose.count);
		   uncast_jp_int(event->xgraphicsexpose.major_code,
				jp.xgraphicsexpose.major_code);
		   uncast_jp_int(event->xgraphicsexpose.minor_code,
				jp.xgraphicsexpose.minor_code);
		   break;

	      case NoExpose:
		   uncast_jp_int(event->xnoexpose.major_code,
				jp.xnoexpose.major_code);
		   uncast_jp_int(event->xnoexpose.minor_code,
				jp.xnoexpose.minor_code);
		   break;

	      case VisibilityNotify:
		   uncast_jp_int(event->xvisibility.state,
				jp.xvisibility.state);
		   break;

	      case CreateNotify:
		   uncast_jp_int(event->xcreatewindow.x, jp.xcreatewindow.x);
		   uncast_jp_int(event->xcreatewindow.y, jp.xcreatewindow.y);
		   uncast_jp_int(event->xcreatewindow.width,
				jp.xcreatewindow.width);
		   uncast_jp_int(event->xcreatewindow.height,
				jp.xcreatewindow.height);
		   uncast_jp_int(event->xcreatewindow.border_width,
				jp.xcreatewindow.border_width);
		   uncast_jp_int(event->xcreatewindow.override_redirect,
				jp.xcreatewindow.override_redirect);
		   break;

	      case DestroyNotify:
		   /*  do nothing */
		   break;

	      case UnmapNotify:
		   uncast_jp_int(event->xunmap.from_configure,
				jp.xunmap.from_configure);
		   break;

	      case MapNotify:
		   uncast_jp_int(event->xmap.override_redirect,
				jp.xmap.override_redirect);
		   break;

	      case MapRequest:
		   /*  do nothing */
		   break;

	      case ReparentNotify:
		   uncast_jp_int(event->xreparent.x, jp.xreparent.x);
		   uncast_jp_int(event->xreparent.y, jp.xreparent.y);
		   uncast_jp_int(event->xreparent.override_redirect,
				jp.xreparent.override_redirect);
		   break;

	      case ConfigureNotify:
		   uncast_jp_int(event->xconfigure.x, jp.xconfigure.x);
		   uncast_jp_int(event->xconfigure.y, jp.xconfigure.y);
		   uncast_jp_int(event->xconfigure.width, jp.xconfigure.width);
		   uncast_jp_int(event->xconfigure.height,
				jp.xconfigure.height);
		   uncast_jp_int(event->xconfigure.border_width,
				jp.xconfigure.border_width);
		   uncast_jp_int(event->xconfigure.override_redirect,
				jp.xconfigure.override_redirect);
		   break;

	      case GravityNotify:
		   uncast_jp_int(event->xgravity.x, jp.xgravity.x);
		   uncast_jp_int(event->xgravity.y, jp.xgravity.y);
		   break;

	      case ConfigureRequest:
		   fprintf(stderr,"play ConfigureRequest\n");
		   break;
	      case ResizeRequest:
		   fprintf(stderr,"play ResizeRequest\n");
		   break;
	      case CirculateNotify:
		   fprintf(stderr,"play CirculateNotify\n");
		   break;
	      case CirculateRequest:
		   fprintf(stderr,"play CirculateRequest\n");
		   break;
	      case PropertyNotify:
		   fprintf(stderr,"play PropertyNotify\n");
		   break;
	      case SelectionClear:
		   fprintf(stderr,"play SelectionClear\n");
		   break;
	      case SelectionRequest:
		   fprintf(stderr,"play SelectionRequest\n");
		   break;
	      case SelectionNotify:
		   fprintf(stderr,"play SelectionNotify\n");
		   break;
	      case ColormapNotify:
		   fprintf(stderr,"play ColormapNotify\n");
		   break;
	      case ClientMessage:
		   fprintf(stderr,"play ClientMessage\n");
		   break;
	   }

	   if (!fwrite((char *) &jp, jpsize, 1, play_file))
	   {
	      fprintf(stderr, "jp_record:\n");
	      fprintf(stderr, "couldn't write event to journal playback \
file\n");
	      return(False);
	   }

	}
	return(True);
}
