/*  x11_src.c  - c routines for Dataplot X11 driver */
/*  UPDATED  - June     1991.  Fixed bug in color handling. */
/*  UPDATED  - June     1991.  Use color names rather than specific
 *                             RGB values.  Had a problem with PC 
 *                             implementations not having enough free
 *                             color cells.  The global variable 
 *                             COLOR_TYPE is used to control which 
 *                             method is used.
 *  UPDATED  - January  1992.  Problem with pixmap on black-white
 *                             devices, modified "xerase" routine.
 *  UPDATED  - January  1992.  Variable FONT_NAME_DEFAULT to softcode
 *                             default X11 font.
 *  UPDATED  - April    1992.  Handle routine names as upper case (for
 *                             the Cray).  Use SUBROUTINE_CASE.
 *  UPDATED  - August   1992.  Minor bug fix.  Also, add support for
 *                             gray scale and a color to the list of
 *                             supported colors.
 *  UPDATED  - October  1993.  Definitions can now be specified on the
 *                             compile line as -D options rather than
 *                             requiring source changes.
 *  UPDATED  - May      1994.  XREGFL routine modified.  DATAPLOT
 *                             now allows more complicated fills.  Note
 *                             that there still seems to be a problem
 *                             if curve is both above and below the
 *                             the region base (e.g., PLOT SIN(X) FOR
 *                             X = 0 .1 25  (may have to revert to 
 *                             software fill for complex regions).
 *  UPDATED  - November 1994.  Modify i_to_s usage to work under both
 *                             ANSI C and K&R C.
 *  UPDATED  - May      1995.  Modify xinit to allow window id to be
 *                             passed from front-end.
 *  UPDATED  - July     1995.  Modify xupdat for front-end
 *  UPDATED  - June     1996.  Option to specify double precision for
 *                             real numbers instead of float (intended
 *                             for when the Fortran is compiled in
 *                             double precision, e.g., use of -r8 on
 *                             Unix Fortran.  Do not use for Cray
 *                             since their single precision is 64-bit
 *                             for both Fortran and C.
 *                             To turn on, use -DDOUBLE on C compile.
 *                             Introduces complications in that C
 *                             still uses 32-bit for both int and long.
 *  UPDATED  - April    1997.  Support for the following Dataplot
 *                             commands:
 *                                SAVE PLOT <file name>
 *                                SAVE PLOT AUTOMATIC
 *
 *                                REPEAT GRAPH <file>
 *                                CYCLE GRAPH
 *                             Add the following X11 routines:
 *                                xsaveg - routine to save the current
 *                                         pixmap to the specified file
 *                                xrestg - routine to restore a pixmap
 *                                         that was previously saved.
 *                                xcycle - cycle through previously
 *                                         created graphs
 *                             For performance reasons, the saving and
 *                             restoring of pixmaps is limited to
 *                             bitmaps rather than images (i.e.,
 *                             bitmaps have a depth of 1 = no color).
 *   
 *                             Change method for setting window
 *                             properties fro X11R3 to X11R4.  Add
 *                             a switch to determine which method to
 *                             use.
 *  UPDATED  - October  1997.  A few minor tweaks to "xrestg" to
 *                             make the April 1997 modifications
 *                             work with the GUI.
 */
/*  This driver has been tested on Suns (both monochrome and color),
 *  Silicon Graphics Iris, HP-9000, a Cray Y-MP, DEC workstation, 
 *  and a PC implementation.   */
/*
 *  The Dataplot command can be entered from any currently open window.
 *  Dataplot's normal alphanumeric I/O (e.g., entering commands, output
 *  from FIT's) will occur in this window.  Dataplot will create a separate
 *  graphics window where the graphical output will be generated.  Note
 *  that although Dataplot will send a recommended size and position for
 *  the graphics window, the user has control over this through the window
 *  manager.  Dataplot will check for the actual dimensions whenever a clear
 *  screen command is entered.  The bit gravity is set to NorthWest so that
 *  drawing coordinates will be valid until the next erase page command.
 *
 *  A dummy version of this library is maintained for those systems
 *  that do not support X11 or that do not allow C routines to be called
 *  from Fortran.  Since the dummy library is coded in Fortran, routine
 *  names will be limited to six characters.
 *
 *  Note that calling C from Fortran is not standard.  Therefore, these
 *  routines may require some tweaking for some operating systems.  This
 *  version was tested on the Sun (using Unix).  The following is a list
 *  of portability issues.
 *
 *  1) The Sun Unix system appends an underscore ("_") to the Fortran
 *     name.  For example, if the Fortran routine calls XEND, the C name
 *     will be XEND_.
 *
 *     NOTE: May, 1990.  The global variable APPEND_UNDERSCORE is now
 *           used to handle this problem.  If your system appends the
 *           underscore, set this variable to 1.  Otherwise set it to
 *           0.  Conditional compilation statements will insert the correct
 *           function name.
 *
 *     NOTE: April, 1992.  Most Unix Fortran compilers automatically 
 *           convert routine names to lower case.  However, the Cray does
 *           not.  Add the global variable SUBROUTINE_CASE to handle this.
 *           For lower case, set this variable to 1.  For upper case, set
 *           this variable to 0.
 *
 *     NOTE: October, 1993.  The above 2 definitions are now controlled
 *           with the -DNOUNDERSCORE and -DUPPERCASE compile definitions.
 *           The default is an underscore and lower case.  This new way allows
 *           the changes to be made without changes in the source code.
 *
 *  2) The primary portability problem will be in how arguments are passed
 *     back and forth between Fortran and C.  Note that Fortran passes
 *     arguments by reference (i.e., it sends the address) while C passes
 *     by value (i.e., a local copy is made of the variable).  On the
 *     Sun (and most Unix systems), real and integer arguments can be sent
 *     via the function arguments.  Be aware that the C subroutine must
 *     declare the function arguments to be pointers since Fortran is
 *     sending an address rather than a value.  The function argument must
 *     be declared as a pointer even if its value is not being returned to
 *     the calling Fortran program.
 *
 *     However, note that arrays are treated as pointers in C, so array
 *     names are not declared as pointers in C.
 *
 *     Character strings should be sent as an array of Ascii Decimal
 *     Equivalents (i.e., "A" should be sent as the integer 65, "0"
 *     should be sent as the integer 48) to correspond to how C defines
 *     character strings.  Note that the string should end with the null
 *     character (integer 0).
 *
 *     If your system passes data differently (e.g., through some type of
 *     common), both the calling Fortran program and the C code here will
 *     have to be modified.
 *
 *  3) The Unix makefile may need to be modified for some Unix systems.
 *     This should be straightforward (may need to specify different
 *     directories for X11 or system libraries).
 *
 *  This initial version is strictly a "device driver".  Development to
 *  utilize the windowing capabilities of X is under consideration, but is
 *  not yet implemented.
 *
 *  The primary references for writing this driver were:
 *
 *     "Introduction to the X Window System" by Oliver Jones (1989).
 *     "Xlib Programming Manual for Version 11" by Adrian Nye (1990).
 *
 *  The following routines are included:
 *
 *  xcheck     - check for expose and configure events
 *  xrdloc     - read mouse position when button pressed
 *  xinit      - initialize X11
 *  xend       - close X11
 *  xclear     - flush the buffer
 *  xerase     - clear the screen
 *  xupdat     - copy pixmap to screen
 *  xfore      - set the foreground color
 *  xback      - set the background color
 *  xlattr     - set line attributes (width, style, cap, join)
 *  xdraw      - draw a polyline
 *  xpoint     - draw a point
 *  xcirc      - draw a circle
 *  xregfl     - solid fill of a region
 *  xtexth     - draw a horizontal character string
 *  xtextv     - draw a vertical character string
 *  xtattr     - set text attributes
 *  xsaveg     - copy pixmap to a specified file
 *  xrestg     - copy pixmap from a specified file to the screen
 *  xcycle     - cycle through previously saved pixmaps
 *  i_to_s     - utility routine to convert array of ADE's to string array
 *  set_screen - utility routine to set screen height and width
 *
 */

/*  Site dependent definitions (see comments above) */
/*  Default is an underscore and lower case.  The compiler specified
 *  definitions -DNOUNDERSCORE and -DUPPERCASE can be specified to override
 *  these defaults. */

#ifdef NOUNDERSCORE
#define APPEND_UNDERSCORE 0
#else
#define APPEND_UNDERSCORE 1
#endif
#ifdef UPPERCASE
#define SUBROUTINE_CASE 0
#else
#define SUBROUTINE_CASE 1
#endif
/* Following 5 lines added June, 1996.  */
#ifdef DOUBLE
#define PRECISION 1
#else
#define PRECISION 0
#endif
#define COLOR_TYPE 1

/*  include files */

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
/* add following 2 lines MAY 1995   */
#include <stdlib.h>
#include <math.h>
#include <strings.h>

/* global definitions */

#if COLOR_TYPE
#define MAX_COLORS    89
#else
#define MAX_COLORS    16
#endif
#define MAX_GRAY         100
#define BORDER_WIDTH      3
/*
#define DEFAULT_X_SIZE  600
#define DEFAULT_Y_SIZE  465
*/
#define DEFAULT_X_SIZE  550
#define DEFAULT_Y_SIZE  425
#define DEFAULT_X        50
#define DEFAULT_Y        50
#define MIN_X_SIZE      200
#define MIN_Y_SIZE      200

/* X11 declarations */
Display       *display;           /* display connection */
Window        window;             /* window identifier */
Window        window2;            /* window identifier for repeat graph */
Pixmap        pixmap;             /* pixmap identifier */
Pixmap        pixmap2, pixmap3;   /* pixmap identifier for repeat graph */
GC            gc;                 /* graphics context */
GC            gc2;                /* graphics context for repeat graph */
XGCValues     gcvalues;           /* set graphics context attributes */
XColor        colors[MAX_COLORS]; /* colors to draw with */
XColor        grays[MAX_GRAY];    /* gray scales to draw with */
XColor        exact_def;          /* returns exact RGB values */
XFontStruct   *font_struct;       /* returned font structure pointer */
Colormap      color_map;          /* default color map */
Visual        *vis;               /* pointer to visual structure */
XEvent        event;              /* holds X server events */
XSetWindowAttributes  window_attributes;    /* attributes structure */
XWindowAttributes     returned_attributes;  /* returned attributes */
unsigned long value_mask;         /* value mask for window attributes */
static XSizeHints                 /* size hints for window manager */
    xsh = {
       (PPosition | PSize | PMinSize),   /* flags */
       DEFAULT_X_SIZE,                   /* height */
       DEFAULT_Y_SIZE,                   /* width */
       MIN_Y_SIZE,                       /* minimum height */
       MIN_X_SIZE,                       /* minimum width */
       DEFAULT_X,                        /* x coordinate */
       DEFAULT_Y,                        /* y coordinate */
    };
static XWMHints       /* more hints for window manager */
    xwmh = {
       (InputHint | StateHint),         /* flags */
       False,                           /* input */
       NormalState,                     /* initial state */
       0,                               /* icon pixmap */
       0,                               /* icon window */
       0, 0,                            /* icon location */
       0,                               /* icon mask */
       0                                /* window group */
    };
static XClassHint    /* class hints for window manager */
    xch = {
        "dataplot",                      /* name */
        "Graphics",                      /* class */
    };
static char  *argv[] = {                 /* dummy command line arguments */
                          (char *)NULL   /* required by a few calls */
                        };
static int   argc = 0;

/* common parameters */
unsigned int  width, height;      /* last known window size */
unsigned int  width2, height2;    /* width, height for second window */
unsigned long black, white;       /* values for black and white */
int           screen;             /* default screen */
int           screen2;            /* repeat graph screen */
int           num_cells;          /* number of color cells available */
int           num_planes;         /* number of planes available */
int           depth;              /* depth (number of planes or bits/pixel */
int           color_flag;         /* 0 - monochrome, 1 - color */
int           max_colors;         /* maximum colors actually allocated */
int           configure_flag;     /* 0 - configuration up to date,
                                     1 - configuration has been changed */
int           expose_flag;        /* 0 - expose status has not changed,
                                     1 - expose status has changed */
int           expose_flag_aux;    /* 0 - expose status has not changed for repeat graph,
                                     1 - expose status has changed */
unsigned int root_width, root_height, root_depth, root_bw;
Window       root_id;
int          root_x, root_y;
int          pixmap_flag;         /* 0 - do not draw to pixmap
                                     1 - draw to pixmap */
