 /*
  * Khoros: $Id: refresh.c,v 1.1 1991/05/10 15:57:18 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: refresh.c,v 1.1 1991/05/10 15:57:18 khoros Exp $";
#endif

 /*
  * $Log: refresh.c,v $
 * Revision 1.1  1991/05/10  15:57:18  khoros
 * Initial revision
 *
  */ 


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


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    file name:  refresh.c
   >>>>               
   >>>>   description:  refresh mechanisms for the display window
   >>>>              
   >>>>      routines:
   >>>>			save_window
   >>>>			restore_window
   >>>>			check_window
   >>>>			resize_window
   >>>>			redraw_window
   >>>>			init_refresh
   >>>>              
   >>>> modifications:
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */

#define diag_id 19


/************************************************************
*
*  MODULE NAME:  save_window
*
*      PURPOSE:  Saves a pixmap for a given graphic window.
*		 This may later be used to restore the screen.
*
*        INPUT:  
*
*       OUTPUT:  none
*
*    CALLED BY:  plot_routines
*
*   WRITTEN BY:  Mark Young
*
*************************************************************/

save_window()
{
        Window      root;
        int         x, y, root_x, root_y;
        unsigned    int width, height, border_width, depth;

	if (gwin->pixmap == NULL)
	   return;

	XFlush(display);
	if ( !XGetGeometry(display, XtWindow(gwin->xprism_widget), &root,
			   &root_x, &root_y, &width, &height,  &border_width,
			   &depth))
	{
	   fprintf (stderr,"\nsave_window: Window does not exist.\n");
	   XFlush(display);
	   return;
	}

	if ( !XGetGeometry(display, gwin->workspace, &root, &x, &y, 
                           &width, &height,  &border_width, &depth))
	{
	   fprintf (stderr,"\nsave_window: Window does not exist.\n");
	   XFlush(display);
	   return;
	}

	/*
	 *  Make sure the portion of the window to be saved
	 *  is completely on the screen
	 */
	if ((x + root_x + width + border_width) > XDisplayWidth(display,screen))
	{
	   width = XDisplayWidth(display, screen) - root_x - x - border_width;
	}

	if (x < 0 || root_x < 0)
	{
	   x = abs(root_x) - x + border_width;
	   width = width - x - border_width;
	}
	else x = 0;

	if ((y + root_y + height+border_width) > XDisplayHeight(display,screen))
	{
	   height = XDisplayHeight(display, screen) - root_y - y - border_width;
	}

	if (y < 0 || root_y < 0)
	{
	   y = abs(root_y) - y + border_width;
	   height = height - y - border_width;
	}
	else y = 0;

	XCopyArea(display, gwin->workspace, gwin->pixmap, gc_draw, x, y,
		  width, height, x, y);
}



/************************************************************
*
*  MODULE NAME:  restore_window
*
*      PURPOSE:  restores the plot window.  If a pixmap exists
*		 then we copy the pixmap back into plot window.
*		 Otherwise it means that the backing store failed
*		 and since we have not been saving the plot to a
*		 pixmap we must redraw the window.
*
*        INPUT:  event -  the exposure event.  We use this event
*			  in association with the pixmap to indicate
*			  how much of the screen/plot window we need
*			  to restore.
*
*       OUTPUT:  none
*
*    CALLED BY:  refresh_gwin
*
*   WRITTEN BY:  Mark Young
*
*************************************************************/

restore_window (event)

XEvent *event;
{
        int         x, y;
        Window      root;
        unsigned    int width, height, border_width, depth;

	if ( !XGetGeometry(display, gwin->workspace, &root, &x, &y, 
                           &width, &height,  &border_width, &depth))
	{
	   fprintf (stderr," \nrestore_window: Window does not exist.\n");
	   XFlush(display);
	   return;
	}

	redraw_window();
/*
	if (gwin->pixmap != NULL)
	{
	   XCopyArea(display, gwin->pixmap, gwin->workspace, gc_draw,
		     event->xexpose.x, event->xexpose.y,
		     event->xexpose.width, event->xexpose.height,
		     event->xexpose.x, event->xexpose.y);
	}
	else
	{
	   redraw_window();
	}
 */
	XSync(display, 0);
}



/************************************************************
*
*  MODULE NAME:  check_window
*
*      PURPOSE:  this routine is called by the X toolkit
*		 when the graphics window has an expose
*		 or configure notify event.  We then
*		 refresh the window on expose events. If
*		 the user resized the window then we resize
*		 the plot to fit the new window size.
*
*        INPUT:  widget     - the plot window (widget).
*		 clientData - not used
*		 event	    - the event that has occured
*
*       OUTPUT:  resize or refreshes the plot, depending on the
*		 type event.
*
*    CALLED BY:  
*
*   WRITTEN BY:  Mark Young & Danielle Argiro
*
*************************************************************/


