#include "gpr.h"

/*  
  I took the original code of Dan Lovinger, Dec, 1990, CMU  and the code
  of Tood W Mummert, Dec 1990, CMU and hacked it in order to get it work
  with the game strek written by Justin S.  Revenaugh Jul, 1987, MIT.

  I also added some comments about the original GPR routines so that any
  user of  this package might  get a  small inside in what this routines
  are meant to do. This package tries to emulate the APOLLO GPR (Graphic
  Primitive   routines) routines that are part   of their OS (Domain OS)
  (AEGIS) version 9.5  or 9.7.   I've included  the include   files  for
  reference purposes,  so that anyone  trying  to  build a proper  gpr2X
  library can see how the datatypes are defined.
*/





/* ================================================================== */
/*                                                                    */
/* void cal_$decode_local_time (decoded_clock)                        */
/*                                                                    */
/* output:                                                            */
/* cal_$timedate_rec_t  decoded_clock;                                */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Returns the local time in integer format ("year, month, day, hour, */
/*                                            minute, second").       */
/*                                                                    */
/* ================================================================== */

void  caldecodelocaltime_ (array)

short int   array[6];

{
   time_t      clock;
   struct tm   *lt;



   (void) time(&clock);
   lt = localtime(&clock);
   array[0] = lt->tm_year + 1900;
   array[1] = lt->tm_mon + 1;
   array[2] = lt->tm_mday;
   array[3] = lt->tm_hour;
   array[4] = lt->tm_min;
   array[5] = lt->tm_sec;
} /* caldecodelocaltime_ */





/* ================================================================== */
/*                                                                    */
/* void cal_$float_clock (clock, float_seconds)                       */
/*                                                                    */
/* input:                                                             */
/* time_$clock_t  clock;                                              */
/*                                                                    */
/* output:                                                            */
/* double         float_seconds;   # this is 8 byte long              */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Converts a system clock representation to the equivilent number of */
/* seconds in double-precision floating-point format. Unlike          */
/* cal_$clock_to_sec this routine does not truncate the fractional    */
/* portion of the conversion.                                         */
/*                                                                    */
/* ================================================================== */

void calfloatclock_ (clock, floatclock)

short int   clock[3];
double      *floatclock;

{
   *floatclock = (double) (clock[0] * 65536) +
                 (double) (clock[1]) +
                 ((double) (clock [2]) / (1000000/4));

/*
   *floatclock = ((((clock[0] * 65536) + clock[1]) * 65536) + clock[3]) 
                 / 250000;
*/
} /* calfloatclock_ */





/* ================================================================== */
/*                                                                    */
/* void cal_$get_local_time (clock)                                   */
/*                                                                    */
/* output:                                                            */
/* time_$clock_t  clock;                                              */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Returns the current local time in system clock representation.     */
/* This is the number of 4-microsecond periods that have elapsed      */
/* since January 1, 1980, 00:00.                                      */
/*                                                                    */
/* ================================================================== */

void calgetlocaltime_ (clock)

short int   clock[3];

{
   struct timeval tv;
   long           tmp_micro;



   gettimeofday(&tv, 0);

   clock[0] = tv.tv_sec >> 16;
   clock[1] = tv.tv_sec & 0xffff;
   clock[2] = tv.tv_usec/4;

/*
   tmp_micro = tv.tv_sec * 250000 + tv.tv_usec/4;

   clock[2] = tmp_micro & 0x000000ff;
   clock[1] = (tmp_micro & 0x0000ff00) >> 16;
   clock[0] = (tmp_micro & 0x00ff0000) >> 32;
*/
} /* calgetlocaltime_ */





/* ================================================================== */
/*                                                                    */
/* void cal_$sec_to_clock (seconds, clock)                            */
/*                                                                    */
/* input:                                                             */
/* int  seconds;     # 4-byte integer                                 */
/*                                                                    */
/* output:                                                            */
/* time_$clock_t  clock;                                              */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Converts seconds to system clock units. No overflow detection is   */
/* performed.                                                         */
/*                                                                    */
/* ================================================================== */

void calsectoclock_ (seconds, clock)

int         *seconds;
short int   clock[3];

{
   long tmp;
   long tmp_micro;



   tmp = (long) *seconds;

   clock[0] = tmp >> 16;
   clock[1] = tmp & 0xffff;
   clock[2] = 0;
/*
   tmp_micro = *seconds * 250000;

   clock[2] = tmp_micro & 0x000000ff;
   clock[1] = (tmp_micro & 0x0000ff00) >> 16;
   clock[0] = (tmp_micro & 0x00ff0000) >> 32;
*/
} /* calsectoclock_ */





/* ================================================================== */
/*                                                                    */
/* Where does this come from?                                         */
/*                                                                    */
/* ================================================================== */

void getusername_ (name, namlen)

char  *name;
long  *namlen;

{
   struct passwd        *pwd;
   char                 *tname;
   int                  i;
   extern char          *getenv();
   extern struct passwd *getpwuid();



   if ((pwd = getpwuid(getuid())) != NULL)
   {
      tname = pwd->pw_name;
   }
   else
   if ((tname = getenv("USER")) == NULL &&
       (tname = getenv("LOGNAME")) == NULL)
   {
      tname = "intruder\0";
   }
   (void) strncpy(name, tname, 8);
   for (i=strlen(tname);i<10;i++)
      name[i] = ' ';
   name[10] = '\0';
} /* getusername_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$bit_blt (source_bitmap_desc, source_window,              */
/*                    source_plane, dest_origin, dest_plane, status)  */
/*                                                                    */
/* input:                                                             */
/* gpr_$bitmap_desc_t  source_bitmap_desc;                            */
/* gpr_$window_t       source_window;                                 */
/* gpr_$plane_t        source_plane;                                  */
/* gpr_$position_t     dest_origin;                                   */
/* gpr_$plane_t        dest_plane;                                    */
/*                                                                    */
/* output:                                                            */
/* status_$t           status;                                        */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Performs a bit block transfer from a single plane of any bitmap to */
/* a single plane of the current bitmap. source_window is a           */
/* rectangular section of the bitmap from which to transfer pixels.   */
/* source_plane is the identifier of the single plane of the source   */
/* bitmap to move. dest_origin is the start position (top left        */
/* coordinate position) of the destination rectangle. status is the   */
/* completion status.                                                 */
/* Both the source and destination bitmaps can be in either display   */
/* memory or main memory. If the source bitmap is a Display Manager   */
/* frame, the only allowed raster op codes are 0, 5, A, and F. These  */
/* are the raster operations in which the source plays no role. If a  */
/* rectangle is transferred by a BLT to a Display Manager frame and   */
/* the frame is refreshed for any reason, the BLT is re-executed.     */
/* Therefore, if the information in the source bitmap has changed,    */
/* the appearance of the frame changes accordingly.                   */
/*                                                                    */
/* ================================================================== */

void gprbitblt_ (bitmap, window, plane, dsto, dstp, status)

bitmap_desc_t  *bitmap;
short          window[4];
plane_t        *plane;
short          dsto[2];
plane_t        *dstp;
long           *status;

{  
   if (lop==6)
      XFillRectangle(d, w, EraseGC, (int)dsto[0], (int)dsto[1],
                     (int)window[2], (int) window[3]);
   else
   {
      XCopyArea (d, w, w, FillGC,
                 (int)window[0],(int) window[1],
                 (int)window[2],(int) window[3],
                 (int)dsto[0], (int)dsto[1]);
   }
   *status = 0;
} /* gprbitblt_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$circle (center, radius, status)                          */
/*                                                                    */
/* input:                                                             */
/* gpr_$position_t  center;                                           */
/* short            radius;   # 2-byte integer in 1-32767             */
/*                                                                    */
/* output:                                                            */
/* status_$t        status;                                           */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Draws a circle with the specified radius around the specified      */
/* center point. gpr_$circle does not change the current position.    */
/* When you have clipping enabled, you can specify coordinates        */
/* outside the bitmap limits. With clipping disabled, specifying      */
/* coordinates outside the bitmap limits results in an error.         */
/*                                                                    */
/* ================================================================== */

void gprcircle_ (center, radius, status)

short int   center[2];
short int   *radius;
long        *status;

{
   long           size = *radius;
   int            x = center[0] - size;
   int            y = center[1] - size;
   unsigned int   width = size+size;
   unsigned int   height = size+size;
   long           moon = 1;



    if (moon) /* Release 3 server paint circles awfully slow */
       if ((strncmp(ServerVendor(d), "MIT", 3) == 0) &&
           VendorRelease(d) < 4)
          return;

   XDrawArc (d, w, DrawGC, x, y, width, height, (int)0, (int)360*64);
} /* gprcircle_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$circle_filled (center, radius, status)                   */
/*                                                                    */
/* input:                                                             */
/* gpr_$position_t  center;                                           */
/* short            radius;   # 2-byte integer in 1-32767             */
/*                                                                    */
/* output:                                                            */
/* status_$t        status;                                           */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Draws and fills a circle with the specified radius around the      */
/* specified center point. gpr_$circle_filled does not change the     */
/* current position. When you have clipping enabled, you can specify  */
/* coordinates outside the bitmap limits. With clipping disabled,     */
/* specifying coordinates outside the bitmap limits results in an     */
/* error.                                                             */
/*                                                                    */
/* ================================================================== */

void gprcirclefilled_ (center, radius, status)

short int   center[2];
short int   *radius;
long        *status;

{
   long           size = *radius;
   int            x = center[0] - size;
   int            y = center[1] - size;
   unsigned int   width = size+size;
   unsigned int   height = size+size;

   XFillArc (d, w, FillGC, x, y, width, height, (int)360*64, (int)-360*64);
} /* gprcirclefilled_ */





/* ================================================================== */
/*                                                                    */
/* Boolean gpr_$cond_event_wait (event_type, event_data, position,    */
/*                               status)                              */
/*                                                                    */
/* return value:                                                      */
/* Boolean gpr_$cond_event_wait( ... )                                */
/*                                                                    */
/* output:                                                            */
/* gpr_$event_t  event_type;                                          */
/* char          *event_data;                                         */
/* gpr_$position_t  position;                                         */
/* status_$t     status;                                              */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Returns information about the occurrence of any event without      */
/* entering a wait state. The boolean return value indicates whether  */
/* or not the window is obscured; a false value means that the window */
/* is obscured. This value is always true unless the program has      */
/* called gpr_$set_obscured_opt(...) and specified an option of       */
/* gpr_$ok_if_obs. The event_type is the type of event that occurred. */
/* It is one of the following: gpr_$keystroke (input from a keyboard) */
/* gpr_$buttons (Input from mouse or bitpad puck buttons)             */
/* gpr_$locator (input from a touchpad or mouse) gpr_$entered_window  */
/* (cursor has entered window) gpr_$left_window (cursor has left      */
/* window) gpr_$locator_stop (input from a locator has stopped) and   */
/* gpr_$no event (no event has occurred). event_data is the keystroke */
/* or button character associated with the event, or the character    */
/* that identifies the window associated with an entered window event.*/
/* This parameter is not modified for other events. position is the   */
/* position on the screen or within the window at which graphics      */
/* input occurred. status is the completion status.                   */
/*                                                                    */
/* When called this routine returns immediately and reports           */
/* information about any event that has occured. The routine allows   */
/* the program to obtain information about an event without having to */
/* suspend all of its activities. Unless locator data has been        */
/* processed since the last event was reported, position will be the  */
/* last position given to gpr_$set_cursor_position(...). If locator   */
/* data is received during this call, and gpr_$locator events are not */
/* enabled, the GPR software will display the arrow cursor and will   */
/* set the keyboard cursor position. Although this call never waits   */
/* it may release the display if it receives an unenabled event that  */
/* needs to be handled by the Display Manager. The input routines     */
/* report button events as ASCII characters. "Down" transitions range */
/* from "a" to "d"; "up" transitions range from "A" to "D". The three */
/* mouse keys start with (a/A) on the leftside. As with keystroke     */
/* events, button events can be selectively enabled by specifying a   */
/* button keyset.                                                     */
/*                                                                    */
/* ================================================================== */

int gprcondeventwait_ (event, key, posn, status)

short       *event;
char        *key;
position_t  *posn;
long        *status;

{
   static unsigned long flag[16] = {0, 0, 0, 0};
   XEvent               ev;
   int                  paused = 0;
   char                 keystr;
   int                  early_return;
   XWindowAttributes    wattr;
   Window               dummywin;
   int                  rx, ry;



   *event=0;
   *key=0;

   if (was_placed)
   {
      XSync(d, False);
      XSelectInput(d,w, ExposureMask|PointerMotionMask|
                        ButtonPressMask|ButtonReleaseMask|
                        KeyPressMask| StructureNotifyMask );
      was_placed = False;
   }

   XFlush(d);
   if (XPending(d))
      while (XPending(d) || paused)
      {
         if (!paused)
            XNextEvent(d, &ev);
         else
            XWindowEvent(d,w,KeyPressMask|StructureNotifyMask,&ev);
      }
   else
      return 0;

   switch(ev.type)
   {
/*
      case Expose:
         if (((XExposeEvent*) &ev)->count)
            break;

         XSelectInput(d, w, StructureNotifyMask);
         XSync(d, True);

	 XMoveResizeWindow(d, w, 0, 0, wid+1, hei+1);  
	 XWindowEvent(d, w, StructureNotifyMask, &ev);

	 XGetWindowAttributes(d, w, &wattr);
	 XTranslateCoordinates(d, w, wattr.root, 0, 0,
			       &rx, &ry, &dummywin);

	 XMoveResizeWindow(d, w, -rx, -ry, wid, hei);  
	 XWindowEvent(d, w, StructureNotifyMask, &ev);

	 XSelectInput(d, w, NoEventMask);
	 XSync(d, False);
	 was_placed = True;

	 mouse_posn.x = ev.xexpose.x;
	 mouse_posn.y = ev.xexpose.y;
	 *posn = mouse_posn;
	 return 1;

      case UnmapNotify:
	 paused = 1;
         return 0;

      case MapNotify:
	 paused = 0;
	 return 0;

      case MotionNotify:
	 mouse_posn.x = ev.xmotion.x;
	 mouse_posn.y = ev.xmotion.y;
	 return 0;

      case ButtonPress:
	 mouse_posn.x = ev.xbutton.x;
	 mouse_posn.y = ev.xbutton.y;	    
	 *key = ev.xbutton.button + 'a' - 1;
	 flag[ev.xbutton.button]=1;
	 *posn = mouse_posn;
	 return 1;

      case ButtonRelease:
	 mouse_posn.x = ev.xbutton.x;
	 mouse_posn.y = ev.xbutton.y;
	 *key = ev.xbutton.button + 'A' - 1;
	 flag[ev.xbutton.button]=0;
	 *posn = mouse_posn;
	 return 1;
*/

      case KeyPress:
      {
	 early_return = False;

	 mouse_posn.x = ev.xmotion.x;
	 mouse_posn.y = ev.xmotion.y;
         *posn = mouse_posn;

	 XLookupString(&ev.xkey,&keystr,1,(KeySym *) 0,
		       (XComposeStatus *) 0);
/*
         if (XLookupString(&ev.xkey,&keystr,1,(KeySym *) 0,
                           (XComposeStatus *) 0) == 1)
            switch (keystr)
	    {
	       case 'p': case 'P':
	          paused = 1;
		  break;
               case 'c': case 'C':
	          paused = 0;
		  break;
               case 'i': case 'I': case ' ':
                  XIconifyWindow(d, w, d->default_screen);
		  break;
               case 'r': case 'R':
                  XSelectInput(d, w, StructureNotifyMask);
		  XSync(d, True);
		  XMoveResizeWindow(d, w, 0, 0, wid+1, hei+1);  
		  XWindowEvent(d, w, StructureNotifyMask, &ev);

		  XGetWindowAttributes(d, w, &wattr);
		  XTranslateCoordinates(d, w, wattr.root, 0, 0,
		                        &rx, &ry, &dummywin);

		  XMoveResizeWindow(d, w, -rx, -ry, wid, hei);  
		  XWindowEvent(d, w, StructureNotifyMask, &ev);

		  XSelectInput(d, w, NoEventMask);
		  XSync(d, False);
		  was_placed = True;

		  *key = 'R';
		  early_return = True;
		  break;
               case '\003': case 'q': case 'Q':
                  *key = 'Q';
		  early_return = True;
		  break;
               default:
                  break;
            }
         if (early_return)
	 {
            mouse_posn.x = ev.xkey.x;
	    mouse_posn.y = ev.xkey.y;
	    *posn = mouse_posn;
	    return 1;
         }
*/
         *event = 1;
	 *key = keystr;
	 return 1;
      }  
   }
   *posn = mouse_posn;
   return 0;
} /* gprcondeventwait_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$enable_input (event_type, key_set, status)               */
/*                                                                    */
/* input:                                                             */
/* gpr_$event_t  event_type;                                          */
/* gpr_$keyset_t key_set;                                             */
/*                                                                    */
/* output:                                                            */
/* status_$t     status;                                              */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Enables an event type and a selected set of keys.                  */
/* For event_type look at gpr_$cond_event_wait(...). key_set is a set */
/* of specifically enabled characters when the event class is in      */
/* gpr_$keyset_t format. In Pascal (AEGIS, e.g. DomainOS was written  */
/* in pascal!), this is a set of characters. In Fortran and C this    */
/* can be implemented as an eight element array of 4-byte integers.   */
/* This parameter is specified for event types of gpr_$keystroke and  */
/* gpr_$butons. status is, as always, the completion status.          */
/* This routine will release and reacquire the display. This routine  */
/* specifies the type of event and event input for which              */
/* gpr_$event_wait(...) is to wait. This routine applies to the       */
/* current bitmap. However, enabled input events are stored in        */
/* attribute blocks (not with bitmaps) in much the same way as        */
/* attributes are. When a program chnages attribute blocks for a      */
/* bitmap during a graphics session, the input events you enabled are */
/* lost unless you enable those events for the new attribute block.   */
/* Programsmust call this routine once for each event type to be      */
/* enabled. No event types are enabled by default. The keyset must    */
/* correspond to the specified event type. For example, use           */
/* ['#'...'~'] (in Pascal) to enable all normal printing graphics.    */
/* Use [chr(0)..chrchr(127)] to enable the entire ASCII character set.*/
/* Except in borrow-display mode, it is a good idea to leave at least */
/* the CMD and NEXT_WINDOW keys out of the keyset so that the user    */
/* can access other Display Manager windows. The insert files         */
/* /sys/ins/kbd.ins.[c,pas,ftn] contain definitions for the non-ASCII */
/* keyboard keys in the range 128-255. Events and keyset data not     */
/* enabled with this routine will be handled by the Display Manager   */
/* in frame or direct mode and discarded in borrow-display mode. When */
/* locator events are disabled, the GPR software will display the     */
/* arrow cursor and will set the keyboard cursor position when        */
/* locator data is received.                                          */
/*                                                                    */
/* ================================================================== */

void gprenableinput_ (event_type, key_set, status)

short *event_type;
long  key_set[8];
long  *status;

{
   /* XXX noop */
} /* gprenableinput */





/* ================================================================== */
/*                                                                    */
/* void gpr_$init (op_mode, unit, size, hi_plane_id,                  */
/*                 init_bitmap_desc, status)                          */
/*                                                                    */
/* input:                                                             */
/* gpr_$display_mode_t  op_mode;                                      */
/* stream_$id_t         unit;                                         */
/* gpr_$offset_t        size;                                         */
/* gpr_$plane_t         hi_plane_id;                                  */
/*                                                                    */
/* output:                                                            */
/* gpr_$bitmap_desc_t   init_bitmap_desc;                             */
/* status_$t            status;                                       */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Initializes the graphics primitive package.                        */
/* op_mode is one of the following: gpr_$borrow (program borrows the  */
/* full screen and the keyboard from the Display Manager and uses the */
/* display driver directly through GPR software) gpr_$borrow_nc (same */
/* as gpr_$borrow except that all the pixels are not set to zero      */
/* [screen is not cleared]) gpr_$direct (program borrows a window     */
/* from the Display Manager instead of borrowing the whol display)    */
/* gpr_$frame (program executes within a frame of a Display Manager   */
/* Pad) gpr_$no_display (GPR allocates a bitmap inmain memory. No     */
/* graphics is displayed on the screen). unit has three possible      */
/* meanings, as follows: 1.) the display unit, if in gpr_$borrow or   */
/* gpr_$borrow_nc. The only valid display unit number is 1. 2.) The   */
/* stream identifier for the pad, if the graphics routines are to     */
/* operate in frame or direct mode. 3.) Any value, if in              */
/* gpr_$no_display mode. size is the size of the initial bitmap (and  */
/* the size of the frame, in frame mode). Possible values are:        */
/*                                      x            y                */
/* Borrow-display or direct mode:  1 to 1024    1 to 1024             */
/* (limits are reduced to display                                     */
/*  or window size if necessary)                                      */
/* Display Manager Frame:          1 to 32767   1 to 32767            */
/* Main Memory Bitmap:             1 to 8192    1 to 8192             */
/* hi_plane_id is the identifier of the bitmap's highest plane.       */
/* Possible values are: 0 for monochromatic displays, 0-3 for         */
/* colordisplays in two-board colfiguration, 0-7 for color displays   */
/* in three-board configuration, 0-7 for main memory bitmaps.         */
/* init_bitmap_desc is the descriptor of the initial bitmap that      */
/* uniquely identifies the bitmap. status is the completion status.   */
/*                                                                    */
/* To use multiple windows, you must call gpr_$init for each window.  */
/* If a program executes in borrow-display mode or direct-mode, the   */
/* size of the initial bitmap can be equal to or smaller than the     */
/* display. If the program executes in a frame of a Display Manager   */
/* Pad, "size" specifies the size of both the frame and the initial   */
/* bitmap. (In frame mode, the frame and the bitmap must be the same  */
/* size.) If the program does not use the display, gpr_$init(...)     */
/* creates a bitmap in main memory of the given size. To use imaging  */
/* formats, aprogram must be initialized in borrow display mode.      */
/*                                                                    */
/* ================================================================== */

void gprinit_ (flag, xx, size, yy, bitmapdesc, status)

float       *flag;
int         *xx;
short int   size[2];
int         *yy;
long int    *bitmapdesc;
long        *status;

{
   XEvent            ev;
   XWindowAttributes wattr;
   Window            dummywin;
   int               rx, ry;



   XSelectInput(d, w, ExposureMask|PointerMotionMask|
                      ButtonPressMask|ButtonReleaseMask|KeyPressMask);
/*
   XMapWindow(d, w);
   XWindowEvent(d, w, ExposureMask, &ev);
#if 0
   while (XGrabPointer (d, w, False,
		        PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
		        GrabModeAsync,
		        GrabModeAsync,
		        w, None, ev.xmotion.time) != GrabSuccess)
   {
      printf("couldn't grab cursor.. waiting 1 second..\n");
      sleep(1);
   }
   printf("cursor grabbed..\n");
#endif
   XGrabServer(d);
*/

   XMapRaised(d, w);
   do
      XWindowEvent(d, w, ExposureMask, &ev);
   while(((XExposeEvent*) &ev)->count);

   XSelectInput(d, w, StructureNotifyMask);
   XSync(d, True);               /*  get rid of anything outstanding */

  /* i cheat and change width and height by 1....this almost guarantees
     i'll generate a ConfigureRequest event.
   */
   XMoveResizeWindow(d, w, 0, 0, wid+1, hei+1);  
   XWindowEvent(d, w, StructureNotifyMask, &ev);

   XGetWindowAttributes(d, w, &wattr);           /* check to see where the */
   XTranslateCoordinates(d, w, wattr.root, 0, 0, /* wm actually placed it */
			 &rx, &ry, &dummywin);

   XMoveResizeWindow(d, w, -rx, -ry, wid, hei);  
   XWindowEvent(d, w, StructureNotifyMask, &ev);

   XSelectInput(d, w, NoEventMask);
   XSync(d, False);
   was_placed = True;

   *status = 0;		/* XXX most args */
} /* gprinit_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$inq_config (config, status)                              */
/*                                                                    */
/* output:                                                            */
/* gpr_$display_config_t  config;                                     */
/* status_$t              status;                                     */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Returns the current display configuration.                         */
/* config can be one of the predifined values: gpr_$bw_800x1024,      */
/* gpr_$bw_1280x1024, gpr_$color_1024x1024x8, gpr_$color_1280x1024x8, */
/* ... status is the completion status. gpr_$inq_config(...) can be   */
/* used before gpr_$init(...). This is useful to determine the number */
/* of possible planes in bitmaps on color displays before initializing*/
/* GPR.                                                               */
/*                                                                    */
/* ================================================================== */

void gprinqconfig_ (config, status)

long  *config;
long  *status;

{
   XSetWindowAttributes attr;
   XColor               color;
   Cursor               c;
   Font                 f;
   XGCValues            xgcv;
   unsigned long        fcolor;
   unsigned long        bcolor;
   Colormap             cmap;
   XColor               exact;
   XColor               closest;
   XWMHints             wmhints;
   int                  i;
   int                  ncolors  = MAX_COLORS;
   /* These colors chosen at random */
   static char          *ColorName[]   =  {"Black",
                                           "White",
                                           "Red",
                                           "Blue",
                                           "Yellow",
                                           "Green",
                                           "Orange",
                                           "Sea Green",
                                           "Coral",
                                           "Maroon",
                                           "Orange Red",
                                           "Sky Blue",
                                           "Violet Red",
                                           "Brown",
                                           "Lime Green",
                                           "Gold"};



   if (d == 0)
      d = XOpenDisplay (0);
   if (d == 0)
   {
      printf("can't open display! bye.\n");
      exit(1);
   }

   colortrans[1] = fcolor = WhitePixelOfScreen(DefaultScreenOfDisplay(d));
   colortrans[0] = bcolor = BlackPixelOfScreen(DefaultScreenOfDisplay(d));

   *config = DisplayPlanes(d,0);
   if (*config != 1)
   {
      cmap = XDefaultColormap(d,0);
      for (i = 0; i < MAX_COLORS; i++)
      {
         if (!XParseColor(d, cmap, ColorName[i], &exact))
         {
	    fprintf(stderr,"XParseColor: color name %s \
		            is not in database\n", ColorName[i]);
	    exit(1);
	 }
	 if (!XAllocColor(d,cmap, &exact))
         {
	    fprintf(stderr, "XAllocColor: Couldn't allocate %s\n",
		    ColorName[i]);
	    exit(1);
	 }
	 colortrans[i] = exact.pixel;
      }
   }
   wid = WidthOfScreen(DefaultScreenOfDisplay(d))-4;
   hei = HeightOfScreen(DefaultScreenOfDisplay(d))-4;
   w = XCreateSimpleWindow (d, DefaultRootWindow(d),
			    0, 0,
			    wid,
		            hei,
		            2,
			    fcolor,
			    bcolor);

   /* Tell the WM that we want input... */
   wmhints.input = True;
   wmhints.flags = InputHint;
   XSetWMHints(d, w, &wmhints);

   /* Name and raise the window */
   XStoreName(d, w,"XStrek");
   XSetIconName(d, w, "XStrek");

/*
   attr.override_redirect = True;
   XChangeWindowAttributes (d, w, CWOverrideRedirect, &attr);
*/
   xgcv.background = bcolor;
   xgcv.foreground = fcolor;
   FillGC = XCreateGC(d, w, GCForeground | GCBackground, &xgcv);
   xgcv.background = bcolor;
   xgcv.foreground = bcolor;
   EraseGC = XCreateGC(d, w, GCForeground | GCBackground, &xgcv);
   xgcv.background = bcolor;
   xgcv.foreground = fcolor;
   DrawGC = XCreateGC(d, w, GCForeground | GCBackground, &xgcv);
   TextGC = XCreateGC(d, w, GCForeground | GCBackground, &xgcv);
   f = XLoadFont (d, "fixed");
   c = XCreateGlyphCursor (d, f, f, ' ', ' ',
			   &color, &color);
   XDefineCursor(d, w, c);
   XSetGraphicsExposures (d, FillGC, False);
   XSetGraphicsExposures (d, DrawGC, False);
   XSetGraphicsExposures (d, TextGC, False);    
   *status = 0;
} /* gprinqconfig_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$inq_cursor (curs_pat, curs_raster_op, active, position,  */
/*                       origin, status)                              */
/*                                                                    */
/* output:                                                            */
/* gpr_$bitmap_desc_t      cursor_pat;                                */
/* gpr_$raster_op_array_t  cursor_raster_op;                          */
/* Boolean                 active;                                    */
/* gpr_$position_t         position;                                  */
/* gpr_$position_t         origin;                                    */
/* status_$t               status;                                    */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Returns information about the cursor.                              */
/* cursor_pat is ithe identifier of the cursor pattern bitmap.        */
/* cursor_raster_op is is operation code. The default value is three. */
/* (The operation assigns all source values to the new destination.)  */
/* active is a boolean which indicateswhether the cursor is displayed.*/
/* True when displayed. position is the current position of the       */
/* cursor on the screen. origin is the pixel curently set as the      */
/* cursor origin. status is the completion status.                    */
/*                                                                    */
/* In borrow-display mode the position is the absolute position on    */
/* the screen. In direct or frame mode position is relative to the    */
/* top left corner of the frame.                                      */
/*                                                                    */
/* ================================================================== */

void gprinqcursor_ (cursor, ops, active, posn, origin, status)

long        *active;
position_t  *posn;
position_t  *origin;
long        *status;

{
   *posn = mouse_posn;
   *status = 0;
} /* gprinqcursor_ */






/* ================================================================== */
/*                                                                    */
/* void gpr_$line (x, y, status)                                      */
/*                                                                    */
/* input:                                                             */
/* gpr_$coordinate_t  x;                                              */
/* gpr_$coordinate_t  y;                                              */
/*                                                                    */
/* output:                                                            */
/* status_$t          status;                                         */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Draws a line from the current position to the end point supplied.  */
/* The current position is updated to the end point. When you have    */
/* cliping enabled, you can specify coordinates outside the bitmap    */
/* limits. With clipping disabled, specifying coordinates outside the */
/* bitmap limits results in an error. To set a new position without   */
/* drawing a line, use gpr_$move(...).                                */
/*                                                                    */
/* ================================================================== */

void gprline_ (x, y, status)

short *x;
short *y;
long  *status;

{

   *status = 0;
   XDrawLine(d, w, DrawGC, curpoint.x, curpoint.y, (int) *x, (int) *y );
   curpoint.x = *x;
   curpoint.y = *y;
} /* gprline_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$load_font_file (pathname, pathname_length, font_id,      */
/*                           status)                                  */
/*                                                                    */
/* input:                                                             */
/* name_$pname_t  pathname;                                           */
/* short          pathname_length;       # 2-byte integer             */
/*                                                                    */
/* output:                                                            */
/* short          font_id;               # 2-byte integer             */
/* status_$t      status;                                             */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Loads a font from a file into the display's font storage area.     */
/* Use the font_id returned as input for gpr_$set_text_font(...)      */
/* To unload fonts use gpr_$unload_font_file(...)                     */
/*                                                                    */
/* ================================================================== */

void gprloadfontfile_ (path, pnlen, fontid, status)

char  *path;
long  *pnlen;
long  *fontid;
long  *status;

{
   int i;



   for (i=0; fontmap[i].gprname; i++)
   {
      if (strcmp(path, fontmap[i].gprname) == 0)
      {
         *fontid = XLoadFont (d, fontmap[i].xname);
	 return;
      }
   }
   *fontid = XLoadFont(d, "fixed");
} /* gprloadfontfile_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$move (x, y, status)                                      */
/*                                                                    */
/* input:                                                             */
/* gpr_$coordinate_t  x;                                              */
/* gpr_$coordinate_t  y;                                              */
/*                                                                    */
/* output:                                                            */
/* status_$t          status;                                         */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Sets the current position to the given position. When you have     */
/* cliping enabled, you can specify coordinates outside the bitmap    */
/* limits. With clipping disabled, specifying coordinates outside the */
/* bitmap limits results in an error.                                 */
/*                                                                    */
/* ================================================================== */

void gprmove_ (x, y, status)

short int   *x;
short int   *y;
long        *status;

{
   curpoint.x = *x;
   if (curpoint.x == 0)
      curpoint.x = *(long *)x;
   curpoint.y = *y;
   if (curpoint.y == 0)
      curpoint.y = *(long *)y;
   *status = 0;
} /* gprmove_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$multiline (x, y, npositions, status)                     */
/*                                                                    */
/* input:                                                             */
/* gpr_$coordinate_array_t  x;                                        */
/* gpr_$coordinate_array_t  y;                                        */
/* short                    npositions;      # 2-byte int in 1-32767  */
/*                                                                    */
/* output:                                                            */
/* status_$t          status;                                         */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Draws a series of disconnected lines. It moves alternately to a    */
/* new position and draws lines: it moves to the first given position */
/* then draws a line from the first to the second given position,     */
/* updates the current position, moves to the third, etc. After all   */
/* that the last point becomes the current position. When you have    */
/* cliping enabled, you can specify coordinates outside the bitmap    */
/* limits. With clipping disabled, specifying coordinates outside the */
/* bitmap limits results in an error.                                 */
/*                                                                    */
/* ================================================================== */

void gprmultiline_ (x, y, number, status)

short *x;
short *y;
int   *number;
long  *status;

{
   int      i;
   int      count;
   XSegment *segments;



   *status = 0;
   count = *number;
   /*
    * gross hack.  we may be passed an integer*2 or an integer*4;
    * neither is likely to be greater than 2<<16
    */
   if (count == 0)
      count = *((long *)number);

   if (count & 1)
      printf("odd multiline??\n");
   /* not exactly what you want.. */
   segments = (XSegment *)malloc (sizeof(XSegment) * (count/2));
   for (i=0; i<count; i+= 2)
   {
      segments[i/2].x1 = x[i];
      segments[i/2].y1 = y[i];
      segments[i/2].x2 = x[i+1];
      segments[i/2].y2 = y[i+1];
   }
   curpoint.x = segments[count/2].x2;
   curpoint.y = segments[count/2].y2;    
   XDrawSegments (d, w, DrawGC, segments, count/2);
   free(segments);
} /* gprmultiline_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$polyline (x, y, npositions, status)                      */
/*                                                                    */
/* input:                                                             */
/* gpr_$coordinate_array_t  x;                                        */
/* gpr_$coordinate_array_t  y;                                        */
/* short                    npositions;      # 2-byte int in 1-32767  */
/*                                                                    */
/* output:                                                            */
/* status_$t          status;                                         */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Draws a series of connected lines. Drawing begins at the current   */
/* position, draws to the first given coordinat position, then sets   */
/* the current position to the first given position. This is repeated */
/* for all given positions. When you have                             */
/* cliping enabled, you can specify coordinates outside the bitmap    */
/* limits. With clipping disabled, specifying coordinates outside the */
/* bitmap limits results in an error.                                 */
/*                                                                    */
/* ================================================================== */

void gprpolyline_ (x, y, number, status)

short *x;
short *y;
int   *number;
long  *status;

{
   int      i;
   int      count;
   XPoint   *points;



   *status = 0;
   count = *number;

   /*
    * gross hack.  we may be passed an integer*2 or an integer*4;
    * neither is likely to be greater than 2<<16
    */
   if (count == 0)
      count = *((long *)number);
	
   points = (XPoint *) malloc (sizeof(XPoint) * (count + 1));
   points[0] = curpoint;
   for (i=0; i<count; i++)
   {
      points[i+1].x = x[i];
      points[i+1].y = y[i];
   }
   curpoint = points[count];
   XDrawLines(d, w, DrawGC, points, count+1, CoordModeOrigin);
   free(points);
} /* gprpolyline_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$rectangle (rectangle, status)                            */
/*                                                                    */
/* input:                                                             */
/* gpr_$window_t  rectangle;                                          */
/*                                                                    */
/* output:                                                            */
/* status_$t      status;                                             */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Draws and fills a rectangle in the current bitmap. It fills the    */
/* rectangle with the color/intensity value specified with            */
/* gpr_$set_fill_value(...). For unfilled rectangles use              */
/* gpr_$draw_box(...) or gpr_$polyline(...)                           */
/*                                                                    */
/* ================================================================== */

void gprrectangle_ (window, status)

short int   window[4];
long        *status;

{
   XPoint   tr[4];



   tr[0].x = window[0];
   tr[0].y = window[1];
   tr[1].x = window[0] + window[2];
   tr[1].y = window[1];
   tr[2].x = window[0] + window[2];
   tr[2].y = window[1] + window[3];
   tr[3].x = window[0];
   tr[3].y = window[1] + window[3];
   XFillPolygon (d, w, FillGC, tr, 4, Convex, CoordModeOrigin);
} /* gprrectangle_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_clipping_active (active, status)                     */
/*                                                                    */
/* input:                                                             */
/* Boolean  active;                                                   */
/*                                                                    */
/* output:                                                            */
/* status_$t  status;                                                 */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Enables/disables a clipping window for the current bitmap. active  */
/* is a boolean (logical) value that specifies whether or not to      */
/* enable the clipping window. True => clipping enabled. status is,   */
/* as always, the completetion status. To specify a clipping window,  */
/* use gpr_$set_clip_window(...). Initially, in borrow-display mode,  */
/* the clip window is disabled. In direct mode, the clip window is    */
/* enabled and clipped to the size of the window. Clipping cannot be  */
/* enabled in a bitmap corresponding to a Display Manager frame.      */
/*                                                                    */
/* ================================================================== */

void gprsetclippingactive_ (flag, status)

int   *flag;
long  *status;

{
   if (*flag)
   {
      XSetClipRectangles (d, FillGC, 0, 0, &clipr, 1, YXBanded);
      XSetClipRectangles (d, DrawGC, 0, 0, &clipr, 1, YXBanded);
      XSetClipRectangles (d, TextGC, 0, 0, &clipr, 1, YXBanded);
   }
   else
   {
      XSetClipMask (d, FillGC, None);
      XSetClipMask (d, DrawGC, None);
      XSetClipMask (d, TextGC, None);		
   }
} /* gprsetclippingactive_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_clip_window (window, status)                         */
/*                                                                    */
/* input:                                                             */
/* gpr_$window_t  window;                                             */
/*                                                                    */
/* output:                                                            */
/* status_$t      status;                                             */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Changes the clipping window for the current bitmap. The default    */
/* clip window is the entire bitmap. This call is not allowed on the  */
/* bitmap corresponding to the Display Manager frame.                 */
/*                                                                    */
/* ================================================================== */

void gprsetclipwindow_ (window, status)

short int   window[4];
long        *status;

{
   clipr.x = window[0];
   clipr.y = window[1];
   clipr.width = window[2];
   clipr.height =  window[3];
} /* gprsetclipwindow_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_color_map (start_index, n_entries, values, status)   */
/*                                                                    */
/* input:                                                             */
/* gpr_$pixel_value_t  start_index;                                   */
/* short               n_entries;          # 2-byte integer           */
/* gpr_$color_vector_t values;                                        */
/*                                                                    */
/* output:                                                            */
/* status_$t           status;                                        */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Establishes new values for the color map. start_index is the index */
/* of the first color value entry. n_entries is the number of entries.*/
/* Valid values are: 2 for monochromatic displays, 1-16 for color     */
/* displays in 4-bit pixel format, 1-256 for color displays in 8-bit  */
/* or 24-bit pixel format. values are the color value entries. status */
/* is the completion status. For the monochromatic display, the       */
/* default start-index is 0, n-entries is 2, and the values are       */
/* gpr_$black and gpr_$white. For the monochromatic display, if the   */
/* program provides fewer than two values, or if the first two vales  */
/* are the same, the routine returns an error. For the monochromatic  */
/* display, the graphics primitives simultae a color map by modifying */
/* the contents of display memory. In direct mode, you must acquire   */
/* the display before establishing new values for the color map. On a */
/* monochromatic display in direct mode, the color map can not be     */
/* modified.                                                          */
/*                                                                    */
/* ================================================================== */

void gprsetcolormap_ (start, nentries, values, status)

pixel_t  *start;
long     *nentries;
long     *values;
long     *status;

{
   Colormap cmap;
   XColor   exact;
   XColor   closest;
} /* gprsetcolormap_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_cursor_position (position, status)                   */
/*                                                                    */
/* input:                                                             */
/* gpr_$position_t  position;                                         */
/*                                                                    */
/* output:                                                            */
/* status_$t        status;                                           */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Establishes a position on the screen for display of the cursor.    */
/* posistion is the screen coordinate position for display of the     */
/* cursor. The values must be within the limits of the display in use.*/
/* (Frame: 0-32767 for x and y). status is the completion status. If  */
/* the coordinate position would cause any part of the cursor to be   */
/* outside the screen or frame, the cursor moves only as far as the   */
/* edge of the screen. The cursor is neither clipped nor made to      */
/* disappear. In a Display Manager frame, this routine moves the      */
/* cursor only if the cursor is in the window viewing this frame when */
/* the call is issued. If not, a "next window" command which moves to */
/* that window will move the cursor to its new position.              */
/*                                                                    */
/* ================================================================== */

void gprsetcursorposition_ (posn, status)

position_t  *posn;
long        *status;

{
   XWarpPointer (d, None, w, 0, 0, 0, 0, posn->x, posn->y);
} /* gprsetcursorposition_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_draw_value (index, status)                           */
/*                                                                    */
/* input:                                                             */
/* gpr_$pixel_value_t  index;                                         */
/*                                                                    */
/* output:                                                            */
/* status_$t           status;                                        */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Specifies the color/intensity value to use to draw lines. index is */
/* the color map index. If this value equals -2 this specifies using  */
/* the color/intensity value of the bitmap background as the line     */
/* drawing value. For borrowed displays and memory bitmaps, the fill  */
/* background is always zero. For Display Manager frames, this is the */
/* pixel value in use for the window background. status is the        */
/* completion status. The default draw value is 1. For monochromatic  */
/* displays, only the low-order bit of the draw value is considered,  */
/* because monochromatic displays have only one plane. For color      */
/* displays in 4-bit pixel format, only the four lowest-order bits of */
/* the draw value are considered, because these displays have four    */
/* planes.                                                            */
/*                                                                    */
/* ================================================================== */

void gprsetdrawvalue_ (pixel, status)

long  *pixel;
long  *status;

{
   XSetForeground(d, DrawGC, colortrans[*pixel]);
   *status = 0;
} /* gprsetdrawvalue_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_fill_value (index, status)                           */
/*                                                                    */
/* input:                                                             */
/* gpr_$pixel_value_t  index;                                         */
/*                                                                    */
/* output:                                                            */
/* status_$t           status;                                        */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Specifies the color/intensity value to use to fill circles,        */
/* rectangle, triangles, and trapezoids. index is                     */
/* the color map index.  status is the                                */
/* completion status. The default fill value is 1. For monochromatic  */
/* displays, only the low-order bit of the draw value is considered,  */
/* because monochromatic displays have only one plane. For color      */
/* displays in 4-bit pixel format, only the four lowest-order bits of */
/* the draw value are considered, because these displays have four    */
/* planes.                                                            */
/*                                                                    */
/* ================================================================== */


void gprsetfillvalue_ (pixel, status)

long  *pixel;
long  *status;

{
   XSetForeground(d, FillGC, colortrans[*pixel]);
   *status = 0;
} /* gprsetfillvalue_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_raster_op (plane_id, raster_op, status)              */
/*                                                                    */
/* input:                                                             */
/* gpr_$plane_t          plane_id;                                    */
/* gpr_$raster_op_t      raster_op;                                   */
/*                                                                    */
/* output:                                                            */
/* status_$t             status;                                      */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Specifies the raster operation for both BLTs and lines. plane_id   */
/* identifies the bitmap plane involved in the raster operation.      */
/* Valid values are zero through the identifier of the bitmap's       */
/* highest plane. raster_op is the raster operation code. Possible    */
/* values are zero through fifteen. status is the completion status.  */
/* The initial raster operation is 3. This operation assigns all      */
/* source bit values to new destination bit values. Following is a    */
/* truth table for all sixteen operation codes:                       */
/*                      result dest                                   */
/* source   dest        0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15         */
/*  0        0          0 0 0 0 0 0 0 0 1 1 1  1  1  1  1  1          */
/*  0        1          0 0 0 0 1 1 1 1 0 0 0  0  1  1  1  1          */
/*  1        0          0 0 1 1 0 0 1 1 0 0 1  1  0  0  1  1          */
/*  1        1          0 1 0 1 0 1 0 1 0 1 0  1  0  1  0  1          */
/*                                                                    */
/* ================================================================== */

void gprsetrasterop_ (plane, op, status)

short int   *plane;
short int   *op;
long        *status;

{
   lop = (long) *op;
   /*
    * When we invert, invert only one bit.
    */
   if (lop == 10)
   {
      XSetPlaneMask(d, FillGC, 0x00000001);
      XSetPlaneMask(d, TextGC, 0x00000001);
      XSetPlaneMask(d, EraseGC, 0x00000001);
   }
   else
   {
      XSetPlaneMask(d, FillGC, 0xffffffff);
      XSetPlaneMask(d, TextGC, 0xffffffff);
      XSetPlaneMask(d, EraseGC, 0xffffffff);
   }
	
   XSetFunction(d, FillGC, lop);
   XSetFunction(d, TextGC, lop);
   XSetFunction(d, EraseGC, lop);
#if 0
   XSetFunction(d, DrawGC, lop);
#endif
} /* gprsetrasterop_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_text_background_value (index, status)                */
/*                                                                    */
/* input:                                                             */
/* gpr_$pixel_value_t  index;                                         */
/*                                                                    */
/* output:                                                            */
/* status_$t           status;                                        */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Specifies the color/intensity value to use for text background.    */
/* index is                                                           */
/* the color map index. If this value equals -2 this specifies using  */
/* the color/intensity value of the bitmap background as the line     */
/* drawing value. For borrowed displays and memory bitmaps, the fill  */
/* background is always zero. For Display Manager frames, this is the */
/* pixel value in use for the window background. If this value equals */
/* -1 this specifies that the text background is transparent; that is */
/* the old values of the pixels are not changed. status is the        */
/* completion status. The default value is -2. For monochromatic      */
/* displays, only the low-order bit of the draw value is considered,  */
/* because monochromatic displays have only one plane. For color      */
/* displays in 4-bit pixel format, only the four lowest-order bits of */
/* the draw value are considered, because these displays have four    */
/* planes.                                                            */
/*                                                                    */
/* ================================================================== */

void gprsettextbackgroundvalue_ (pixel, status)

long  *pixel;
long  *status;

{
   XSetBackground(d, TextGC, colortrans[*pixel]);
   *status = 0;
} /* gprsettextbackgroundvalue_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_text_font (font_id, status)                          */
/*                                                                    */
/* input:                                                             */
/* short     font_id;       # 2-byte integer                          */
/*                                                                    */
/* output:                                                            */
/* status_$t status;                                                  */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Establishes a new font for subsequent text operations. font_id is  */
/* the identifier of the new text font. status is the completion      */
/* status. There is no default text font. A program must load and set */
/* the font. Call gpr_$set text_font(...) for each main memory bitmap.*/
/* Otherwise an error is returned (invalid font id).                  */
/*                                                                    */
/* ================================================================== */

void gprsettextfont_ (font, status)

long  *font;
long  *status;

{
   /* XXX fill in font here */
   XSetFont(d, TextGC, *font);
   *status = 0;
} /* gprsettextfont_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_text_path (direction, status)                        */
/*                                                                    */
/* input:                                                             */
/* gpr_$direction_t  direction;                                       */
/*                                                                    */
/* output:                                                            */
/* status_$t         status;                                          */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Specifies the direction for writing a line of text. direction is   */
/* on of gpr_$up, gpr_$down. gpr_$left, gpr_$right. The default text  */
/* path is gpr_$right. status is the completion status.               */
/*                                                                    */
/* ================================================================== */

void gprsettextpath_ (direction, status)

long  *status;

{
   /*XXX noop */
   *status = 0;
} /* gprsettextpath_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$set_text_value (index, status)                           */
/*                                                                    */
/* input:                                                             */
/* gpr_$pixel_value_t  index;                                         */
/*                                                                    */
/* output:                                                            */
/* status_$t           status;                                        */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Specifies the color/intensity value to use for writing text. index */
/* is the color map index. status is the                              */
/* completion status. The default value is 1 for borrowed displays,   */
/* memory bitmaps, and Display Manager frames on monochromatic        */
/* displays; 0 for Display Manager frames on color displays.          */
/* For monochromatic                                                  */
/* displays, only the low-order bit of the draw value is considered,  */
/* because monochromatic displays have only one plane. For color      */
/* displays in 4-bit pixel format, only the four lowest-order bits of */
/* the draw value are considered, because these displays have four    */
/* planes.                                                            */
/*                                                                    */
/* ================================================================== */

void gprsettextvalue_ (pixel, status)

long  *pixel;
long  *status;

{
   XSetForeground(d, TextGC, colortrans[*pixel]);
   *status = 0;
} /* gprsettextvalue_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$terminate (delete_display, status)                       */
/*                                                                    */
/* input:                                                             */
/* Boolean     delete_display;                                        */
/*                                                                    */
/* output:                                                            */
/* status_$t  status;                                                 */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Terminates the graphics primitives package. delete_display         */
/* specifies whether to delete the frame of the Display Manager pad.  */
/* If the program has operated in a Display Manager frame and needs   */
/* to delete the frame at the end of a graphics sesion, set this      */
/* value to True. If the program needs to close, but not to delete    */
/* the frame, set this value to false. If the program has not used a  */
/* Display Manager frame, the value is ignored. status is the         */
/* completion status. gpr_$terminate(...) deletes the frame           */
/* regardless of the value of the delete-display argument in the      */
/* following case. A BLT operation from a memory bitmap has been done */
/* to a Display Manager frame since the last time gpr_$clear was      */
/* called for the frame.                                              */
/*                                                                    */
/* ================================================================== */

void gprterminate_ (flag, status)

int   *flag;
long  *status;

{
/*
   XUngrabServer(d);
   XUngrabPointer(d, CurrentTime);
*/
   XCloseDisplay(d);
   *status = 0;
} /* gprterminate_ */





/* ================================================================== */
/*                                                                    */
/* void gpr_$text (string, string_length, status)                     */
/*                                                                    */
/* input:                                                             */
/* gpr_$string_t  string;                                             */
/* short          string_length;     # 2-byte integer ( <257 )        */
/*                                                                    */
/* output:                                                            */
/* status_$t      status;                                             */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Writes text to the current bitmap, beginning at the current        */
/* position. gpr_$text(...) always clips to the edge of the bitmap,   */
/* regardless of whether clipping is enabled. It writes the characters*/
/* in the current font which correspond to the ASCII values of the    */
/* characters in the specified string. If the font does not have a    */
/* character which corresponds to a character in the string,          */
/* gpr_$text(...) leaves a space. The size of the space is set by     */
/* gpr_$set_space_size(...). The origin of the first character of the */
/* string is placed at the current position. Generally, the origin is */
/* is at the bottom left, excluding descenders of the character. Upon */
/* completion of the gpr_$text routine, the current position is       */
/* updated to the coordinate position where a next character would be */
/* written. This is the case even if the string is partly or completly*/
/* clipped. However, the current position always remains within the   */
/* boundaries of the bitmap.                                          */
/*                                                                    */
/* ================================================================== */

void gprtext_ (string, nchars, status)

char  *string;
int   *nchars;
long  *status;

{
#if 0
   printf("%d: (%.*s) show at %d, %d\n", *nchars, *nchars, string,
	                                 curpoint.x, curpoint.y);
#endif
   XDrawImageString (d, w, TextGC, curpoint.x, curpoint.y, string, *nchars);
   *status = 0;
} /* gprtext_ */




/* ================================================================== */
/*                                                                    */
/* void gpr_$trapezoid (trapezoid, status)                            */
/*                                                                    */
/* input:                                                             */
/* gpr_$trap_t  trapezoid;                                            */
/*                                                                    */
/* output:                                                            */
/* status_$t    status;                                               */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Draws and fills a trapezoid. trapezoid is the trapezoid to be      */
/* drawn. status is the completion status. gpr_$trapezoid(...) fills  */
/* in a trapezoid with the color/intensity value specified with       */
/* gpr_$set_fill_value(...) or the pattern set by                     */
/* gpr_$set_fill_pattern(...). The GPR routines define a trapezoid as */
/* a quadrilateral with two horizontal parallel sides. To draw an     */
/* unfilled trapezoid use gpr_$polyline(...).                         */
/*                                                                    */
/* ================================================================== */

void gprtrapezoid_ (trap, status)

trap_t   *trap;
long     *status;

{
   XPoint tr[4];



   tr[0].x = trap->top.x_coord_l;
   tr[0].y = trap->top.y_coord;
   tr[1].x = trap->top.x_coord_r;
   tr[1].y = trap->top.y_coord;    
   tr[2].x = trap->bot.x_coord_r;
   tr[2].y = trap->bot.y_coord;    
   tr[3].x = trap->bot.x_coord_l;
   tr[3].y = trap->bot.y_coord;    
   XFillPolygon (d, w, FillGC, tr, 4, Convex, CoordModeOrigin);
} /* gprtrapezoid_ */





/* ================================================================== */
/*                                                                    */
/* void time_$clock (clock)                                           */
/*                                                                    */
/* output:                                                            */
/* time_$clock_t  clock;                                              */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Returns the current UTC (Coordinated Universal) time. It is        */
/* represented as the number of 4-microsecond periods that have       */
/* elapsed since January1, 1980 at 00:00. To get the local time, use  */
/* cal_$get_local_time(...). To compute the local time from the value */
/* returned by time_$clock(...), use cal_$apply_local_offset(...).    */
/*                                                                    */
/* ================================================================== */

void timeclock_ (clock)

short int  clock[3];

{
   struct timeval tv;
   long   tmp_micro;



   XSync(d,0);
   gettimeofday(&tv, 0);

   clock[0] = tv.tv_sec >> 16;
   clock[1] = tv.tv_sec & 0xffff;
   clock[2] = tv.tv_usec/4;

/*
   tmp_micro = tv.tv_sec * 250000 + tv.tv_usec/4;

   clock[2] = tmp_micro & 0x000000ff;
   clock[1] = (tmp_micro & 0x0000ff00) >> 16;
   clock[0] = (tmp_micro & 0x00ff0000) >> 32;
*/
} /* timeclock_ */





/* ================================================================== */
/*                                                                    */
/* void time_$wait (rel_abs, clock, status)                           */
/*                                                                    */
/* input:                                                             */
/* time_$rel_abs_t  rel_abs;                                          */
/* time_$clock_t    clock;                                            */
/*                                                                    */
/* output:                                                            */
/* status_$t        status;                                           */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Suspends the calling process for a specified time. rel_abs is one  */
/* of the following: time_$relative (clock specifies the number of    */
/* 4-microsecond periods to wait), time_$absolute (clock contains the */
/* UTC system time for which to wait). status is, as always, the      */
/* completion status.                                                 */
/*                                                                    */
/* ================================================================== */

void timewait_ (delta, clock, status)

float       *delta;
short int   clock[3];
long        *status;

{
   struct timeval tv;
   long           tmp_micro;



   XSync(d, 0);

   tv.tv_sec = ((clock[0] <<16) + clock[1])>>1;
   tv.tv_usec = clock[2] * 4;

/*
   tmp_micro = ((((clock[0] * 65536) + clock[1]) * 65536) + clock[2]);

   tv.tv_sec = tmp_micro / 250000;
   tv.tv_usec = (tmp_micro && 0x000000ff);
*/
   select (0, 0, 0, 0, &tv);
} /* timewait_ */





/* ================================================================== */
/*                                                                    */
/* void tone_$time (time)                                             */
/*                                                                    */
/* input:                                                             */
/* time_$clock_t  time;                                               */
/*                                                                    */
/* ================================================================== */
/*                                                                    */
/* Makes a tone. The tone remains on for the time indicated in the    */
/* call.                                                              */
/*                                                                    */
/* ================================================================== */

void tonetime_ (time)

long  *time;

{
   XBell(d, 0);
}





/* ================================================================== */
/*                                                                    */
/* Where does this come from?                                         */
/*                                                                    */
/* ================================================================== */

void rand_ (x)

float *x;

{
   unsigned long  r = random();
   double         dr = r % 566927;
    
   *x = dr / 566927;
} /* rand_ */