int          color_list[MAX_COLORS]; /* Color availability */
int          color_list_gray[MAX_GRAY]; /* Gray scale availability */
char         *color_names[] = {   /* define color names (for Release */
 /*  0 */        "black",         /* 3, p. 184 of Adrian Nye book,   */
 /*  1 */        "white",         /* these should be recognized by   */
 /*  2 */        "green",         /* all Release 3 implementations.  */
 /*  3 */        "yellow",        /* If color not physically         */
 /*  4 */        "red",           /* available, should be mapped to  */
 /*  5 */        "blue",          /* closest possible alternative.   */
 /*  6 */        "magenta",       /* Updated August 1992 to add      */
 /*  7 */        "cyan",          /* some colors from R4 color       */
 /*  8 */        "orange",        /* database (Appendix D of Xlib    */
 /*  9 */        "yellow green",  /* Programmer's Reference from     */
 /* 10 */        "dark green",    /* O'Reilly and Associates (only a */
 /* 11 */        "light blue",    /* few of the additions for R4 are */
 /* 12 */        "blue violet",   /* supported, may add more later). */
 /* 13 */        "violet red",
 /* 14 */        "dark slate gray",
 /* 15 */        "light gray",
 /* 16 */        "aquamarine",
 /* 17 */        "brown",
 /* 18 */        "cadet blue",
 /* 19 */        "coral",
 /* 20 */        "cornflower blue",
 /* 21 */        "dark olive green",
 /* 22 */        "dark orchid",
 /* 23 */        "dark slate blue",
 /* 24 */        "dark turquoise",
 /* 25 */        "firebrick",
 /* 26 */        "forest green",
 /* 27 */        "gold",
 /* 28 */        "goldenrod",
 /* 29 */        "gray",
 /* 30 */        "indian red",
 /* 31 */        "khaki",
 /* 32 */        "dim gray",
 /* 33 */        "light steel blue",
 /* 34 */        "lime green",
 /* 35 */        "maroon",
 /* 36 */        "medium aquamarine",
 /* 37 */        "medium blue",
 /* 38 */        "medium forest green",
 /* 39 */        "light goldenrod yellow",
 /* 40 */        "medium orchid",
 /* 41 */        "medium sea green",
 /* 42 */        "medium slate blue",
 /* 43 */        "medium spring green",
 /* 44 */        "medium turquoise",
 /* 45 */        "medium violet red",
 /* 46 */        "midnight blue",
 /* 47 */        "navy",
 /* 48 */        "orange red",
 /* 49 */        "orchid",
 /* 50 */        "pale green",
 /* 51 */        "pink",
 /* 52 */        "plum",
 /* 53 */        "purple",
 /* 54 */        "salmon",
 /* 55 */        "sea green",
 /* 56 */        "sienna",
 /* 57 */        "sky blue",
 /* 58 */        "slate blue",
 /* 59 */        "spring green",
 /* 60 */        "steel blue",
 /* 61 */        "tan",
 /* 62 */        "thistle",
 /* 63 */        "turquoise",
 /* 64 */        "violet",
 /* 65 */        "wheat",
 /* 66 */        "green yellow",
 /* 67 */        "light cyan",    /* This starts additions for R4 */
 /* 68 */        "blue2",
 /* 69 */        "blue3",
 /* 70 */        "blue4",
 /* 71 */        "cyan2",
 /* 72 */        "cyan3",
 /* 73 */        "cyan4",
 /* 74 */        "green2",
 /* 75 */        "green3",
 /* 76 */        "green2",
 /* 77 */        "yellow2",
 /* 78 */        "yellow3",
 /* 79 */        "yellow4",
 /* 80 */        "orange2",
 /* 81 */        "orange3",
 /* 82 */        "orange4",
 /* 83 */        "red2",
 /* 84 */        "red3",
 /* 85 */        "red4",
 /* 86 */        "magenta2",
 /* 87 */        "magenta3",
 /* 88 */        "magenta4"
              };
char         *gray_names[] = {    /* define gray scale names         */
                 "gray0",
                 "gray1", 
                 "gray2", 
                 "gray3", 
                 "gray4", 
                 "gray5", 
                 "gray6", 
                 "gray7", 
                 "gray8", 
                 "gray9", 
                 "gray10", 
                 "gray11", 
                 "gray12", 
                 "gray13", 
                 "gray14", 
                 "gray15", 
                 "gray16", 
                 "gray17", 
                 "gray18", 
                 "gray19", 
                 "gray20", 
                 "gray21", 
                 "gray22", 
                 "gray23", 
                 "gray24", 
                 "gray25", 
                 "gray26", 
                 "gray27", 
                 "gray28", 
                 "gray29", 
                 "gray30", 
                 "gray31", 
                 "gray32", 
                 "gray33", 
                 "gray34", 
                 "gray35", 
                 "gray36", 
                 "gray37", 
                 "gray38", 
                 "gray39", 
                 "gray40", 
                 "gray41", 
                 "gray42", 
                 "gray43", 
                 "gray44", 
                 "gray45", 
                 "gray46", 
                 "gray47", 
                 "gray48", 
                 "gray49", 
                 "gray50", 
                 "gray51", 
                 "gray52", 
                 "gray53", 
                 "gray54", 
                 "gray55", 
                 "gray56", 
                 "gray57", 
                 "gray58", 
                 "gray59", 
                 "gray60", 
                 "gray61", 
                 "gray62", 
                 "gray63", 
                 "gray64", 
                 "gray65", 
                 "gray66", 
                 "gray67", 
                 "gray68", 
                 "gray69", 
                 "gray70", 
                 "gray71", 
                 "gray72", 
                 "gray73", 
                 "gray74", 
                 "gray75", 
                 "gray76", 
                 "gray77", 
                 "gray78", 
                 "gray79", 
                 "gray80", 
                 "gray81", 
                 "gray82", 
                 "gray83", 
                 "gray84", 
                 "gray85", 
                 "gray86", 
                 "gray87", 
                 "gray88", 
                 "gray89", 
                 "gray90", 
                 "gray91", 
                 "gray92", 
                 "gray93", 
                 "gray94", 
                 "gray95", 
                 "gray96", 
                 "gray97", 
                 "gray98", 
                 "gray99" 
              };

/* flags for current attribute settings */
static int    OPEN_FLAG = 0;          /* 0 - X11 closed, 1 - X11 open */
static int    OPEN_FLAG_2 = 0;        /* 0 - repeat graph window closed, 1 - open */
int           GRAPH_FLAG = 0;         /* 0 - xerase has not been called, 1 - xerase has been called  */
int           WIDTH_CURRENT;          /* current line width */
int           LINE_STYLE_CURRENT;     /* current line style */
int           CAP_STYLE_CURRENT;      /* current cap style */
int           JOIN_STYLE_CURRENT;     /* current join style */
char          FONT_NAME_CURRENT[80];  /* name of current font */
char          FONT_NULL[80];          /* null font */
char          FONT_NAME_DEFAULT[80];  /* name of default font */
int           FONT_HEIGHT_CURRENT;    /* pixel ascent of current font */
int           FONT_DESCENT_CURRENT;   /* descent of current font */
int           FONT_GAP_CURRENT;       /* vertical gap of current font */
int           BACKGROUND_CURRENT;     /* current background color */
int           COLOR_CURRENT;          /* current color */
int           PIXMAP_CURRENT;         /* 0 - closed, 1 - open */
int           PIXMAP_CURRENT_2;       /* 0 - repeat graph closed, 1 - open */
int           ORIENTATION_CURRENT;    /* current orientation */

#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void  xclear_(), xend_(), xcheck_();
void  xinit_(), xlattr_(), xdraw_();
void  xpoint_(), xcirc_(), xregfl_(), xrdloc_();
void  xfore_(),  xerase_(), xupdat_();
void  xsaveg_(),  xrestg_(), xcycle_();
void  xtexth_(), xtextv_(),xtattr_();
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void  XCLEAR_(), XEND_(), XCHECK_();
void  XINIT_(), XLATTR_(), XDRAW_();
void  XPOINT_(), XCIRC_(), XREGFL_(), XRDLOC_();
void  XFORE_(),  XERASE_(), XUPDAT_();
void  XSAVEG_(),  XRESTG_(), XCYCLE_();
void  XTEXTH_(), XTEXTV_(), XTATTR_();
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void  xclear(), xend(), xcheck();
void  xinit(), xlattr(), xdraw();
void  xpoint(), xcirc(), xregfl(), xrdloc();
void  xfore(),  xerase(), xupdat();
void  xsaveg(),  xrestg(), xcycle();
void  xtexth(), xtextv(),xtattr();
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void  XCLEAR(), XEND(), XCHECK();
void  XINIT(), XLATTR(), XDRAW();
void  XPOINT(), XCIRC(), XREGFL(), XRDLOC();
void  XFORE(),  XERASE(), XUPDAT();
void  XSAVEG(), XRESTG(), XCYCLE();
void  XTEXTH(), XTEXTV(), XTATTR();
#endif
void  i_to_s(), set_screen(), xback();

/* XCHECK  - routine to check for X expose and configuration events.
 *           Specifically, resizing of the graphics window by the window
 *           manager (usually initiated by the user) generates a
 *           configuration event.  Placing windows on top of the graphics
 *           window and then re-raising it will generate an expose event.
 *           Dataplot makes no attempt to check if the part of the
 *           graphics window is not visible.  It simply draws and lets the
 *           window manager do any required clipping.
 *
 *           Note that this routine will not wait for any events.  It will
 *           simply check if there are any currently in the event queue.
 *
 *           Also, no action is taken for expose and configure events.
 *           This routine simply sets a flag indicating that these events
 *           were found.  It is the calling programs option as to what
 *           should be done about them.
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xcheck_(expose_flag_2, error_flag)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XCHECK_(expose_flag_2, error_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xcheck(expose_flag_2, error_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XCHECK(expose_flag_2, error_flag)
#endif
#if PRECISION == 0
int  *error_flag;
int  *expose_flag_2;
#else
int  error_flag[2];
int  expose_flag_2[2];
#endif
{
     XEvent   event;            /* holds Xserver events */

#if PRECISION == 0
     *error_flag = 0;
     *expose_flag_2 = 0;
#else
     error_flag[0] = 0;
     expose_flag_2[0] = 0;
#endif
     while (XEventsQueued(display, QueuedAfterReading) != 0) {/* check queue */
          XNextEvent(display, &event);        /* get next event from queue */
          switch (event.type) {
          case DestroyNotify:   /* window has been destroyed */
              if (event.xdestroywindow.window == window2) {
                XFreeGC(display, gc2);
                XDestroyWindow(display,window2);
                OPEN_FLAG_2 = 0;
              }
              else {
                XFreeGC(display, gc);
                XDestroyWindow(display,window);
                XCloseDisplay(display);
                OPEN_FLAG = 0;
                OPEN_FLAG_2 = 0;
              }
#if PRECISION == 0
              *error_flag = 1;
#else
              error_flag[0] = 1;
#endif
              break;
          case Expose:          /* portion of window has become visible */
              if (event.xexpose.window == window2) {
                if(event.xexpose.count == 0) {
                  expose_flag_aux = 1;
                }
              }
              else {
                if(event.xexpose.count == 0) {
                  expose_flag = 1;
                }
              }
#if PRECISION == 0
              *expose_flag_2 = 1;
#else
              expose_flag_2[0] = 1;
#endif
              break;
          case ConfigureNotify: /* window has been reconfigured */
              configure_flag = 1;
              break;
          default:
              break;
          }                     /* end switch */
     }                          /* end while */
}

/* XRDLOC  - routine to read a position from the graphics window (used
 *           by the Dataplot cross-hair command).  The mouse position at
 *           the next mouse click will be determined.
 *
 *           This routine will wait until a mouse button is pressed.
 *
 *           Note that expose and configure events will still be collected.
 *           Also, the pointer motion events are included for future
 *           development.  Currently, the code is commented out
 *           (although it should valid).  It will be activated if Dataplot
 *           develops a need for it later.  Dataplot's cross-hair simply
 *           wants a single coordinate position when any of the mouse buttons
 *           is pressed.
 *
 * ixret   - x coordinate of mouse position when button pressed
 * iyret   - y coordinate of mouse position when button pressed
 * error   - error flag (for window destroy event)
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xrdloc_(ixret, iyret, error)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XRDLOC_(ixret, iyret, error)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xrdloc(ixret, iyret, error)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XRDLOC(ixret, iyret, error)
#endif
#if PRECISION == 0
int  *ixret, *iyret, *error;
#else
int  ixret[2], iyret[2], error[2];
#endif
{
     XEvent   event;            /* holds Xserver events */
     int      x, y;             /* the last X pointer position */
     int      new_x, new_y;     /* a new X pointer position */
     unsigned int dummy;        /* placeholder for unwanted return value */
     int      done;

     XSelectInput(display, window,    /* Types of graphic input to accept */
       StructureNotifyMask |          /* Window notification events */
       ExposureMask |                 /* Expose events */
       ButtonPressMask |              /* Button press */
       ButtonMotionMask |             /* Pointer moves with button pressed */
       PointerMotionMask);            /* Pointer moves in window */