void check_window(widget, clientData, event)

Widget  widget;
caddr_t clientData;
XEvent  *event;
{
	if (gwin != NULL)  
	{
	   /*
	    *  Get and restore all exposure events.  We don't have to worry
	    *  about getting other events, since we set the mask only for
	    *  exposure events.
	    */
	   switch (event->type)
	   {
	      case Expose:
		   restore_window(event);
		   break;

	      case ConfigureNotify:
		   resize_window();
		   break;
	   }
	}
}



/************************************************************
*
*  MODULE NAME:  resize_window
*
*      PURPOSE:  this routine is called by check_window()
*		 when the graphics window has an configure
*		 notify event.  The user resized the window
*		 so we resize the plot to fit the new window
*		 size.
*
*        INPUT:  
*
*       OUTPUT:  resize the plot for the new window
*
*    CALLED BY:  check_window()
*
*   WRITTEN BY:  Mark Young
*
*************************************************************/


resize_window()
{
	int	    x, y;
        short	    win_x, win_y, win_width, win_height;
        Window      root;
        unsigned    int width, height, border_width, depth;

	/*
	 *  Check the size of the X window.  We need to get the width
	 *  height to see if it has changed.
	 */
	if ( !XGetGeometry(display, gwin->workspace, &root, &x, &y, 
                           &width, &height,  &border_width, &depth))
	{
	   fprintf (stderr,"\nresize_window: Window does not exist.\n");
	   XFlush(display);
	   return;
	}

	X3D_inquire_window (gwin->id, &win_x, &win_y, &win_width, &win_height);

	/*
	 *  Check to see if we still have the correct window dimensions
	 */
	if ((width != win_width) || (height != win_height))
	{
	   if (PLOT_TYPE_2D(gwin->plot_type))
	   {
	      X2D_set_window (gwin->id, 0, 0, width, height);
	   }
	   else
	   {
	      X3D_set_window (gwin->id, 0, 0, width, height);
	      X3D_set_window (diag_id, 0, 0, width, height);
	   }

	   if (gwin->pixmap != NULL)
	   {
	      XFreePixmap(display, gwin->pixmap);
	      init_refresh();
	   }
	   redraw_window();
	}
}



/************************************************************
*
*  MODULE NAME:  redraw_window
*
*      PURPOSE:  redraw_window refresh the plot window.  This
*		 is done by disposing of all the expose events
*		 in the event queue and then calling plot_routine
*		 to redraw the plot to the window.
*
*        INPUT:  none
*
*       OUTPUT:  refreshes the plot window
*
*    CALLED BY:  
*
*   WRITTEN BY:  Mark Young
*
*************************************************************/


redraw_window()
{
	unsigned int mask;
	XEvent event;

	/*
	 *  check to see if the gwin structure is active, if not then
	 *  return.  Note:  this really should never happen since the
	 *  plot window should only be active if the gwin is active.
	 */
	if (gwin == NULL)
	   return;

	/*
	 * this while loop is used to discard the rest of the 
	 * exposure events (if any)
	 */
	mask = ExposureMask;
	while (XCheckWindowEvent(display, gwin->workspace, mask, &event))
	{
	   XFlush(display);
	}
	plot_routine();
}



/************************************************************
*
*  MODULE NAME:  init_refresh
*
*      PURPOSE:  This routine is used to create the refresh pixmap
*		 or turn on backing store.  The routine first checks
*		 to see if backing store is available,  in which case
*		 we change the plot window attributes to use backing
*		 store always.  Otherwise we create a pixmap of the
*		 same size as the plot window.  If we fail to create
*		 the refresh pixmap, then we redraw the window upon
*		 exposure events.
*
*        INPUT:  none
*
*       OUTPUT:  none
*
*   WRITTEN BY:  Mark Young
*
*************************************************************/

init_refresh()
{
        Window    root;
        int       wx, wy, mode;
        unsigned  int width, height, border_width, depth;
	unsigned  long mask;
	XSetWindowAttributes xwa;


	gwin->pixmap = NULL;
	mode = XDoesBackingStore(def_scr);

	if (mode != NotUseful)
	{
	   mask = CWBackingStore;
	   xwa.backing_store = mode;
	   XChangeWindowAttributes(display, gwin->workspace, mask, &xwa);
	}
	else
	{
           if ( !XGetGeometry(display, gwin->workspace, &root, &wx, &wy,
			      &width, &height, &border_width, &depth))
           {
               xvf_error_wait("Plot Window doesn't exist.","init_refresh",NULL);
               return;
	   }

	   gwin->pixmap = XCreatePixmap(display, gwin->workspace, width,
					height, depth);
	   if ( !XGetGeometry(display, gwin->pixmap, &root, &wx, &wy, &width,
			      &height, &border_width, &depth))
	   {
	      gwin->pixmap = NULL;
	   }
	}
}