#if PRECISION == 0
       *ixret = -1;
       *iyret = -1;
       *error = 0;
#else
       ixret[0] = -1;
       iyret[0] = -1;
       error[0] = 0;
#endif
       done = 0;
       while (done == 0) {               /* loop until button press event */

          XNextEvent(display, &event);   /* get next event from queue */
          switch (event.type) {
          case DestroyNotify:            /* window has been destroyed */
              XFreeGC(display, gc);
              XDestroyWindow(display,window);
              XCloseDisplay(display);
#if PRECISION == 0
              *error = 1;
#else
              error[0] = 1;
#endif
              done = 1;
              break;
          case Expose:                   /* expose event */
              if(event.xexpose.count == 0) {
                expose_flag = 1;
              }
              break;
          case ConfigureNotify:          /* window has been reconfigured */
              configure_flag = 1;
              break;
          case MotionNotify:             /* pointer motion */
          /*  XQueryPointer(display, window,
                            &dummy, &dummy,
                            &dummy, &dummy,
                            &new_x, &new_y,
                            &mask);
              x = new_x;
              y = new_y;    */
              break;
          case ButtonPress:     /* Button event */
#if PRECISION == 0
              *ixret = event.xbutton.x;
              *iyret = event.xbutton.y;
#else
              ixret[0] = event.xbutton.x;
              iyret[0] = event.xbutton.y;
#endif
              done = 1;
              break;
          default:
              break;
          }       /* end switch */
       }          /* end while */

       XSelectInput(display, window,    /* Reset default event selection */
         StructureNotifyMask |          /* Window notification events */
         ExposureMask);                 /* Expose events */

}

/* XINIT  - routine to initialize X11.
 *
 * xp          - suggested width of graphics window in pixels (0 for default)
 * yp          - suggested height of graphics window in pixels (0 for default)
 * or          - 0 for landscape, 1 for portrait, 2 for use pixel sizes
 *               3 for square
 * ixret       - acutal width returned by window manager (as opposed to
 *               suggested width sent to window manager)
 * iyret       - actual height returned by window manager (as opposed to
 *               suggested height sent to window manager)
 * display_name- display name (NULL means use the default)
 * error_flag  - following error codes:
 *               0 - normal
 *               1 - unable to open display connection
 *               2 - X11 already open
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xinit_(xp, yp, or, ixret, iyret, display_name, iwind, iwindn,
            error_flag) 
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XINIT_(xp, yp, or, ixret, iyret, display_name, iwind, iwindn,
            error_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xinit(xp, yp, or, ixret, iyret, display_name, iwind, iwindn,
            error_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XINIT(xp, yp, or, ixret, iyret, display_name, iwind, iwindn,
            error_flag)
#endif
#if PRECISION == 0
int    *xp, *yp, *or;
int    *error_flag, *ixret, *iyret;
int    display_name[];
int    iwind[], iwindn[2];
#else
int    xp[2], yp[2], or[2];
int    error_flag[2], ixret[2], iyret[2];
int    display_name[];
int    iwind[], iwindn[2];
#endif
{
     XTextProperty  WindowName, IconName;
     char *window_name = "Dataplot";
     char *icon_name = "Dataplot";
     int          xpixels, ypixels, orien, iwindn_temp;
     int          temp, i;
     int          class;
     int          bits_per_rgb;
     float        atemp;
     Status       result;
     int          len, itest;
     char         display_string[80];
     long         itemp;
     int          counter;
     double       atemp1;
     int          window_flag;
#if PRECISION == 1
     int          iplace;
#endif

#if PRECISION == 0
     *error_flag = 0;
     xpixels = *xp;
     ypixels = *yp;
     orien = *or;
     iwindn_temp = *iwindn;
#else
     error_flag[0] = 0;
     xpixels = xp[0];
     ypixels = yp[0];
     orien = or[0];
     iwindn_temp = iwindn[0];
#endif
     strcpy(FONT_NULL,"ZZZZ");
     strcpy(FONT_NAME_DEFAULT,"8X13");
     if(OPEN_FLAG != 0) {                         /* X11 already open */
#if PRECISION == 0
       *error_flag = 2;
#else
       error_flag[0] = 2;
#endif
       return;
     }

     strcpy(display_string," ");
#if PRECISION == 0
     i_to_s(display_name, display_string, 80, &len);
#else
     i_to_s(display_name, display_string, 160, &len);
#endif
     itest = strncmp(display_string, "DEFAULT", 7);
     if (itest == 0) {          /* default display name */
       if((display = XOpenDisplay(NULL)) == NULL) { /*open display connection*/
#if PRECISION == 0
         *error_flag = 1;
#else
         error_flag[0] = 1;
#endif
         OPEN_FLAG = 0;
         return;
        }
     }
     else {           /* user specified display name */
       if((display = XOpenDisplay(display_string)) == NULL) {
#if PRECISION == 0
         *error_flag = 1;
#else
         error_flag[0] = 1;
#endif
         OPEN_FLAG = 0;
         return;
        }
     }

     OPEN_FLAG = 1;
     screen = DefaultScreen(display);        /* Set default screen */
     white = WhitePixel(display,screen);     /* Set white */
     black = BlackPixel(display,screen);     /* Set black */

     XGetGeometry(                           /* Get root window geometry */
                  display, DefaultRootWindow(display),
                  &root_id,                  /* root id */
                  &root_x, &root_y,          /* root position */
                  &root_width, &root_height, /* root width and height */
                  &root_bw, &root_depth);    /* root border width and depth */

     /* If window id passed from front-end, define window variable
      * from string in iwind and skip some code below.
      */

     set_screen(xpixels, ypixels, orien);
     ORIENTATION_CURRENT = orien;

     window_flag = 0;
     if ( iwindn_temp > 0 ) {
       window_flag = 1;
#if PRECISION == 0
       itemp = 0;
       for ( counter = 0; counter < iwindn_temp; counter++ ) {
          atemp1 = pow(16., (double) counter);
          itemp = itemp + (long) iwind[counter]* (long) atemp1;
       }
#else
       iplace = 0;
       itemp = 0;
       for ( counter = 0; counter < iwindn_temp; counter++ ) {
          atemp1 = pow(16., (double) counter);
          itemp = itemp + (long) iwind[iplace]* (long) atemp1;
          iplace = iplace + 2;
       }
#endif
       window = (Window) itemp;
       goto frontend;
     }

     window = XCreateSimpleWindow(           /* Open graphics window */
                display,                     /* Pointer to Display structure */
                DefaultRootWindow(display),  /* Parent for new window */
                xsh.x,                       /* X position of window */
                xsh.y,                       /* Y position of window */
                xsh.width,                   /* Width of window */
                xsh.height,                  /* Height of window */
                BORDER_WIDTH,                /* Pixel width of border */
                black,                       /* Border color */
                white);                      /* Background color */

     /* Set the bit gravity to NorthWest.  This means that if the
      * window is resized or repositioned by the window manager, the
      * window will be redrawn from top left corner.  This means we
      * can use current scale units until next page erase (i.e., do not
      * change units until start a new graph).  This is best solution
      * since Dataplot is vector rather than raster oriented, so not
      * possible to redraw what was previously drawn.  Transformed window
      * may not use full window or it may clip current graph, but should
      * otherwise be OK.  Next erase page will start drawing in new units.
      */
     
    /* Come here if front-end opened the graphics window.  */

    frontend:

 if ( window_flag == 0) {
     window_attributes.bit_gravity = NorthWestGravity; /* Set bit gravity */
     value_mask = CWBitGravity;
     XChangeWindowAttributes(display, window, value_mask,
         &window_attributes);

#ifdef X11R3  /* Use following for X11 Release 3 and earlier */
     XSetStandardProperties(display, window, "Dataplot", "Dataplot",
       None, argv, argc, &xsh);
     XSetWMHints(display, window, &xwmh);
     XSetClassHint(display, window, &xch);
#else  /* X11R4 or later */
     if (XStringListToTextProperty(&window_name, 1, &WindowName) == 0) {
#if PRECISION == 0
        *error_flag = 1;
#else
        error_flag[0] = 1;
#endif
        return;
     }
     if (XStringListToTextProperty(&icon_name, 1, &IconName) == 0) {
#if PRECISION == 0
        *error_flag = 1;
#else
        error_flag[0] = 1;
#endif
        return;
     }
     XSetWMProperties(display, window, &WindowName, &IconName, 
                      argv, argc, &xsh, &xwmh, &xch);
#endif

     XSelectInput(display, window,    /* Types of graphic input to accept */
       StructureNotifyMask |          /* Window notification events */
       ExposureMask );                /* Expose events */

    XMapWindow(display, window);      /* Map the window (make visible) */
    XFlush(display);                  /* Flush the buffer */

 }

    /* Get actual height and width set by the window manager */
    XGetWindowAttributes(display, window, &returned_attributes);
    width = returned_attributes.width;
    height = returned_attributes.height;
#if PRECISION == 0
    *ixret = width;
    *iyret = height;
#else
    ixret[0] = width;
    iyret[0] = height;
#endif

    if (window_flag == 0 ) {
      do {
          XNextEvent(display, &event);
      } while (event.type != MapNotify || event.xmap.window != window);
    }

    gc = XCreateGC(display, window, 0, &gcvalues);/* Create graphics context */
    XSetState(display,                /* the current display */
      gc,                             /* the current graphics context */
      black,                          /* set default foreground color */
      white,                          /* set default background color */
      GXcopy,                         /* set default to "overwrite" */
      AllPlanes);
    XSetLineAttributes(display, gc,   /* current display , graphics context */
      0,                              /* default line width */
      LineSolid,                      /* default soild line */
      CapButt,                        /* default end-cap style */
      JoinMiter);                     /* default line join style */
    WIDTH_CURRENT = 0;
    LINE_STYLE_CURRENT = 0;
    CAP_STYLE_CURRENT = 0;
    JOIN_STYLE_CURRENT = 0;

    strcpy(FONT_NAME_CURRENT,FONT_NULL);
    PIXMAP_CURRENT = 0;
    pixmap_flag = 0;

    num_cells = XDisplayCells(display,screen);    /* Color inquiry calls */
    num_planes = XDisplayPlanes(display, screen);
    color_map = XDefaultColormap(display, screen);
    vis = XDefaultVisual(display, screen);
    class = vis->class;
    bits_per_rgb = vis->bits_per_rgb;
    depth = XDefaultDepth(display, screen);


    if (depth == 1) {                 /* one-plane monochrome */
      color_flag = 0;
    }
    else if (class == PseudoColor) {  /* multi-plane color */
      color_flag = 2;
    }
    else if (class == GrayScale)   {  /* multi-plane monochrome */
       color_flag = 1;
    }
    else if (class == StaticGray)  {  /* multi-plane monochrome, unchangeable
                                         color map */
       color_flag = 1;
    }
    else if (class == DirectColor) {  /* direct color */
       color_flag = 2;
    }
    else if (class == TrueColor)   {  /* direct color, unchangeable color map*/
       color_flag = 2;
    }
    else if (class == StaticColor) {  /* multi-plane color, unchangeable
                                         color map */
       color_flag = 2;
    }
    else {
       color_flag = 0;
    }

/* June, 1991.  Switch from specifying colors by specific RGB values
 * to using the named colors (as defined by the R3 Color Database).
 * This avoids the problem of running out of color cell entries
 * (occured on a PC implementation).  In addition, all implementations
 * at R3 or higher should support all the colors in the database 
 * (or at least map the color to the closest possible alternative
 * available on the particular workstation).  It has the drawback
 * that RGB values cannot be specified exactly, but this is not
 * not really a problem since most of the colors we defined for
 * Dataplot are defined in the database.  Release 4 and some       
 * implementations of X11 support a broader database.  We will limit
 * it to more conservative one since this should be supported on
 * all implementations (R3 or higher).  The global variable COLOR_TYPE
 * is used to control whether the old method or the new method is used.
 * A possible future enhancement might be to allow a user-specified
 * color map based on RGB values.  This would work better with the
 * old implementation.
 */
/* August 1992.  Allocate gray scale colors (for both monochrome
 * and color workstations). */
    max_colors = 0;
#if COLOR_TYPE
    if (color_flag > 1) {  /* define colors */
       max_colors = MAX_COLORS;
       for (i=0; i < MAX_COLORS; i++) {
           color_list[i] = 1;
           if (!XAllocNamedColor (display, color_map, color_names[i], 
               &colors[i], &exact_def)) {
             color_list[i] = 0;
           } 
        } 
    }
    color_list_gray[0] = 0;
    for (i=1; i < MAX_GRAY; i++) {
        color_list_gray[i] = 1;
        if (!XAllocNamedColor (display, color_map, gray_names[i], 
            &grays[i], &exact_def)) {
          color_list_gray[i] = 0;
        } 
    } 
#else
    if (color_flag > 1) {  /* define colors */
      max_colors = MAX_COLORS;
      colors[0].red = 0;   /* define black */
      colors[0].green = 0;
      colors[0].blue = 0;

      colors[1].red = 65535; /* define white */
      colors[1].green = 65535;
      colors[1].blue = 65535;

      colors[2].red = 0; /* define green */
      colors[2].green = 40000;
      colors[2].blue = 0;

      colors[3].red = 65535; /* define yellow */
      colors[3].green = 65535;
      colors[3].blue = 0;

      colors[4].red = 65535;   /* define red */
      colors[4].green = 0;
      colors[4].blue = 0;

      colors[5].red = 0;   /* define blue */
      colors[5].green = 0;
      colors[5].blue = 65535;

      colors[6].red = 65535;   /* define magenta */
      colors[6].green = 0;
      colors[6].blue = 65535;

      colors[7].red = 0; /* define cyan */
      colors[7].green = 65535;
      colors[7].blue = 65535;

      colors[8].red = 65535; /* define Yellow Orange  (or Orange) */
      colors[8].green = 32767;
      colors[8].blue = 0;

      colors[9].red = 32767; /* define Yellow Green */
      colors[9].green = 65535;
      colors[9].blue = 0;

      colors[10].red = 0; /* define Blue Green */
      colors[10].green = 65535;
      colors[10].blue = 32767;

      colors[11].red = 0; /* define Green Blue */
      colors[11].green = 32767;
      colors[11].blue = 65535;

      colors[12].red = 32767; /* define Blue Violet (or purple) */
      colors[12].green = 0;
      colors[12].blue = 65535;

      colors[13].red = 65535; /* define Red violet */
      colors[13].green = 0;
      colors[13].blue = 32767;

      colors[14].red = 21845; /* define Dark Grey */
      colors[14].green = 21845;
      colors[14].blue = 21845;

      colors[15].red = 43690; /* Define Light Grey */
      colors[15].green = 43690;
      colors[15].blue = 43690;

      for (i = 0; i < 15; i++) {   /* allocate the 16 colors */
         color_list[i] = 1;
         if (! XAllocColor(display, color_map, &colors[i])) {
           color_list[i] = 0;      /* color allocation failed */
         }
      }
    }
#endif

    BACKGROUND_CURRENT = -1;
    COLOR_CURRENT = -1;
    temp = 0;
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
    xfore_(&temp);
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
    XFORE_(&temp);
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
    xfore(&temp);
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
    XFORE(&temp);
#endif
    BACKGROUND_CURRENT = 1;

}

/* XERASE  - routine to clear the screen.  Check to see if the window
 *           configuration has been changed by the window manager (or
 *           by the user).  If so, reset the screen size.  Resizes
 *           done by the window manager will take precedence over resizes
 *           requested by the calling program (assume user resized window
 *           via the window manager).
 *
 *           Clear the pixmap as well as the graphics window.
 *
 *           Note that this routine assumes that XFLUSH has already
 *           been called to flush the buffer and that XCHECK has been
 *           called to check for expose and configure events.
 *
 *  xpixels   - width (in pixels) for graphics window
 *  ypixels   - height (in pixels) for graphics window
 *  orien     - window orientation (i.e., landscape, portrait, or none)
 *  ixret     - width returned to calling program
 *  iyret     - height returned to calling program
 *  back_col  - background color
 *  pix_flag  - 0 = no pixmap generated, 1 = pixmap generated
 *
 */

#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xerase_(xpixels, ypixels, orien, ixret, iyret, back_col, pix_flag)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XERASE_(xpixels, ypixels, orien, ixret, iyret, back_col, pix_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xerase(xpixels, ypixels, orien, ixret, iyret, back_col, pix_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XERASE(xpixels, ypixels, orien, ixret, iyret, back_col, pix_flag)
#endif
#if PRECISION == 0
int  *xpixels, *ypixels, *orien, *back_col, *pix_flag;
int  *ixret, *iyret;
#else
int  xpixels[2], ypixels[2], orien[2], back_col[2], pix_flag[2];
int  ixret[2], iyret[2];
#endif
{

   int   temp_color, temp_color_2;
   int   xpixels_temp, ypixels_temp, orien_temp, back_col_temp;
   int   pix_flag_temp;

#if PRECISION == 0
   xpixels_temp = *xpixels;
   ypixels_temp = *ypixels;
   orien_temp = *orien;
   back_col_temp = *back_col;
   pix_flag_temp = *pix_flag;
#else
   xpixels_temp = xpixels[0];
   ypixels_temp = ypixels[0];
   orien_temp = orien[0];
   back_col_temp = back_col[0];
   pix_flag_temp = pix_flag[0];
#endif
   if (configure_flag == 1) {    /* graphics window re-configured by user */
      /* Get actual height and width set by the window manager */
      XGetWindowAttributes(display, window, &returned_attributes);
      width = returned_attributes.width;
      height = returned_attributes.height;
#if PRECISION == 0
      *ixret = width;
      *iyret = height;
#else
      ixret[0] = width;
      iyret[0] = height;
#endif


   }
   else if (    /* calling program changing width or height of window */
            ((xpixels_temp > 0) && (ypixels_temp > 0) &&
            (xpixels_temp != width || ypixels_temp != height)) ||
            (orien_temp != ORIENTATION_CURRENT)) {
      set_screen(xpixels_temp, ypixels_temp, orien_temp);
      ORIENTATION_CURRENT = orien_temp;
      XUnmapWindow(display,window);
      XResizeWindow(display, window, xsh.width, xsh.height);

      XMapWindow(display, window);
      do {     /* make sure correct window is in place */
          XNextEvent(display, &event);
      } while (event.type != MapNotify || event.xmap.window != window);
      expose_flag = 0;
      configure_flag = 0;

      /* Get actual height and width set by the window manager */
      XGetWindowAttributes(display, window, &returned_attributes);
      width = returned_attributes.width;
      height = returned_attributes.height;
#if PRECISION == 0
      *ixret = width;
      *iyret = height;
#else
      ixret[0] = width;
      iyret[0] = height;
#endif

   }
   else {
#if PRECISION == 0
     *ixret = width;
     *iyret = height;
#else
     ixret[0] = width;
     iyret[0] = height;
#endif
   }
   configure_flag = 0;

   switch (pix_flag_temp) {
      case 0:                         /* user does not want pixmap */
          if (PIXMAP_CURRENT != 0) {  /* get rid of current pixmap */
            PIXMAP_CURRENT = 0;
            XFreePixmap(display, pixmap);
          }
          break;
      case 1:                          /* user wants a pixmap */
          if (PIXMAP_CURRENT != 0) {   /* pixmap already exists */
            XFreePixmap(display, pixmap);
          }
          else {                      /* pixmap does not yet exist */
            PIXMAP_CURRENT = 1;
          }
          pixmap = XCreatePixmap(display, window, width, height, depth);
          break;
      default:
          break;
   }

   xback(back_col_temp);                         /* set background color */
   XClearWindow(display, window);            /* clear the window */
   temp_color = BACKGROUND_CURRENT;
   temp_color_2 = COLOR_CURRENT;
   BACKGROUND_CURRENT = -1;
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
   xfore_(&temp_color);
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
   XFORE_(&temp_color);
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
   xfore(&temp_color);
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
   XFORE(&temp_color);
#endif

   XFillRectangle(display, window, gc, 0, 0, width, height);
/* January 1992.  Follwoing 3 lines added.  */
   if (PIXMAP_CURRENT == 1) {                /* set pixmap to background */
     XFillRectangle(display, pixmap, gc, 0, 0, width, height);
   }
/* End change.  */
   BACKGROUND_CURRENT = temp_color;
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
   xfore_(&temp_color_2);
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
   XFORE_(&temp_color_2);
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
   xfore(&temp_color_2);
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
   XFORE(&temp_color_2);
#endif
/* January 1992.  Following 5 lines commented out */
/* if (PIXMAP_CURRENT == 1) {   */             /* set pixmap to background */
/*   XSetForeground(display, gc, colors[BACKGROUND_CURRENT].pixel); */
/*   XFillRectangle(display, pixmap, gc, 0, 0, width, height);      */
/*   XSetForeground(display, gc, colors[COLOR_CURRENT].pixel);      */
/* }  */
/* End change.  */

   /*  July 1995.  Set flag that xerase routine has been called.
    *  needed by front-end (so won't copy background pixmap before
    *  any graphs have been drawn.
    */

    GRAPH_FLAG = 1;
}

/* XUPDAT - routine to copy pixmap to screen
 *
 * If an expose event has been detected, update the graphics
 * window with the pixmap (if calling program has requested it).
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xupdat_(frontend)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XUPDAT_(frontend)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xupdat(frontend)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XUPDAT(frontend)
#endif
#if PRECISION == 0
int     *frontend;
#else
int     frontend[2];
#endif
{
/*  July 1995.  Add frontend argument.  If frontend active,
 *  automatically update graphics window regardless of expose_flag.
 */

#if PRECISION == 0
   if (*frontend == 0) {
#else
   if (frontend[0] == 0) {
#endif
     if (expose_flag == 1 &&         /* update screen  if expose event */
         PIXMAP_CURRENT == 1) {      /* copy pixmap to screen to update */
         XCopyArea(display, pixmap, window, gc, 0, 0, width, height, 0, 0);
         XFlush(display);           /* do copy immediately */
         expose_flag = 0;
     }
   }

#if PRECISION == 0
   if (*frontend == 1) {
#else
   if (frontend[0] == 1) {
#endif
     if (PIXMAP_CURRENT == 1 &&
         GRAPH_FLAG == 1) {      /* copy pixmap to screen to update */
         XCopyArea(display, pixmap, window, gc, 0, 0, width, height, 0, 0);
         XFlush(display);           /* do copy immediately */
     }
   }

#if PRECISION == 0
   if (*frontend == 0) {
#else
   if (frontend[0] == 0) {
#endif
     if (expose_flag_aux == 1 &&       /* update second screen  if expose event */
         PIXMAP_CURRENT_2 == 1) {    /* copy pixmap to screen to update */
         XCopyArea(display, pixmap2, window2, gc2, 0, 0, width2, height2, 0, 0);
         XFlush(display);           /* do copy immediately */
         expose_flag_aux = 0;
     }
   }

}

/* XCLEAR  - routine to flush the buffer
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xclear_()
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XCLEAR_()
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xclear()
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XCLEAR()
#endif
{
   XFlush(display);
}

/* XSAVEG - routine to copy pixmap to a specified file
 *
 * Save the current pixmap to the specified file.
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xsaveg_(file_name, error_flag)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XSAVEG_(file_name, error_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xsaveg(file_name, error_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XSAVEG(file_name, error_flag)
#endif
#if PRECISION == 0
int     *error_flag;
int     file_name[];
#else
int     *error_flag[2];
int     file_name[];
#endif
{
#if PRECISION == 0
#define MAX_STRING_LEN  128
#else
#define MAX_STRING_LEN  256
#endif
   int      len, istatus;
   char     file_name_string[MAX_STRING_LEN];

   if ( OPEN_FLAG == 0 ){
#if PRECISION == 0
     *error_flag = 3;
#else
     error_flag[0] = 3;
#endif
     return;
   }

   if ( PIXMAP_CURRENT == 0 ){
#if PRECISION == 0
     *error_flag = 2;
#else
     error_flag[0] = 2;
#endif
     return;
   }

   strcpy(file_name_string," ");
   i_to_s(file_name, file_name_string, MAX_STRING_LEN, &len);

   istatus = XWriteBitmapFile(display, file_name_string, pixmap, width, height, -1, -1);
   XFlush(display);           /* do copy immediately */
#if PRECISION == 0
   if (istatus != BitmapSuccess) *error_flag = 2;
#else
   if (istatus != BitmapSuccess) error_flag[0] = 2;
#endif

}

/* XRESTG - routine to copy pixmap from a specified file
 *          The pixmap will be restored to a special window
 *
 * Save the current pixmap to the specified file.
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xrestg_(file_name, title, iwind, iwindn, error_flag)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XRESTG_(file_name, title, iwind, iwindn, error_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xrestg(file_name, title, iwind, iwindn, error_flag)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XRESTG(file_name, title, iwind, iwindn, error_flag)
#endif
#if PRECISION == 0
int     *error_flag;
int     file_name[];
int     iwind[], iwindn[2];
#else
int     *error_flag[2];
int     file_name[];
int     iwind[], iwindn[2];
int     title[];
#endif

{

#if PRECISION == 0
#define MAX_STRING_LEN  128
#else
#define MAX_STRING_LEN  256
#endif
   XTextProperty  WindowName, IconName;
   XWindowAttributes     window_attributes_tmp;
   int      len, istatus;
   int      x_hot, y_hot, iwindn_temp;
   unsigned int  width3, height3;
   char     file_name_string[MAX_STRING_LEN];
/* char     *title_string_2; */
   char     title_string[MAX_STRING_LEN+10];
   static   XSizeHints  xsh2;
   char     *window_name = "1- Pixmap";
   long         itemp;
   int          counter;
   double       atemp1;
   int          window_flag;
   FILE          *ijunk;
#if PRECISION == 1
   int          iplace;
#endif

#if PRECISION == 0
  iwindn_temp = *iwindn;
#else
  iwindn_temp = iwindn[0];
#endif
   if ( OPEN_FLAG == 0 ){
#if PRECISION == 0
     *error_flag = 3;
#else
     error_flag[0] = 3;
#endif
     return;
   }

   strcpy(file_name_string," ");
   i_to_s(file_name, file_name_string, MAX_STRING_LEN, &len);
   strcpy(title_string," ");
   i_to_s(title, title_string, MAX_STRING_LEN+10, &len);

   if (PIXMAP_CURRENT_2 != 0) {    /* Clear current pixmap */
     PIXMAP_CURRENT_2 = 0;
     XFreePixmap(display, pixmap2);
   }

   istatus = XReadBitmapFile(display, window, file_name_string,
             &width2, &height2, &pixmap3, &x_hot, &y_hot);
   XFlush(display);           /* do copy immediately */
#if PRECISION == 0
   if (istatus != BitmapSuccess) {
      *error_flag = 2;
      return;
   }
#else
   if (istatus != BitmapSuccess) {
      error_flag[0] = 2;
      return;
   }
#endif

   pixmap2 = XCreatePixmap(display, window, width, height, depth);
   PIXMAP_CURRENT_2 = 1;
   /*  Now open (or use currently open window) to display the
    *  successfully read pixmap */
   if ( OPEN_FLAG_2 == 0 ){
      OPEN_FLAG_2 = 1;

      window_flag = 0;
      if ( iwindn_temp > 0 ) {
        window_flag = 1;
#if PRECISION == 0
        itemp = 0;
        for ( counter = 0; counter < iwindn_temp; counter++ ) {
           atemp1 = pow(16., (double) counter);
           itemp = itemp + (long) iwind[counter]* (long) atemp1;
        }
#else
        iplace = 0;
        itemp = 0;
        for ( counter = 0; counter < iwindn_temp; counter++ ) {
           atemp1 = pow(16., (double) counter);
           itemp = itemp + (long) iwind[iplace]* (long) atemp1;
           iplace = iplace + 2;
        }
#endif
        window2 = (Window) itemp;

        xsh2 =xsh;
        XGetWindowAttributes(display, window2, &returned_attributes);
        width3 = returned_attributes.width;
        height3 = returned_attributes.height;
        xsh2.x = returned_attributes.x;
        xsh2.y = returned_attributes.y;
        xsh2.width = width3;
        xsh2.height = height3;
        if (width3 < width2 || height3 < height2) {
           XUnmapWindow(display,window2);
           XResizeWindow(display, window2, width2, height2);
           XMapWindow(display, window2);
           XFlush(display);
           expose_flag_aux = 0;
           xsh2.width = width2;
           xsh2.height = height2;
        }
        XSetStandardProperties(display, window2, title_string, title_string,
                              None, argv, argc, &xsh2);
        XSelectInput(display, window2,
           StructureNotifyMask | 
           ExposureMask );     
      }  

      else {

        xsh2 = xsh;
        xsh2.x = DEFAULT_X - 100;
        xsh2.y = DEFAULT_Y - 50;
        xsh2.width = width2;
        xsh2.height = height2;

        window2 = XCreateSimpleWindow(      /* Open graphics window */
                display,                    /* Pointer to Display structure */
                DefaultRootWindow(display), /* Parent for new window */
                xsh2.x,                     /* X position of window */
                xsh2.y,                     /* Y position of window */
                xsh2.width,                 /* Width of window */
                xsh2.height,                /* Height of window */
                BORDER_WIDTH,               /* Pixel width of border */
                black,                      /* Border color */
                white);                     /* Background color */

        value_mask = CWBitGravity;
        XChangeWindowAttributes(display, window2, value_mask,
                 &window_attributes);

#ifdef X11R3  /* Use following for X11 Release 3 and earlier */
        XSetStandardProperties(display, window2, title_string, title_string,
                               None, argv, argc, &xsh);
        XSetWMHints(display, window2, &xwmh);
        XSetClassHint(display, window2, &xch);
#else  /* X11R4 or later */
    
/*     *title_string_2 = &title_string;  */
       if (XStringListToTextProperty(&window_name, 1, &WindowName) == 0) {
#if PRECISION == 0
          *error_flag = 1;
#else
          error_flag[0] = 1;
#endif
          return;
       }
       XSetWMProperties(display, window2, &WindowName, &WindowName, 
                        argv, argc, &xsh2, &xwmh, &xch);
#endif

       XSelectInput(display, window2,
           StructureNotifyMask | 
           ExposureMask );     
       XMapWindow(display, window2); /* Map the window (make visible) */
       XFlush(display);              /* Flush the buffer */
       do {
            XNextEvent(display, &event);
          } while (event.type != MapNotify || event.xmap.window != window2);
     }

   }
   /* If window exists, only need to check if the current width and
    * height are appropriate.  */

   else {
       xsh2 =xsh;
       XGetWindowAttributes(display, window2, &returned_attributes);
       xsh2.x = returned_attributes.x;
       xsh2.y = returned_attributes.y;
       width3 = returned_attributes.width;
       height3 = returned_attributes.height;
       xsh2.width = width3;
       xsh2.height = height3;
       if (width3 < width2 || height3 < height2) {
          XUnmapWindow(display,window2);
          XResizeWindow(display, window2, width2, height2);
          XMapWindow(display, window2);
          XFlush(display);
          expose_flag_aux = 0;
          xsh2.width = width2;
          xsh2.height = height2;
       }
         XSetStandardProperties(display, window2, title_string, title_string,
                              None, argv, argc, &xsh2);
   }

   /* Following code is same for either a new window or a previously
    * created window.  */
   gc2 = XCreateGC(display, window2, 0, &gcvalues);/* Create graphics context */
   XSetState(display, gc2, black, white, GXcopy, AllPlanes);
   XSetForeground(display,gc2,BlackPixel(display,DefaultScreen(display)));
   XSetBackground(display,gc2,WhitePixel(display,DefaultScreen(display)));
   XSetGraphicsExposures(display,gc2,False);
   XCopyPlane(display,pixmap3,pixmap2,gc2,0,0,width2,height2,0,0,1);
   XFreePixmap(display,pixmap3);
   XCopyArea(display, pixmap2, window2, gc2, 0, 0, width2, height2, 0, 0);
   XFlush(display);
   expose_flag_aux = 0;

}

/* XCYCLE - routine to cycle through previously created pixmaps
 *          The button pressed is stored in ibutton
 *          (1=left, 2=middle, 3=right)
 *          This routine only processes a SINGLE button event.  The
 *          calling routine reads ibutton and either redraws another
 *          pixmap or exits.
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xcycle_(error_flag, ibutton)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XCYCLE_(error_flag, ibutton)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xcycle(error_flag, ibutton)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XCYCLE(error_flag, ibuttton)
#endif
#if PRECISION == 0
int     *error_flag;
int     *ibutton;
#else
int     *error_flag[2];
int     *ibutton[2];
#endif
{
     XEvent   event;        /* holds Xserver events */
     int      x, y;         /* the last X pointer position */
     int      new_x, new_y; /* a new X pointer position */
     unsigned int dummy;    /* placeholder for unwanted return value */
     int      done;

   if ( OPEN_FLAG == 0 ){
#if PRECISION == 0
     *error_flag = 3;
#else
     error_flag[0] = 3;
#endif
     return;
   }

   if ( PIXMAP_CURRENT == 0 ){
#if PRECISION == 0
     *error_flag = 2;
#else
     error_flag[0] = 2;
#endif
     return;
   }

     XSelectInput(display, window2,    /* Types of graphic input to accept */
       StructureNotifyMask |          /* Window notification events */
       ExposureMask |                 /* Expose events */
       ButtonPressMask |              /* Button press */
       ButtonMotionMask |             /* Pointer moves with button pressed */
       PointerMotionMask);            /* Pointer moves in window */

       done = 0;
       while (done == 0) {         /* loop until button press event */

          XNextEvent(display, &event);   /* get next event from queue */
          switch (event.type) {
          case DestroyNotify:            /* window has been destroyed */
              XFreeGC(display, gc2);
              XDestroyWindow(display,window2);
#if PRECISION == 0
              *error_flag = 1;
#else
              error_flag[0] = 1;
#endif
              done = 1;
              break;
          case Expose:                   /* expose event */
              if(event.xexpose.count == 0) {
                expose_flag_aux = 1;
              }
              break;
          case ConfigureNotify:          /* window has been reconfigured */
              break;
          case MotionNotify:             /* pointer motion */
          /*  XQueryPointer(display, window2,
                            &dummy, &dummy,
                            &dummy, &dummy,
                            &new_x, &new_y,
                            &mask);
              x = new_x;
              y = new_y;    */
              break;
          case ButtonPress:     /* Button event */
#if PRECISION == 0
              *ibutton = event.xbutton.button;
        /*    *ixret = event.xbutton.x;
              *iyret = event.xbutton.y;   */
#else
              ibutton[0] = event.xbutton.button;
       /*     ixret[0] = event.xbutton.x;
              iyret[0] = event.xbutton.y; */
#endif
              done = 1;
              break;
          default:
              break;
          }       /* end switch */
       }          /* end while */

       XSelectInput(display, window2,    /* Reset default event selection */
         StructureNotifyMask |          /* Window notification events */
         ExposureMask);                 /* Expose events */


}
/* XEND   - routine to end X11.  Close the display.
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xend_()
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XEND_()
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xend()
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XEND()
#endif

{
     if (OPEN_FLAG_2 != 0) {
        XFreeGC(display,gc2);
        XDestroyWindow(display,window2);
     }
     OPEN_FLAG_2 = 0;

     if (OPEN_FLAG != 0) {
        XFreeGC(display,gc);
        XDestroyWindow(display,window);
        XCloseDisplay(display);
     }
     OPEN_FLAG = 0;

}

/* XFORE  - routine to set the foreground color.  Specify the color as
 *          an index.
 *       INDEX   COLOR_TYPE = 0        COLOR_TYPE = 1
 *       =====   ==============        ==============
 *           0 - black                 black
 *           1 - white                 white
 *           2 - green                 green
 *           3 - yellow                yellow
 *           4 - red                   red
 *           5 - blue                  blue
 *           6 - magenta               magenta
 *           7 - cyan                  cyan
 *           8 - yellow orange         orange
 *           9 - yellow green          yellow green
 *          10 - blue green            dark green
 *          11 - green blue            light blue
 *          12 - blue violet           blue violet
 *          13 - red violet            violet red
 *          14 - dark grey             dark slate gray
 *          15 - light grey            light gray
 *          16 -                       aquamarine
 *          17 -                       brown
 *          18 -                       cadet blue
 *          19 -                       coral
 *          20 -                       cornflower blue
 *          21 -                       dark olive green
 *          22 -                       dark orchid
 *          23 -                       dark slate blue
 *          24 -                       dark turquoise
 *          25 -                       firebrick       
 *          26 -                       forest green 
 *          27 -                       gold
 *          28 -                       goldenrod
 *          29 -                       gray
 *          30 -                       indian red 
 *          31 -                       khaki
 *          32 -                       dim gray   
 *          33 -                       light blue steel 
 *          34 -                       lime green
 *          35 -                       maroon
 *          36 -                       medium aquamarine 
 *          37 -                       medium blue
 *          38 -                       medium forest green
 *          39 -                       medium goldenrod
 *          40 -                       medium orchid
 *          41 -                       medium sea green
 *          42 -                       medium slate blue
 *          43 -                       medium spring green
 *          44 -                       medium turquoise
 *          45 -                       medium violet red
 *          46 -                       midnight blue
 *          47 -                       navy
 *          48 -                       orange red
 *          49 -                       orchid
 *          50 -                       pale green 
 *          51 -                       pink 
 *          52 -                       plum
 *          53 -                       purple
 *          54 -                       salmon
 *          55 -                       sea green 
 *          56 -                       sienna
 *          57 -                       sky blue 
 *          58 -                       slate blue
 *          59 -                       spring green
 *          60 -                       steel blue 
 *          61 -                       tan  
 *          62 -                       thistle    
 *          63 -                       turquoise
 *          64 -                       violet
 *          65 -                       wheat 
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xfore_(index)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XFORE_(index)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xfore(index)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XFORE(index)
#endif
#if PRECISION == 0
int   *index;
#else
int   index[2];
#endif
{
      unsigned long  temp;
      int            temp2;
      int            index_temp;

#if PRECISION == 0
      index_temp = *index;
#else
      index_temp = index[0];
#endif
      if (index_temp == COLOR_CURRENT) return;
      COLOR_CURRENT = index_temp;

      if (index_temp == BACKGROUND_CURRENT) {    /* test if equal background */
        if (index_temp == 0) {                   /* set to white */
          COLOR_CURRENT = 1;
          XSetForeground(display, gc, white);
        }
        else {                               /* set to black */
          COLOR_CURRENT = 0;
          XSetForeground(display, gc, black);
        }
        return;
      }

      if (index_temp < 0) {       /* Gray scale requested */
        temp2 = index_temp;
        temp2 = -temp2;
        if (temp2 > MAX_GRAY) temp2 = MAX_GRAY;
        if (color_list_gray[temp2] == 0) {   /* Color unavailable */
           if (BACKGROUND_CURRENT != 0) {  /* set to black */
             temp2 = 0;
           }
           else {                          /* set to white */
             temp2 = 1;
           }
           COLOR_CURRENT = temp2;
           XSetForeground(display, gc, colors[temp2].pixel);
        }
        else {
           XSetForeground(display, gc, grays[temp2].pixel);
        }
        return;
      } 

      if (color_flag < 2) {   /* monochrome devices */
        switch (index_temp) {
           case 0:       /* black foreground color */
               temp = black;
               COLOR_CURRENT = 0;
               break;
           case 1:       /* white foreground color */
               temp = white;
               COLOR_CURRENT = 1;
               break;
           default:      /* default, set to black */
               temp = black;
               COLOR_CURRENT = 0;
               break;
         }
         XSetForeground(display, gc, temp);
       }
       else {          /* color devices */
         temp2 = index_temp;
         if (temp2 > max_colors - 1) {    /* index out of range */
           if (BACKGROUND_CURRENT != 0) {  /* set to black */
             temp2 = 0;
           }
           else {                          /* set to white */
             temp2 = 1;
           }
         }
         else if (color_list[temp2] == 0) { /* color unavailable */
           if (BACKGROUND_CURRENT != 0) {  /* set to black */
             temp2 = 0;
           }
           else {                          /* set to white */
             temp2 = 1;
           }
         }
         COLOR_CURRENT = temp2;
         XSetForeground(display, gc, colors[temp2].pixel);
       }

}


/* xback  - routine to set the background color.  Specify the color as
 *          an index.  See comments for xfore routine above for the 
 *          index to color mapping.
 *
 * Note: the background color only applies in the following 4 cases:
 *          XDrawImageString
 *          XCopyPlane
 *          drawing lines with line style LineDoubleDash
 *          filling with fill style of FillOpaqueStippled
 *       Although Dataplot does not currently use any of these features,
 *       the background value will be set (in case any of these are
 *       implemented at a future date).  However, the background will
 *       be set by doing a solid fill rectangle of the entire screen
 *       (setting the foreground color to the background color).
 *
 */
void xback(index)
int  index;
{

      unsigned long temp;
      int           temp2;

      if (index == BACKGROUND_CURRENT) return;

      if (color_flag < 2) {   /* monochrome devices */
        temp2 = index;
        if (temp2 < 0 || temp2 > 1) temp2 = 2;
        switch (temp2) {
           case 0:       /* black background color */
               temp = black;
               BACKGROUND_CURRENT = 0;
               break;
           case 1:       /* white background color */
               temp = white;
               BACKGROUND_CURRENT = 1;
               break;
           case 2:
               temp = white;
               BACKGROUND_CURRENT = 1;
               break;
           default:      /* default, set to white */
               temp = white;
               BACKGROUND_CURRENT = 1;
               break;
         }
         XSetBackground(display, gc, temp);
       }
       else {          /* color devices */
         temp2 = index;
         if (temp2 < 0) temp2 = 1;
         if (temp2 > max_colors - 1) {    /* index out of range */ 
           if (BACKGROUND_CURRENT != 1) {  /* set to white */
             temp2 = 1;
             BACKGROUND_CURRENT = 1;
           }
           else {                          /* set to black */
             temp2 = 0;
             BACKGROUND_CURRENT = 0;
           }
         }
         else if (color_list[temp2] == 0) { /* color unavailable */
           if (BACKGROUND_CURRENT != 1) {  /* set to white */
             temp2 = 1;
             BACKGROUND_CURRENT = 1;
           }
           else {                          /* set to black */
             temp2 = 0;
             BACKGROUND_CURRENT = 0;
           }
         }
         BACKGROUND_CURRENT = temp2;
         XSetBackground(display, gc, colors[temp2].pixel);
       }
}

/* XLATTR  - set line attributes.  Note that the attribute will only be
 *           set if it is being changed (i.e., test against current
 *           value of the attribute).
 *
 * index - parameter that sets the value
 * icode - identify which attribute to set
 *         1 - set the line width in pixels
 *         2 - set the line style (i.e., solid or dash).  Currently only
 *             three dash patterns are supported.  However, additional ones
 *             may be added.
 *             0 - solid line
 *             1 - dash line
 *             2 - dotted line
 *             3 - dot-dash line (dash2 pattern)
 *             4 - dash3
 *             5 - dash4
 *         3 - set the line cap
 *             0 - cap butt (end-caps squared off at endoints perpindicular
 *                 to the slope of the line)
 *             1-  cap not last (similar to cap butt, but for 1 pixel wide
 *                 line, do not draw last point of line)
 *             2 - cap round (end-caps are circles with diameter equal to
 *                 line width)
 *             3 - cap projecting (end caps are squared off similar to cap
 *                 butt, however they project half the line width beyond
 *                 the end points)
 *         4 - set the line join
 *             0 - miter join (outer edges of wide line extended so that
 *                 they meet at same angle as would narow lines)
 *             1 - round join (corners are rounded off using a circle of
 *                 diameter equal to line width centered at join point)
 *             2 - bevel join (intersecting endpoints of lines both drawn
 *                 as if they were end points with cap butt style.  The
 *                 small triangle created is filled).
 *
 */
#define MAX_WIDTH  15
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xlattr_(index, icode)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XLATTR_(index, icode)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xlattr(index, icode)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XLATTR(index, icode)
#endif
#if PRECISION == 0
int    *index, *icode;
#else
int    index[2], icode[2];
#endif
{
unsigned long  valuemask;
int            dash_offset;
int            width_temp;
int            temp;
int            icode_temp, index_temp;
static char    dot [] = {1,2};
static char    dash [] = {6,3};
static char    dash3 [] = {3,3};
static char    dash4 [] = {2,4};
static char    dash_dot [] = {9,3,3,3};

#if PRECISION == 0
   icode_temp = *icode;
   index_temp = *index;
#else
   icode_temp = icode[0];
   index_temp = index[0];
#endif
   switch (icode_temp) {
      case 1:         /* set the line width */
          if (index_temp == WIDTH_CURRENT) break;
          valuemask = GCLineWidth;
          if (index_temp < 2) {
             gcvalues.line_width = 0;
          }
          else {
             width_temp = index_temp;
             if (width_temp > MAX_WIDTH) width_temp = MAX_WIDTH;
             gcvalues.line_width = width_temp;
          }
          XChangeGC(display, gc, valuemask, &gcvalues);
          WIDTH_CURRENT = index_temp;
          break;
      case 2:         /* set the line style */
          if (index_temp == LINE_STYLE_CURRENT) break;
          valuemask = GCLineStyle;
          dash_offset = 0;
          temp = index_temp;
          if (temp > 3) temp = 3;
          switch (temp) {    /* index determines the style */
             case 0:         /* solid line */
                 gcvalues.line_style = LineSolid;
                 break;
             case 1:         /* dashed line */
                 gcvalues.line_style = LineOnOffDash;
                 XSetDashes(display, gc, dash_offset, dash, 2);
                 break;
             case 2:         /* dotted line */
                 gcvalues.line_style = LineOnOffDash;
                 XSetDashes(display, gc, dash_offset, dot, 2);
                 break;
             case 3:         /* dash-dot line */
                 gcvalues.line_style = LineOnOffDash;
                 XSetDashes(display, gc, dash_offset, dash_dot, 4);
                 break;
             case 4:         /* dash3 */
                 gcvalues.line_style = LineOnOffDash;
                 XSetDashes(display, gc, dash_offset, dash3, 2);
                 break;
             case 5:         /* dash4 line */
                 gcvalues.line_style = LineOnOffDash;
                 XSetDashes(display, gc, dash_offset, dash4, 2);
                 break;
              default:
                 gcvalues.line_style = LineSolid;
                 break;
          }
          XChangeGC(display, gc, valuemask, &gcvalues);
          LINE_STYLE_CURRENT = index_temp;
          break;
      case 3:         /* set the line cap style */
          if (index_temp == CAP_STYLE_CURRENT) break;
          valuemask = GCCapStyle;
          switch (index_temp) {  /* index determines the style */
             case 0:         /* cap butt */
                 gcvalues.cap_style = CapButt;
                 break;
             case 1:         /* cap round */
                 gcvalues.cap_style = CapRound;
                 break;
             case 2:         /* cap not last */
                 gcvalues.cap_style = CapNotLast;
                 break;
             case 3:         /* cap projecting */
                 gcvalues.cap_style = CapProjecting;
                 break;
             default:
                 gcvalues.cap_style = CapButt;
                 break;
          }
          XChangeGC(display, gc, valuemask, &gcvalues);
          CAP_STYLE_CURRENT = index_temp;
          break;
      case 4:         /* set the join style */
          if (index_temp == JOIN_STYLE_CURRENT) break;
          valuemask = GCJoinStyle;
          switch (index_temp) {  /* index determines the style */
             case 0:         /* miter join */
                 gcvalues.join_style = JoinMiter;
                 break;
             case 1:         /* round join */
                 gcvalues.join_style = JoinRound;
                 break;
             case 2:         /* bevel join */
                 gcvalues.join_style = JoinBevel;
                 break;
             default:
                 gcvalues.join_style = JoinMiter;
                 break;
          }
          XChangeGC(display, gc, valuemask, &gcvalues);
          JOIN_STYLE_CURRENT = index_temp;
          break;
      default:
          break;
   }
}

/* XDRAW  - draw a polyline.  The attributes of the line have been
 *          previously set (by the XLATTR routine).
 *
 * xpts   - contains the x coordinates
 * ypts   - contains the y coordinates
 * npts   - the number of points to plot
 *
 */
#define MAX_LINE_POINTS  500
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xdraw_(xpts, ypts, npts)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XDRAW_(xpts, ypts, npts)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xdraw(xpts, ypts, npts)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XDRAW(xpts, ypts, npts)
#endif
int   xpts[], ypts[];
#if PRECISION == 0
int   *npts;
#else
int   npts[2];
#endif
{
   XPoint  points[MAX_LINE_POINTS];
   int     npts_temp;
#if PRECISION == 0
   npts_temp = *npts;
#else
   npts_temp = npts[0];
#endif

   if (npts_temp == 2) {      /* draw 2 points */
      int  x1, y1, x2, y2;
#if PRECISION == 0
      x1 = xpts[0];
      x2 = xpts[1];
      y1 = ypts[0];
      y2 = ypts[1];
#else
      x1 = xpts[0];
      x2 = xpts[2];
      y1 = ypts[0];
      y2 = ypts[2];
#endif
      XDrawLine(display, window, gc, x1, y1, x2, y2);
      if (PIXMAP_CURRENT == 1) {
        XDrawLine(display, pixmap, gc, x1, y1, x2, y2);
      }
      return;
   }
   else if (npts_temp > 2) {     /* more than 2 points */
#if PRECISION == 0
     int  i, ilower, iupper, nloops, temp, itimes;
     iupper = 0;
     nloops = 0;
     while (nloops != 1) {  /* do MAX_LINE_POINTS per loop */
        ilower = iupper;
        iupper = ilower + MAX_LINE_POINTS - 1;
        if (iupper > npts_temp) {
          iupper = npts_temp;
          nloops = 1;
        }
        temp = 0;
        itimes = iupper - ilower;
        for (i = 0; i < itimes; i++) {
           points[i].x = xpts[i + ilower];
           points[i].y = ypts[i + ilower];
           temp = temp + 1;
        }
        XDrawLines(display, window, gc, points, temp, CoordModeOrigin);
        if (PIXMAP_CURRENT == 1) {
          XDrawLines(display, pixmap, gc, points, temp, CoordModeOrigin);
        }
     }  /* end while loop */
   }    /* end of npts loop */
#else
     int  i, ilower, iupper, nloops, temp, itimes;
     iupper = 0;
     nloops = 0;
     while (nloops != 1) {  /* do MAX_LINE_POINTS per loop */
        ilower = iupper;
        iupper = ilower + MAX_LINE_POINTS - 1;
        if (iupper > npts_temp) {
          iupper = npts_temp;
          nloops = 1;
        }
        temp = 0;
        itimes = iupper - ilower;
        for (i = 0; i < itimes; i++) {
           points[i].x = xpts[2*(i + ilower)];
           points[i].y = ypts[2*(i + ilower)];
           temp = temp + 1;
        }
        XDrawLines(display, window, gc, points, temp, CoordModeOrigin);
        if (PIXMAP_CURRENT == 1) {
          XDrawLines(display, pixmap, gc, points, temp, CoordModeOrigin);
        }
     }  /* end while loop */
   }    /* end of npts loop */
#endif

}

/* XPOINT - draw a point.
 *          previously set (by the XLATTR routine).
 *
 * ix     - contains the x coordinate
 * iy     - contains the y coordinate
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xpoint_(ix, iy)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XPOINT_(ix, iy)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xpoint(ix, iy)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XPOINT(ix, iy)
#endif
#if PRECISION == 0
int   *ix, *iy;
#else
int   ix[2], iy[2];
#endif
{
#if PRECISION == 0
   XDrawPoint(display, window, gc, *ix, *iy);
   if (PIXMAP_CURRENT == 1) {
     XDrawPoint(display, pixmap, gc, *ix, *iy);
#else
   XDrawPoint(display, window, gc, ix[0], iy[0]);
   if (PIXMAP_CURRENT == 1) {
     XDrawPoint(display, pixmap, gc, ix[0], iy[0]);
#endif
   }

}

/* XCIRC  - draw a circle.  Note that the circle may be either filled or 
 *          unfilled.  For a filled circle, do twice, (once for the 
 *          outline, once to fill the interior).
 *
 * ix     - contains the x coordinate for the center of the circle
 * iy     - contains the y coordinate for the center of the circle 
 * irad   - radius
 * ifill  - 0 for unfilled circle, 1 for filled circle
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xcirc_(ix, iy, irad, ifill)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XCIRC_(ix, iy, irad, ifill)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xcirc(ix, iy, irad, ifill)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XCIRC(ix, iy, irad, ifill)
#endif
#if PRECISION == 0
int   *ix, *iy, *irad, *ifill;
#else
int   ix[2], iy[2], irad[2], ifill[2];
#endif
{

   int   xpos, ypos, iwidth, iheight, iang1, iang2, ir;

   iang1 = 0;
   iang2 = 23040;
#if PRECISION == 0
   ir = *irad;
   xpos = *ix - *irad;
   ypos = *iy - *irad;
#else
   ir = irad[0];
   xpos = ix[0] - irad[0];
   ypos = iy[0] - irad[0];
#endif
   iwidth = 2 * ir;
   iheight = 2 * ir;
   XDrawArc(display, window, gc, xpos, ypos, iwidth, iheight, iang1, iang2);
   if (PIXMAP_CURRENT == 1) {
     XDrawArc(display, pixmap, gc, xpos, ypos, iwidth, iheight, iang1, iang2);
   }
#if PRECISION == 0
   if (*ifill != 0) {
#else
   if (ifill[0] != 0) {
#endif
     XFillArc(display, window, gc, xpos, ypos, iwidth, iheight, iang1, iang2);
     if (PIXMAP_CURRENT == 1) {
       XDrawArc(display, pixmap, gc, xpos, ypos, iwidth, iheight, iang1, iang2);
     }
   }

}

/* XREGFL - fill a region.  Rectangular regions will be filled differently
 *          non-rectangular regions.  Dataplot only handles convex polygons,
 *          so set this (for faster performance).  This routine only does
 *          solid fills.  Hatch patterns must be drawn
 *          by the calling program (i.e., send the individual lines to
 *          the XDRAW routine).
 *
 * xpts   - contains the x coordinates
 * ypts   - contains the y coordinates
 * npts   - the number of points in the polygon (if 2, assume a rectangle,
 *          otherwise, a convex polygon)
 *
 */
#define MAX_REG_POINTS  1000
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xregfl_(xpts, ypts, npts)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XREGFL_(xpts, ypts, npts)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xregfl(xpts, ypts, npts)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XREGFL(xpts, ypts, npts)
#endif
int   xpts[], ypts[];
#if PRECISION == 0
int   *npts;
#else
int   npts[2];
#endif
{
   XPoint  points[MAX_REG_POINTS];
   int     npts_temp;

#if PRECISION == 0
   npts_temp = *npts;
#else
   npts_temp = npts[0];
#endif
   if (npts_temp == 2) {      /* rectangle */
      int  x1, y1, x2, y2, rect_height, rect_width;
      if (xpts[0] <= xpts[1]) {
#if PRECISION == 0
        x1 = xpts[0];
        x2 = xpts[1];
#else
        x1 = xpts[0];
        x2 = xpts[2];
#endif
        rect_width = x2 - x1 + 1;
      }
      else {
#if PRECISION == 0
        x1 = xpts[1];
        x2 = xpts[0];
#else
        x1 = xpts[2];
        x2 = xpts[0];
#endif
        rect_width = x2 - x1 + 1;
      }
      if (ypts[0] <= ypts[1]) {
#if PRECISION == 0
        y1 = ypts[0];
        y2 = ypts[1];
#else
        y1 = ypts[0];
        y2 = ypts[2];
#endif
        rect_height = y2 - y1 + 1;
      }
      else {
#if PRECISION == 0
        y1 = ypts[1];
        y2 = ypts[0];
#else
        y1 = ypts[2];
        y2 = ypts[0];
#endif
        rect_height = y2 - y1 + 1;
      }
      XFillRectangle(display, window, gc, x1, y1, rect_width, rect_height);
      if (PIXMAP_CURRENT == 1) {
        XFillRectangle(display, pixmap, gc, x1, y1, rect_width, rect_height);
      }
   }
   else if (npts_temp > 2) {     /* convex polygon */
      int  i, temp;
      temp = npts_temp;
      if( npts_temp > MAX_REG_POINTS) temp = MAX_REG_POINTS;
      for (i = 0; i < temp; i++) {
#if PRECISION == 0
         points[i].x = xpts[i];
         points[i].y = ypts[i];
#else
         points[i].x = xpts[2*i];
         points[i].y = ypts[2*i];
#endif
      }
      /* June 1994.  Use Complex instead of Convex (for possibly
         self-intersecting polygons.  X11 has problem with
         PLOT SIN(X) FOR X = 0 0.1 22 (i.e., more than 1 cycle).  
         The choice of fill rule does not seem to make a difference, 
         so leave as default.  Added a SET X11 HARDWARE FILL ON/OFF. */
   /* XSetFillRule(display,gc,EvenOddRule);  */
   /* XSetFillRule(display,gc,WindingRule);  */
      XFillPolygon(display,window,gc,points,temp,Convex,CoordModeOrigin);
      if (PIXMAP_CURRENT == 1) {
        XFillPolygon(display,pixmap,gc,points,temp,Convex,CoordModeOrigin);
      }
   }

}
/* XTATTR - set the font for drawing text strings.  Note that the fonts
 *          available on a particular workstation can vary, so a test
 *          is made to see if the font exists.  If not, the 8x13 font
 *          will be used (this should be available on all X
 *          workstations.
 *
 *          It is the calling programs responsibility to provide a
 *          valid font name.  This routine does no checking for valid
 *          names since it is possible for local sites to have their own
 *          predefined font names.  The calling program should be sure
 *          to end the font name string with a null (i.e., ascii 0).
 *
 *          In order to avoid excessive reloading of the same font, the
 *          current font name is stored.  A change is made only if the
 *          requested font differs from the current font.
 *
 * font        - name of font
 * error       - 0 - valid font,
 *               1 - invalid font, leave current font in place
 *               2 - invalid font, set default
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xtattr_(font, error)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XTATTR_(font, error)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xtattr(font, error)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XTATTR(font, error)
#endif
int    font[];
#if PRECISION == 0
int    *error;
#else
int    error[2];
#endif
{

   int          itest;          /* temporary variables */
   int          len;            /* number of characters in font name */
   char         font_name[80];  /* converted font name */
   char         *font_name_2;   
   int          i;
   int          direction_hint, font_ascent, font_descent, font_gap;
   XCharStruct  overall;

   strcpy(font_name," ");
#if PRECISION == 0
   i_to_s(font, font_name, 80, &len);
#else
   i_to_s(font, font_name, 160, &len);
#endif

   /* Check current font against requested font */
   itest = strcmp(font_name, FONT_NAME_CURRENT);
   if (itest != 0) {
     if (strcmp(FONT_NAME_CURRENT,FONT_NULL) != 0) {
       XFreeFont(display, font_struct);      /* free default font */
     }
     font_name_2 = &font_name[0];
     font_struct = XLoadQueryFont (display, font_name_2);
     if (font_struct == 0) {
       if (strcmp(FONT_NAME_CURRENT,FONT_NULL) == 0)  { 
          strcpy(font_name,FONT_NAME_DEFAULT); /* load default font */
#if PRECISION == 0
         *error = 2;
#else
         error[0] = 2;
#endif
       }
       else {                              /* leave current font */
         strcpy(font_name, FONT_NAME_CURRENT);
#if PRECISION == 0
         *error = 1;
#else
         error[0] = 1;
#endif
       }
       font_name_2 = &font_name[0];
       font_struct = XLoadQueryFont(display, font_name_2);
     }
     strcpy(FONT_NAME_CURRENT, font_name);
     XSetFont(display, gc, font_struct->fid);  /* Set the font */
     XTextExtents(font_struct, " ", 0, &direction_hint, &font_ascent,
          &font_descent, &overall);
     font_gap = (font_ascent + font_descent) * .20;
     FONT_HEIGHT_CURRENT = font_ascent + font_descent;
     FONT_GAP_CURRENT = font_gap;
   }
}

/* XTEXTH - draw a horizontal text string.
 *
 *          Use XDrawString rather than XDrawText so that background pixels
 *          are not changed.  This is so that other lines that may intersect
 *          the character box will not be blanked out.
 *
 * string - text string to draw
 * ixpos  - x position
 * iypos  - y position
 * ijusth - justification (horizontal)
 *          0 - left justified
 *          1 - center justified
 *          2 - right justified
 * ijustv - justiciation (vertical)
 *          0 - center justified
 *          1 - bottom justified
 *          2 - top justified
 * error  - error flag
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xtexth_(string, ixpos, iypos, ijusth, ijustv, error)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XTEXTH_(string, ixpos, iypos, ijusth, ijustv, error)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xtexth(string, ixpos, iypos, ijusth, ijustv, error)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XTEXTH(string, ixpos, iypos, ijusth, ijustv, error)
#endif
int    string[];
#if PRECISION == 0
int    *ixpos, *iypos, *ijusth, *ijustv, *error;
#else
int    ixpos[2], iypos[2], ijusth[2], ijustv[2], error[2];
#endif
{

   int          itest, itempx, itempy;   /* temporary variables */
   int          len;                     /* number of characters in string */
   int          string_width;            /* width of string in pixels */
   char         string2[130];            /* converted string */
   int          i;
   int          ixpos_temp, iypos_temp, ijusth_temp, ijustv_temp;

#if PRECISION == 0
   ixpos_temp = *ixpos;
   iypos_temp = *iypos;
   ijusth_temp = *ijusth;
   ijustv_temp = *ijustv;
#else
   ixpos_temp = ixpos[0];
   iypos_temp = iypos[0];
   ijusth_temp = ijusth[0];
   ijustv_temp = ijustv[0];
#endif

#if PRECISION == 0
   i_to_s(string, string2, 130, &len);
#else
   i_to_s(string, string2, 260, &len);
#endif
   string_width = XTextWidth(font_struct, string2, len);

   switch (ijusth_temp) {
      case 0:                       /* Left justified string */
          itempx = ixpos_temp;
          break;
      case 1:                       /* Center justified string */
          itempx = ixpos_temp - (string_width/2);
          break;
      case 2:                       /* Right justified string */
          itempx = ixpos_temp - string_width;
          break;
      default:
          itempx = ixpos_temp;
          break;
   }
   switch (ijustv_temp) {
      case 0:                       /* Center justified string */
          itempy = iypos_temp + (FONT_HEIGHT_CURRENT/2.0);
          break;
      case 1:                       /* Bottom justified string */
          itempy = iypos_temp;
          break;
      case 2:                       /* Top justified string */
          itempy = iypos_temp + FONT_HEIGHT_CURRENT;
          break;
      default:
          itempy = iypos_temp + (FONT_HEIGHT_CURRENT/2.0);
          break;
    }


    XDrawString(display, window, gc, itempx, itempy, string2, len);
    if (PIXMAP_CURRENT == 1) {
      XDrawString(display, pixmap, gc, itempx, itempy, string2, len);
    }

}

/* XTEXTV - draw a horizontal text string.
 *
 *          Use XDrawString rather than XDrawText so that background pixels
 *          are not changed.  This is so that other lines that may intersect
 *          the character box will not be blanked out.
 *
 * string - text string to draw
 * ixpos  - x position
 * iypos  - y position
 * ijusth - justification (horizontal)
 *          0 - left justified
 *          1 - center justified
 *          2 - right justified
 * ijustv - justiciation (vertical)
 *          0 - center justified
 *          1 - bottom justified
 *          2 - top justified
 * error  - error flag
 *
 */
#if APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 1
void xtextv_(string, ixpos, iypos, ijusth, ijustv, error)
#elif APPEND_UNDERSCORE == 1 && SUBROUTINE_CASE == 0
void XTEXTV_(string, ixpos, iypos, ijusth, ijustv, error)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 1
void xtextv(string, ixpos, iypos, ijusth, ijustv, error)
#elif APPEND_UNDERSCORE == 0 && SUBROUTINE_CASE == 0
void XTEXTV(string, ixpos, iypos, ijusth, ijustv, error)
#endif
int    string[];
#if PRECISION == 0
int    *ixpos, *iypos, *ijusth, *ijustv, *error;
#else
int    ixpos[2], iypos[2], ijusth[2], ijustv[2], error[2];
#endif
{

   int          itest, itempx, itempy;   /* temporary variables */
   int          len;                     /* number of characters in string */
   int          y_pix_len;               /* height of entire string */
   int          string_width;            /* width of string in pixels */
   char         string2[130];            /* converted string */
   int          i, ijunk;
#if PRECISION == 0
   int          string3[2];              /* one character at a time */
#else
   int          string3[4];              /* one character at a time */
#endif
   int          ixpos_temp, iypos_temp, ijusth_temp, ijustv_temp;

#if PRECISION == 0
   ixpos_temp = *ixpos;
   iypos_temp = *iypos;
   ijusth_temp = *ijusth;
   ijustv_temp = *ijustv;
#else
   ixpos_temp = ixpos[0];
   iypos_temp = iypos[0];
   ijusth_temp = ijusth[0];
   ijustv_temp = ijustv[0];
#endif


#if PRECISION == 0
   i_to_s(string, string2, 130, &len);
#else
   i_to_s(string, string2, 260, &len);
#endif
   y_pix_len = len * (FONT_HEIGHT_CURRENT + FONT_GAP_CURRENT);

   switch (ijustv_temp) {
      case 0:                       /* Center justified string */
          itempy = -(y_pix_len/2) + FONT_HEIGHT_CURRENT;
          break;
      case 1:                       /* Bottom justified string */
          itempy = -y_pix_len + FONT_HEIGHT_CURRENT;
          break;
      case 2:                       /* Top justified string */
          itempy = FONT_HEIGHT_CURRENT;
          break;
      default:
          itempy = -(y_pix_len/2) + FONT_HEIGHT_CURRENT;
          break;
    }
    itempy = iypos_temp + itempy;

#if PRECISION == 0
   string3[1] = 0;
   for (i = 0; i < len; i++) {  /* plot each character one at a time */
      string3[0] = string[i];
      i_to_s(string3,string2, 2, &ijunk);
      string_width = XTextWidth(font_struct, string2, 1);

     switch (ijusth_temp) {
        case 0:                       /* Left justified string */
            itempx = 0;
            break;
        case 1:                       /* Center justified string */
            itempx = (string_width/2);
            break;
        case 2:                       /* Right justified string */
            itempx = string_width;
            break;
        default:
            itempx = ixpos_temp;
            break;
     }

     itempx = ixpos_temp - itempx;
     XDrawString(display, window, gc, itempx, itempy, string2, 1);
     if (PIXMAP_CURRENT) {
       XDrawString(display, pixmap, gc, itempx, itempy, string2, 1);
     }
     itempy = itempy + (FONT_HEIGHT_CURRENT + FONT_GAP_CURRENT);

   }
#else
   string3[1] = 0;
   string3[2] = 0;
   string3[3] = 0;
   for (i = 0; i < len; i++) {  /* plot each character one at a time */
      string3[0] = string[2*i];
      i_to_s(string3,string2, 4, &ijunk);
      string_width = XTextWidth(font_struct, string2, 1);

     switch (ijusth_temp) {
        case 0:                       /* Left justified string */
            itempx = 0;
            break;
        case 1:                       /* Center justified string */
            itempx = (string_width/2);
            break;
        case 2:                       /* Right justified string */
            itempx = string_width;
            break;
        default:
            itempx = ixpos_temp;
            break;
     }

     itempx = ixpos_temp - itempx;
     XDrawString(display, window, gc, itempx, itempy, string2, 1);
     if (PIXMAP_CURRENT) {
       XDrawString(display, pixmap, gc, itempx, itempy, string2, 1);
     }
     itempy = itempy + (FONT_HEIGHT_CURRENT + FONT_GAP_CURRENT);

   }
#endif

}

/* i_to_s  - utitlity routine to convert an integer array containing
 *           Ascii Decimal Equivalents to a character string array.  The
 *           Fortran routines pass character type data as an array of
 *           ADE's, which this routine then converts to C's character
 *           type.  Note that the input array is assumed to be correct
 *           (i.e., a value between 0 and 127) and no error checking is
 *           done on it.
 *
 * string1 - input array containing ADE's.
 * string2 - output array in C character format.
 * maxlen  - maximum length for string2
 * ilen    - length of character string
 *
 */
void i_to_s(string1, string2, maxlen, ilen)
int   string1[], maxlen, *ilen;
char  string2[];

{
     int  i;
     int  itemp;
     i = 0;
#if PRECISION == 0
     while (string1[i] != 0 && i < (maxlen - 1) ) {
         itemp = string1[i];
         string2[i] = string1[i];
         i++;
     }
     *ilen = i;
     string2[i]='\0';
}
#else
     while (string1[2*i] != 0 && i < (maxlen - 1) ) {
         itemp = string1[2*i];
         string2[i] = string1[2*i];
         i++;
     }
     *ilen = i;
     string2[i]='\0';
}
#endif
/* Set the screen size, use following steps:
 *
 * orien = 2:
 *
 * if xpixels and ypixels are zero, use the default sizes given
 * by this routine.  Otherwise, use xpixels and ypixels.  However,
 * compare them to the number of pixels available on the screen
 * (i.e., the root window).  If not within a certain tolerance, use
 * a half the screen width and 2/3 the screen height.
 *
 * orien = 0:
 *
 * This specifies a landscape orientation.  If the calling routine
 * specifies a positive number of x pixels, this will be used as the
 * x size.  The y size will then be (8.5/11.) of the x size.  If no
 * x size is given (i.e., xpixels = 0), then the default x size will
 * be used.  In either case, the aspect ratio will be constrained.
 *
 * orien = 1:
 *
 * This specifies a portrait orientation.  This works similarly to
 * the landscape orientation, except now the x size will be (8.5/11.)
 * of the y size.  If ypixels = 0, base the y size on the default x
 * size.
 *
 * orien = 3:
 *
 * This specifies a square orientation.  If ypixels = 0, then base on
 * default y size, otherwise use the ypixels value.
 */

void set_screen(xpixels, ypixels, orien)
int   xpixels;  /* suggested width in pixels */
int   ypixels;  /* suggested height in pixels */
int   orien;    /* orientation (landscape, portrait) */

{
   int   temp;
   float atemp;

   switch (orien) {
   case 2:              /* User specified height and width (in pixels) */
       if (xpixels > 0 && ypixels > 0) {
         temp = xpixels;
         atemp = temp;
         if (atemp < 0.3*root_width || atemp > 0.8*root_width) {
            atemp = 0.5*root_width;
            temp = atemp + 0.5;
         }
         xsh.width = temp;
         temp = ypixels;
         atemp = temp;
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.67*root_height;
            temp = atemp + 0.5;
         }
         xsh.height = temp;
       }
       else {            /* Use default size */
         temp = DEFAULT_X_SIZE;
         atemp = temp;
         if (atemp < 0.3*root_width || atemp > 0.8*root_width) {
            atemp = 0.5*root_width;
            temp = atemp + 0.5;
         }
         xsh.width = temp;
         temp = DEFAULT_Y_SIZE;
         atemp = temp;
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.67*root_height;
            temp = atemp + 0.5;
         }
         xsh.height = temp;
       }
       xsh.min_aspect.x = 2;
       xsh.min_aspect.y = 3;
       xsh.max_aspect.x = 4;
       xsh.max_aspect.y = 3;
       break;
   case 0:                     /* Landscape orientation */
       if (xpixels > 0 ) {     /* User specified x size */
         temp = xpixels;
         atemp = temp;
         if (atemp < 0.3*root_width || atemp > 0.8*root_width) {
            atemp = 0.5*root_width;
            temp = atemp + 0.5;
         }
         xsh.width = temp;
         atemp = xpixels * (8.5/11.0);
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.67*root_height;
         }
         temp = atemp + 0.5;
         xsh.height = temp;
       }
       else {                 /* Use default x size */
         temp = DEFAULT_X_SIZE;
         atemp = temp;
         if (atemp < 0.3*root_width || atemp > 0.8*root_width) {
            atemp = 0.5*root_width;
            temp = atemp + 0.5;
         }
         xsh.width = temp;
         atemp = temp * (8.5/11.0);
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.67*root_height;
         }
         temp = atemp + 0.5;
         xsh.height = temp;
       }
       xsh.min_aspect.x = 11;
       xsh.min_aspect.y = 8;
       xsh.max_aspect.x = 11;
       xsh.max_aspect.y = 9;
       break;
   case 1:                      /* Portrait orientation */
       if (ypixels > 0) {       /* User specified y size */
         temp = ypixels;
         atemp = temp;
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.67*root_height;
         }
         temp = atemp + 0.5;
         xsh.height = temp;
         atemp = temp * (8.5/11.);
         if (atemp < 0.3*root_width || atemp > 0.8*root_width) {
            atemp = 0.5*root_width;
         }
         temp = atemp + 0.5;
         xsh.width = temp;
       }
       else {                   /* Use default size (base on X default) */
         temp = DEFAULT_X_SIZE;
         atemp = temp;
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.67*root_height;
         }
         temp = atemp + 0.5;
         xsh.height = temp;
         atemp = temp * (8.5/11.0);
         if (atemp < 0.3*root_width || atemp > 0.8*root_width) {
            atemp = 0.5*root_width;
         }
         temp = atemp + 0.5;
         xsh.width = temp;
       }
       xsh.min_aspect.x = 8;
       xsh.min_aspect.y = 11;
       xsh.max_aspect.x = 9;
       xsh.max_aspect.y = 11;
       break;
   case 3:                     /* Square orientation */
       if (ypixels > 0 ) {     /* User specified y size */
         temp = ypixels;
         atemp = temp;
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.5*root_height;
            temp = atemp + 0.5;
         }
         xsh.height = temp;
         xsh.width = temp;
       }
       else {                 /* Use default x size */
         temp = DEFAULT_X_SIZE;
         atemp = temp;
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.5*root_height;
            temp = atemp + 0.5;
         }
         xsh.height = temp;
         xsh.width = temp;
       }
       xsh.min_aspect.x = 1;
       xsh.min_aspect.y = 1;
       xsh.max_aspect.x = 1;
       xsh.max_aspect.y = 1;
       break;
   default:           /* Orientation flag not specified */
       if (xpixels > 0 && ypixels > 0) {
         temp = xpixels;
         atemp = temp;
         if (atemp < 0.3*root_width || atemp > 0.8*root_width) {
            atemp = 0.5*root_width;
            temp = atemp + 0.5;
         }
         xsh.width = temp;
         temp = ypixels;
         atemp = temp;
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.67*root_height;
            temp = atemp + 0.5;
         }
         xsh.height = temp;
       }
       else {            /* Use default size */
         temp = DEFAULT_X_SIZE;
         atemp = temp;
         if (atemp < 0.3*root_width || atemp > 0.8*root_width) {
            atemp = 0.5*root_width;
            temp = atemp + 0.5;
         }
         xsh.width = temp;
         temp = DEFAULT_Y_SIZE;
         atemp = temp;
         if (atemp < 0.3*root_height || atemp > 0.8*root_height) {
            atemp = 0.67*root_height;
            temp = atemp + 0.5;
         }
         xsh.height = temp;
       }
       xsh.min_aspect.x = 2;
       xsh.min_aspect.y = 3;
       xsh.max_aspect.x = 4;
       xsh.max_aspect.y = 3;
       break;
    }

}
