r104: initial cvs import
authorKevin M. Rosenberg <kevin@rosenberg.net>
Mon, 19 Jun 2000 18:05:03 +0000 (18:05 +0000)
committerKevin M. Rosenberg <kevin@rosenberg.net>
Mon, 19 Jun 2000 18:05:03 +0000 (18:05 +0000)
14 files changed:
libctgraphics/Makefile.am [new file with mode: 0644]
libctgraphics/Makefile.nt [new file with mode: 0644]
libctgraphics/bresenham.cpp [new file with mode: 0644]
libctgraphics/circle.cpp [new file with mode: 0644]
libctgraphics/ctm.cpp [new file with mode: 0644]
libctgraphics/drawbox.cpp [new file with mode: 0644]
libctgraphics/driver_x11.cpp [new file with mode: 0644]
libctgraphics/ezplot.cpp [new file with mode: 0644]
libctgraphics/ezpol.cpp [new file with mode: 0644]
libctgraphics/ezset.cpp [new file with mode: 0644]
libctgraphics/ezsupport.cpp [new file with mode: 0644]
libctgraphics/sgp.cpp [new file with mode: 0644]
libctgraphics/sgpdrive.cpp [new file with mode: 0644]
libctgraphics/sgptext.cpp [new file with mode: 0644]

diff --git a/libctgraphics/Makefile.am b/libctgraphics/Makefile.am
new file mode 100644 (file)
index 0000000..7bc2d47
--- /dev/null
@@ -0,0 +1,7 @@
+noinst_LIBRARIES = libctgraphics.a
+libctgraphics_a_SOURCES=ezplot.cpp ezsupport.cpp ezset.cpp ezpol.cpp circle.cpp ctm.cpp drawbox.cpp sgp.cpp sgpdrive.cpp sgptext.cpp
+INCLUDES=@my_includes@
+EXTRA_DIST=Makefile.nt
+
+
+
diff --git a/libctgraphics/Makefile.nt b/libctgraphics/Makefile.nt
new file mode 100644 (file)
index 0000000..89396b9
--- /dev/null
@@ -0,0 +1,32 @@
+# Makefile for libk\r
+\r
+!include <ntwin32.mak>\r
+\r
+CC=cl\r
+LD=link\r
+CFLAGS=-O -nologo -I..\include\r
+LDFLAGS=\r
+O=.obj\r
+\r
+# variables\r
+OBJ1 = axis$(O) ezplot$(O) ezplot1d$(O) ezset$(O) makefmt$(O) pol$(O)\r
+\r
+all:  libezplot.lib\r
+\r
+.obj: .c\r
+       $(CC) -c $(cvarsdll) $(CFLAGS) $*.c\r
+\r
+\r
+libezplot.lib: $(OBJ1)\r
+        echo something to del > libezplot.lib\r
+        del libezplot.lib\r
+        lib /out:libezplot.lib $(OBJ1)\r
+\r
+\r
+clean:\r
+        echo dummy > a.obj\r
+        echo dummy > a.lib\r
+        echo dummy > a.exe\r
+       del *.obj\r
+       del *.exe\r
+       del *.lib\r
diff --git a/libctgraphics/bresenham.cpp b/libctgraphics/bresenham.cpp
new file mode 100644 (file)
index 0000000..e9936fe
--- /dev/null
@@ -0,0 +1,278 @@
+/* ; FILE IDENTIFICATION
+;
+;              Name:  CRT_LINE.ASM
+;           Purpose:  Draw lines on screen using Bresenham's integer algorithm
+;        Programmer:  Kevin Rosenberg
+;      Date Started:  1 Jun 84
+;  Last Modification: 15 Jul 85, Version 1.0
+;      
+; CORRESPONDENCE
+;      Kevin Rosenberg
+;      2515 E. 16th St.
+;      Newport Beach, CA 92663
+;      (714) 642-0119 (voice)
+;      (714) 842-6348 (E-Mail on Consultant's Exchange RBBS)
+;      Compuserve 73775,1232
+;
+; LANGAUGE
+;      IBM macro v1.000000000
+;
+; LANGAUGE INTERFACE
+;      Public routines callable from Lattice C v2.0+
+;          Works with S & L memory models.  Can easily add support for the
+;          other models by changing the STK structure below.
+;
+; NEEDED FILES
+;      egadrive.inc    Definitions, macros, & procedures for driving EGA
+;      hidden.inc      Defines OPTIONAL public procedure, crt_hdn_line().
+;      dos.mac         Lattice's file containing memory model macros
+;                      See inclusion statement for more documentation
+;
+; GRAPHIC MODES SUPPORTED
+;      - Standard CGA modes -- BIOS codes 4, 5, & 6 -- are support through
+;        the ROM BIOS pixel setting routine.  Things could be speeded up
+;        by a factor of 7-15 by writing to the video buffer directly.
+;      - You may remove support for the CGA completely by changing the
+;        EQU of STD_GRF to 0, a slight speed increase in EGA operations
+;        is the gain.
+;      - All EGA graphic modes are supported with optimized direct pixel
+;        accessing.  Note: mode 13 (320x200) is bugged, see LOG date 6-20-85
+;
+; LANGUAGE INTERFACE
+;      Lattice C v2.0+
+;
+; HISTORY LOG
+;    7-15-85
+;      Released in PD as version 1.0
+;    6-27-85
+;      Put EGA routines in INCLUDE file EGADRIVE.INC
+;      Put Hidden line routines in OPTIONAL INCLUDE file HIDDEN.INC
+;    6-20-85
+;      Tested with video modes 13 (320x200) & 14 (640x200).  Mode 14 worked
+;      ok, mode 13 was missing every other vertical line:  I'm probably
+;      not setting one of the myriad of registers correctly.  Since I'll
+;      never use mode 13, I won't investigate it further.
+;    6-05-85
+;      Added & updated documentation
+;    2-28-85
+;      Added hidden line routines
+;         PUBLIC crt_hdn_line plus internal routines
+;         (see function summary for more info)
+;    1-20-85
+;      Added global variable STD_GRF
+;         Will support standard graphic modes if it is set to non-zero value;
+;         however, the slow ROM BIOS is used as well as a slight overhead
+;         for the EG code.  IT IS MUCH FASTER TO USE THE EGA ENHANCED
+;         (350 line) GRAPHIC MODES.
+;    1-09-85
+;      Convert to support IBM's Enhanced graphics adapter.
+;      Remove all optimized code for color graphics adapter (CGA)
+;    7-16-84
+;      Changed calls to ROM that set pixels to speedy routines which use
+;      incremental address calculation and direct writing the to graphics
+;      buffer.
+;    1-12-84
+;      File creation:
+;           Converted C function, bresline.c, to assembly langauge.
+;           Retained C source of Bresenham's integer rastering algorithm
+;           as comments.
+;
+; FUNCTION SUMMARY 
+;
+;      crt_line_page (page)
+;              Set graphics page to plot lines on [default = 0]
+;
+;      crt_line_style (style)
+;              Set line style [Default = solid line]
+;
+;      crt_line (x1, y1, x2, y1, color)
+;              Plots a line on the screen using Bresenham's integer algorithm
+;
+;      crt_hdn_line (x1, y1, x2, y1, color, col_min, col_max)
+;              OPTIONAL routine to plots lines using hidden areas
+;              INCLUDE file HIDDEN.INC if you wish to use this routine
+;
+;      crt_init_hdn (col_min, col_max)
+;              Initializes vectors for use with crt_hdn_line()
+;
+;
+;      int x1, y1 - starting point
+;      int x2, y2 - end point
+;      int color  - color to draw line, as defined by IBM bios setting
+;      int linestyle - 16 bit wide dot setting pattern
+;      int col_min[640]  Minimum values for each X column (initialize to 349)
+;      int col_max[640]  Maximum values for each X column (initialize to 0)
+;                        (Do not display any points between the min & max,
+;                         and update these values for each new min & max)
+;                        If a vector == NULL, then do not clip against that
+;                        boundary.
+;
+; REFERENCES FOR BRESENHAM'S ALGORITHM
+;      Newman & Sproll, "Principals of Interactive Computer Graphics",
+;         page 25.
+;      Foley & van Dam, "Fundementals of Interactive Computer Graphics",
+;         page 433
+*/
+
+;------        Bresenham variables
+
+       deltx           dw      ?
+       delty           dw      ?
+       absdx           dw      ?
+       absdy           dw      ?
+       min_inc         dw      ?       ; (-1, 1) indicates direction of minor axis
+       dinc1           dw      ?       ; d increment if (d >= 0)
+       dinc2           dw      ?       ; d increment if (d < 0)
+
+
+
+
+;------------------------------------------------------------------------------
+; PROCEDURE
+;      crt_line [PUBLIC]       Plot a line on the screen using Bresenham's alg
+;
+; SYNOPSIS
+;      crt_line (x1, y1, x2, y2, color)
+
+void bresenham (int x1, int y1, int x2, int y2)
+{
+       delta_x = x2 - x1;
+        dx_abs = (delta_x >= 0 ? delta_x : -delta_x);
+
+       delta_y = y2 - y1;
+        dy_abs = (delta_y >= 0 ? delta_y : -delta_y);
+
+if (dx_abs > dy_abs) 
+    bresx();
+else
+   bresy();
+}
+
+lastx= x2;
+lasty = y2;
+
+
+;------------------------------------------------------------------------------
+; MACRO NAME
+;      BRES
+;
+; FUNCTION
+;      Do inner most loop to draw pictures
+;
+; SYNOPSIS
+;      BRES P1,P2
+;      P1      Major axis & direction 
+;      P2      Minor axis 
+;
+; EXAMPLES
+;      BRES INC_COL,ROW
+;
+; INPUT
+;      (DI)            Address of local routine to call when setting pixel
+;      (BX)            Decision variable
+;      (CX)            Number of points to plot on major axis (loop counter)
+;      [bp].min_inc    Direction of minor axis increments
+;      [bp].dinc1      Bresenham decision increments (see references)
+;      [bp].dinc2
+;      MACROS          ADDR_INC_ROW, _DEC_ROW, _INC_COL, _DEC_COL
+;
+; REGISTERS USED BY PIXEL SETTING ROUTINES
+;      (SI)            Offset in EGA buffer
+;      (AH)            Bitmask
+;
+; REGISTERS AVAILABLE FOR USE
+;      (AL)
+;      (DX)
+;
+; CALLS
+;      LS_PSET, this routine uses the addr in (DI) to set a point if
+;               the linestyle allows.
+;------------------------------------------------------------------------------
+
+BRES   MACRO   P1,P2
+       LOCAL   b0,b1
+       cmp     [bp].min_inc,0  ;if (min_inc >= 0)
+       jl      b0
+       _BRES   P1,INC_&P2      ;       inc_minor_axis
+       jmp     b1              ;else
+b0:    _BRES   P1,DEC_&P2      ;       dec_minor_axis
+b1:
+       ENDM
+
+
+_BRES  MACRO   P1,P2
+       LOCAL   bres0,bres1,bres2
+bres0:                         ; do {
+       LS_PSET                 ;       ls_pset() /* set pix using linestyle */
+
+       ADDR_&P1                        ;       P1 (change major axis)
+
+       cmp     bx,0            ;
+       jge     bres1           ;       if (d < 0)
+       add     bx,[bp].dinc2   ;           d += dinc2;
+       jmp     bres2           ;       else {
+bres1:                         ;
+       add     bx,[bp].dinc1   ;           d += dinc1
+       ADDR_&P2                        ;           P2 (change minor axis)
+                               ;       }
+bres2:
+       loop    bres0           ; } while (--count > 0)
+       ENDM
+
+bresx()
+{
+    /*    draws a line then abs(dx) >= abs(dy) */
+
+    int npix = dx_abs + 1;
+
+    /* determine direction of minor axis */
+
+    int  min_inc = 1;
+    if (delta_y < 0)
+       min_inc = -1;
+
+    /* Put decision variable in d */
+
+    int d = dy_abs * 2 - dx_abs;
+    int dinc1 = (dy_abs - dx_abs) * 2;
+    int dinc2 = 2 * dy_abs;
+
+    if (x1 <= x2)
+       bres(INC_COL, ROW);
+    else 
+       breas (DEC_COL, ROW)l
+
+           }
+
+
+void bresy()
+{
+    /*;    bresy [LOCAL]       For plotting lines with abs(dy) > abs(sx)
+
+ NOTES
+    Logic identical to bresx's, substitution x for y and
+    vice versa.  I separate the into two routines rather
+    than having the main loop spending time determining
+    which are the major & minor axis. 
+    */
+
+
+    int count = dy_abs + 1;
+
+    /* check direction of minor axis */
+
+    min_inc = 1;
+    if (delta_x < 0)
+       min_inc = -1;
+
+
+    int d = dx_abs * 2 - dy_abs;
+    dinc1 = (dx_abs - dy_abs) * 2;
+    dinc2 = 2 * dx_abs;
+
+    if (y1 <= y2)
+       bres(INC_ROW,COL);
+    else
+       bres(DEL_ROW,COL);
+}
+
diff --git a/libctgraphics/circle.cpp b/libctgraphics/circle.cpp
new file mode 100644 (file)
index 0000000..373edae
--- /dev/null
@@ -0,0 +1,90 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: circle.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**  $Log: circle.cpp,v $
+**  Revision 1.1  2000/06/19 18:05:03  kevin
+**  initial cvs import
+**
+**  Revision 1.1  2000/06/13 16:20:31  kevin
+**  finished c++ conversions
+**
+**  Revision 1.2  2000/05/24 22:49:01  kevin
+**  Updated SGP: first function X-windows version
+**
+**  Revision 1.1.1.1  2000/04/28 13:02:44  kevin
+**  Initial CVS import for first public release
+**
+**
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+
+/* FUNCTION
+ * sgp2_circle - draw circle of radius r at current center             
+ */
+
+#include "math.h"
+#include "kmath.h"
+#include "sgp.h"
+
+void 
+sgp2_draw_circle (const double r)
+{
+       sgp2_draw_arc (0.0, 7.0, r);
+}
+
+/*==============================================================*/
+/* draw arc around current center.  pass angles and radius     */
+/*==============================================================*/
+
+void 
+sgp2_draw_arc (double start, double stop, const double r)
+{
+       double c, s, theta, angle;
+       float x, y, xp, yp;
+
+       if ((stop-start) > 2 * PI)
+           stop = start + 2 * PI;
+       if ((start-stop) > 2 * PI)
+           stop = start + 2 * PI;
+       while (start >= stop)
+           stop += 2*PI;
+
+       x = r * cos ((double) start);
+       y = r * sin ((double) start);
+       sgp2_move_rel (x, y);          /* move from center to start of arc */
+
+       theta = 5 * PI / 180;
+       c = cos(theta);
+       s = sin(theta);
+
+       for (angle = start; angle < stop - theta; angle += theta) {
+           xp = c * x - s * y;
+           yp = s * x + c * y;
+           sgp2_line_rel (xp - x, yp - y);
+           x = xp; y = yp;
+       }
+
+       c = cos (stop - angle);
+       s = sin (stop - angle);
+       xp = c * x - s * y;
+       yp = s * x + c * y;
+       sgp2_line_rel (xp - x, yp - y);
+
+       x = r * cos ((double) stop);
+       y = r * sin ((double) stop);
+       sgp2_move_rel (-x, -y);         /* move back to center of circle */
+}
diff --git a/libctgraphics/ctm.cpp b/libctgraphics/ctm.cpp
new file mode 100644 (file)
index 0000000..4f88c77
--- /dev/null
@@ -0,0 +1,245 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: ctm.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**  $Log: ctm.cpp,v $
+**  Revision 1.1  2000/06/19 18:05:03  kevin
+**  initial cvs import
+**
+**  Revision 1.1  2000/06/13 16:20:31  kevin
+**  finished c++ conversions
+**
+**  Revision 1.2  2000/05/11 14:07:23  kevin
+**  Fixed compilation warnings
+**
+**  Revision 1.1.1.1  2000/04/28 13:02:44  kevin
+**  Initial CVS import for first public release
+**
+**
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+
+/*-----------------------------------------------------------------------------
+ * FILE IDENTIFICATION
+ *
+ *     Name:       ctm.c
+ *     Function:   Current Transform Matrix routine for graphic library
+ *     Programmer: Kevin Rosenberg
+ *     Date Started:   1-22-85
+ *
+ * FUNCTION SUMMARY
+ *     ctm_xlat_pre_2 ()
+ *     ctm_xlat_post_2 ()
+ *     ctm_scale_pre_2 ()
+ *     ctm_scale_post_2 ()
+ *     ctm_rotate_pre_2 ()
+ *     ctm_rotate_post_2 ()
+ *
+ * NOTES
+ *     The indices on the 2d matrix are opposite of the cartesian order used
+ *     in the sdf_2d files.  Here, the 1st index is the row & and 2nd is the
+ *     column
+ *---------------------------------------------------------------------------*/
+
+#include "kstddef.h"
+#include <math.h>
+#include "kmath.h"
+#include "sgp.h"
+
+
+/*---------------------------------------------------------------------------*/
+/*                             Geometric Operations                         */
+/*---------------------------------------------------------------------------*/
+
+void
+ctm_xlat_pre_2 (double x, double y)
+{
+    GRFMTX_2D m;
+
+    xlat_gmtx_2 (m, x, y);
+    ctm_pre_mult_2 (m);
+}
+
+
+void 
+ctm_xlat_post_2 (double x, double y)
+{
+    GRFMTX_2D m;
+
+    xlat_gmtx_2 (m, x, y);
+    ctm_post_mult_2 (m);
+}
+
+
+void 
+ctm_scale_pre_2 (double sx, double sy)
+{
+    GRFMTX_2D m;
+
+    scale_gmtx_2 (m, sx, sy);
+    ctm_pre_mult_2 (m);
+}
+
+
+void 
+ctm_scale_post_2 (double sx, double sy)
+{
+    GRFMTX_2D m;
+
+    scale_gmtx_2 (m, sx, sy);
+    ctm_post_mult_2 (m);
+}
+
+
+void 
+ctm_rotate_pre_2 (double theta)
+{
+    GRFMTX_2D m;
+
+    rotate_gmtx_2 (m, theta);
+    ctm_pre_mult_2 (m);
+}
+
+
+void 
+ctm_rotate_post_2 (double theta)
+{
+    GRFMTX_2D m;
+
+    rotate_gmtx_2 (m, theta);
+    ctm_post_mult_2 (m);
+}
+
+
+void 
+ctm_shear_pre_2 (double shrx, double shry)
+{
+    GRFMTX_2D m;
+
+    shear_gmtx_2 (m, shrx, shry);
+    ctm_pre_mult_2 (m);
+}
+
+
+void 
+ctm_shear_post_2 (double shrx, double shry)
+{
+    GRFMTX_2D m;
+
+    shear_gmtx_2 (m, shrx, shry);
+    ctm_post_mult_2 (m);
+}
+
+/*---------------------------------------------------------------------------*/
+/*                     Low-Level Internal Functions                         */
+/*---------------------------------------------------------------------------*/
+
+
+void 
+xlat_gmtx_2 (GRFMTX_2D m, double x, double y)
+{
+    ident_gmtx_2 (m);
+    m[2][0] = x;
+    m[2][1] = y;
+}
+
+
+void 
+scale_gmtx_2 (GRFMTX_2D m, double sx, double sy)
+{
+    ident_gmtx_2 (m);
+    m[0][0] = sx;
+    m[1][1] = sy;
+}
+
+
+void 
+shear_gmtx_2 (GRFMTX_2D m, double shrx, double shry)
+{
+    ident_gmtx_2 (m);
+    m[1][0] = shrx;
+    m[0][1] = shry;
+}
+
+void 
+rotate_gmtx_2 (GRFMTX_2D m, double theta)
+{
+    double s, c;
+
+    s = sin (theta);
+    c = cos (theta);
+
+    ident_gmtx_2 (m);
+
+    m[0][0] =  c;  m[0][1] = s;
+    m[1][0] = -s;  m[1][1] = c;
+}
+
+
+void 
+ident_gmtx_2 (GRFMTX_2D m)
+{
+    m[0][0] = 1.;  m[0][1] = 0.;  m[0][2] = 0.;
+    m[1][0] = 0.;  m[1][1] = 1.;  m[1][2] = 0.;
+    m[2][0] = 0.;  m[2][1] = 0.;  m[2][2] = 1.;
+}
+
+
+void 
+mult_gmtx_2 (GRFMTX_2D a, GRFMTX_2D b, GRFMTX_2D c)
+{
+    int row, col, calc;
+
+    for (row = 0; row < 3; row++)
+       for (col = 0; col < 3; col++) {
+           c[row][col] = 0.;
+           for (calc = 0; calc < 3; calc++)
+               c[row][col] += a[row][calc] * b[calc][col];
+       }
+}
+
+void 
+invert_gmtx_2 (GRFMTX_2D a, GRFMTX_2D b)
+{
+    double determ;
+
+    determ = determ_gmtx_2 (a);
+    if (fabs(determ) < 1E-6)
+       sys_error (ERR_WARNING, "Determinant = %lg [invert_gmtx_2]", determ);
+
+    b[0][0] =  (a[1][1] * a[2][2] - a[2][1] * a[1][2]) / determ;
+    b[1][0] = -(a[1][0] * a[2][2] - a[2][0] * a[1][2]) / determ;
+    b[2][0] =  (a[1][0] * a[2][1] - a[2][0] * a[1][1]) / determ;
+
+    b[0][1] = -(a[0][1] * a[2][2] - a[2][1] * a[0][2]) / determ;
+    b[1][1] =  (a[0][0] * a[2][2] - a[2][0] * a[0][2]) / determ;
+    b[2][1] = -(a[0][0] * a[2][1] - a[2][0] * a[0][1]) / determ;
+
+    b[0][2] =  (a[0][1] * a[1][2] - a[1][1] * a[0][2]) / determ;
+    b[1][2] = -(a[0][0] * a[1][2] - a[1][0] * a[0][2]) / determ;
+    b[2][2] =  (a[0][0] * a[1][1] - a[1][0] * a[0][1]) / determ;
+}
+
+
+double 
+determ_gmtx_2 (GRFMTX_2D a)
+{
+    return
+       (a[0][0] * a[1][1] * a[2][2] - a[0][0] * a[2][1] * a[1][2] -
+        a[0][1] * a[1][0] * a[2][2] + a[0][1] * a[2][0] * a[1][2] +
+        a[0][2] * a[1][0] * a[2][1] - a[0][2] * a[2][0] * a[1][1]);
+}
+
diff --git a/libctgraphics/drawbox.cpp b/libctgraphics/drawbox.cpp
new file mode 100644 (file)
index 0000000..9d9eff6
--- /dev/null
@@ -0,0 +1,61 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: drawbox.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**  $Log: drawbox.cpp,v $
+**  Revision 1.1  2000/06/19 18:05:03  kevin
+**  initial cvs import
+**
+**  Revision 1.1  2000/06/13 16:20:31  kevin
+**  finished c++ conversions
+**
+**  Revision 1.3  2000/05/24 22:49:01  kevin
+**  Updated SGP: first function X-windows version
+**
+**  Revision 1.2  2000/05/11 14:07:23  kevin
+**  Fixed compilation warnings
+**
+**  Revision 1.1.1.1  2000/04/28 13:02:44  kevin
+**  Initial CVS import for first public release
+**
+**
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+
+/* NAME
+ *   sgp2_draw_rect                            Draw box in graphics mode
+ *
+ * SYNOPSIS
+ *   drawbox (xmin, ymin, xmax, ymax)
+ *   double xmin, ymin                 Lower left corner of box
+ *   double xmax, ymax                 Upper left corner of box
+ *
+ * NOTES
+ *   This routine leaves the current position of graphic cursor at lower
+ *   left corner of box.
+ */
+
+#include "sgp.h"
+
+void
+sgp2_draw_rect(double xmin, double ymin, double xmax, double ymax)
+{
+       sgp2_move_abs (xmin, ymin);
+       sgp2_line_abs (xmax, ymin);
+       sgp2_line_abs (xmax, ymax);
+       sgp2_line_abs (xmin, ymax);
+       sgp2_line_abs (xmin, ymin);
+}
diff --git a/libctgraphics/driver_x11.cpp b/libctgraphics/driver_x11.cpp
new file mode 100644 (file)
index 0000000..c48a4d2
--- /dev/null
@@ -0,0 +1,285 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: driver_x11.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**  $Log: driver_x11.cpp,v $
+**  Revision 1.1  2000/06/19 18:05:03  kevin
+**  initial cvs import
+**
+**  Revision 1.1  2000/05/08 20:08:15  kevin
+**  *** empty log message ***
+**
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "kstddef.h"
+#include "sgp.h"
+#include "kmath.h"
+#include "cio.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+struct sgp_x11_driver {
+  Display *theDisplay;
+  int  theScreen;
+  int  theDepth;
+};
+
+typedef struct sgp_x11_driver SGP_X11_DRIVER;
+
+SGP_X11_DRIVER sgp_x11;
+
+sgpdrv_X11_init()
+{
+  int i;
+
+  sgp_x11.theDisplay = NULL;
+  for (i = 0; i < 2 && theDisplay == NULL; i++)
+    sgp_x11.theDisplay = XOpenDisplay( NULL  );
+
+  if ( sgp_x11.theDisplay == NULL ) {
+    fprintf( stderr, "ERROR: Cannot establish a connection to the X Server %s\n", XDisplayName( NULL ));
+    exit( 1 );
+  }
+
+  sgp_x11.theScreen = DefaultScreen( sgp_x11.theDisplay );
+  sgp_x11.theDepth = DefaultDepth( sgp_x11.theDisplay, sgp_x11.theScreen );
+}
+
+sgpdrv_X11_info()
+{
+  printf("%s version %d of the X Window System, X%d R%d\n", 
+        ServerVendor( sgp_x11.theDisplay ),
+        VendorRelease( sgp_x11.theDisplay ),
+        ProtocolVersion( sgp_x11.theDisplay ),
+        ProtocolRevision( sgp_x11.theDisplay ) );
+
+  if ( sgp_x11.theDepth == 1) 
+    printf( "Color plane depth....................%d (monochrome)\n", sgp_x11.theDepth );
+  else
+    printf( "Color plane depth....................%d\n", sgp_x11.theDepth);
+  
+  printf( "Display Width........................%d\n",
+         DisplayWidth( sgp_x11.theDisplay, sgp_x11.theScreen ));
+  printf( "Display Height.......................%d\n",
+         DisplayHeight( theDisplay, theScreen ));
+  printf( "The display %s\n", XDisplayName( sgp_x11.theDisplay ));
+}
+
+
+
+setlinestyle (LS_SOLID);
+setcolor (1);
+settext (XCHARSIZ, YCHARSIZ, 0.0, 0);
+setbackg (0);
+settextclr (1, 0);
+gp_set_aspect (CRTDEV, CRTASPT);
+gp_set_aspect (PRTDEV, 1.0);
+state.xndc = 10.;              /* to guarntee a move */
+stylus (0.0,0.0,0);            /* move to starting corner */
+
+
+int 
+initdevice (int dev, int mode, int xsize, int ysize)
+{
+  //        crt.dotfunc = crt_wdot;
+  //       crt.linefunc = crt_line;
+  crt.xmin = 0;
+  crt.ymin = 0;
+  crt.xmax  = 319;
+  crt.xsize = 320;
+}
+           
+
+/* NAME
+ *   gp_closedev               Close device for output
+ *
+ * SYNOPSIS
+ *   gp_closedev (dev)
+ *   int dev                   Device handle
+ *
+ * DESCRIPTION
+ *    Temporarily suspends output from going to a device
+ */
+
+void sgpdrv_x11_term()
+{
+}
+
+void sgpdrv_x11_line()
+{
+}
+
+void sgpdrive_x11_point()
+{
+}
+
+void 
+sgpdrv_x11_linestyle (int style)
+{
+
+  state.linestyle = style;
+  
+       //      crt_line_style (crt.style);
+}
+
+void
+sgpdrv_x11_linewidth (int wid)
+{
+       state.linewidth = wid;
+}
+
+void
+sgpdrv_x11_textparam (
+    double width,
+    double height,                     /* size of character in NDC */
+    double textangle,                  /* text angle */
+    int font                           /* text font */
+)
+{
+       double temp;
+
+       CLIP(height, 0.0, 1.0);
+       CLIP(width, 0.0, 1.0);
+/*     textangle = textangle - (2 * PI * (int) (textangle / (2 * PI)));
+*/
+       cspec.width = width;
+       cspec.height = height;
+       cspec.textangle = textangle;
+       cspec.font = font;
+
+       if (textangle > - HALFPI / 2 && textangle < HALFPI / 2) {
+           cspec.updir = YPLUS;
+           cspec.textdir = XPLUS;
+       } else if (textangle > HALFPI / 2 && textangle < 3 * HALFPI / 2) {
+           cspec.updir = XMINUS;
+           cspec.textdir = YPLUS;
+       } else if (textangle > 3 * HALFPI / 2 && textangle < 5 * HALFPI / 2) {
+           cspec.updir = YMINUS;
+           cspec.textdir = XMINUS;
+       } else if (textangle > 5 * HALFPI / 2 && textangle < 7 * HALFPI / 2) {
+           cspec.updir = XPLUS;
+           cspec.textdir = YMINUS;
+       } else {
+           cspec.updir = YPLUS;
+           cspec.textdir = XPLUS;
+       }
+
+       if (cspec.updir == XMINUS || cspec.updir == XPLUS) {
+           temp = height;
+           height = width;
+           width = temp;
+       }
+
+       crt.icwidth = width * crt.xsize + 0.5;
+       crt.icheight = height * crt.ysize + 0.5;
+       crt.icwidth = iclip (crt.icwidth, 8, crt.xsize);
+       crt.icheight = iclip (crt.icheight, 8, crt.ysize);
+
+       prt.icwidth = width * prt.xsize + 0.5;
+       prt.icheight = height * prt.ysize + 0.5;
+       prt.icwidth = iclip (prt.icwidth, 8, prt.xsize);
+       prt.icheight = iclip (prt.icheight, 8, prt.ysize);
+}
+
+void
+sgpdrv_textcolor (int fore, int back)
+{
+       cspec.fore = fore;
+       cspec.back = back;
+       crt.cfore = fore;
+       crt.cback = back;
+       prt.cfore = iclip (fore, 0, prt.colormax);
+       prt.cback = back;
+}
+
+void
+sgpdrv_color (int fore)
+{
+       int back;
+
+       state.foregnd = fore;
+       back = state.backgnd;
+       crtcolor (crt.mode, &fore, &back);              /* set colors on crt */
+}
+
+void
+sgpdrv_backgroundg (int back)
+{
+       int fore;
+
+       state.backgnd = back;
+       fore = state.foregnd;
+       crtcolor (crt.mode, &fore, &back);
+}
+
+/*
+ * INITMARKER (<SYMBOL>)
+ *
+ * Sets the current marker symbol (cross, square, diamond..)
+ */
+void sgpdrv_marker (int marker, int color)
+{
+       if (marker > NMARKERS || marker < 0)
+           return(-1);
+       else {
+           state.marktype = marker;
+           state.markcolor = color;
+       }
+       return(0);
+} /* end initmarker */
+
+/*
+ * SETCHARDIR ( <DIRECTION> )
+ *
+ * indicates in which direction a string should be printed, e.g.:
+ *  direction = YPLUS  -> print on the horizontal from left to right
+ *  direction = YMINUS -> print upside-down characters from right to left
+ *  direction = XMINUS -> print on the vertical from down to up
+ *  direction = XPLUS  -> print on the vertical from up to down
+ */
+void sgpdrv_x11_textdir (
+    int direction       /* direction flag */
+)
+{
+  if (direction != XPLUS &&
+      direction != XMINUS &&
+      direction != YPLUS &&
+      direction != YMINUS ) {
+    printf("Error in character direction: %d\n", direction);
+    return(-1);
+  }
+  cspec.textdir = direction;
+  charsize (cspec.width, cspec.height);
+}
+
+int 
+void sgpdrv_x11_charsize (double wid, double height)
+{
+       settext (wid, height, cspec.textangle, cspec.font);
+}
+
+void
+sgpdrv_x11_textangle (double angle)
+{
+  settext (cspec.width, cspec.height, angle, cspec.font);
+}
+
+
diff --git a/libctgraphics/ezplot.cpp b/libctgraphics/ezplot.cpp
new file mode 100644 (file)
index 0000000..73db34d
--- /dev/null
@@ -0,0 +1,915 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: ezplot.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+/*----------------------------------------------------------------------*/
+/*                             EZPLOT                                  */
+/*----------------------------------------------------------------------*/
+
+#include "ezplot.h"
+#include "algo.h"
+
+static int plot (SGP_ID *gid);
+static void drawaxis(void);
+static void symbol (int sym, double symwidth, double symheight);
+
+
+/*-------------------------------------*/
+/* GLOBAL variables for EZPLOT & EZSET */
+/*-------------------------------------*/
+
+bool ezplot_firstcall = TRUE;  /* set to false on first call to EZSET or EZPLOT */
+struct ezplot_var ez;          /* ezplot variables */
+
+/*----------------*/
+/* DEFAULT values */
+/*----------------*/
+
+#define TICKRATIO 0.4          /* ratio of minor to major tick lengths */
+#define MAXNUMFMT 15           /* maximum length of a numeric format */
+
+#define DEF_CRTMODE    0  /*GM_HIGHRES*/       /* default crt mode */
+#define DEF_CHARHEIGHT (1./43.)        /* default size of characters in NDC */
+#define DEF_CHARWIDTH  (1./80.)
+
+#define DEF_CURVE_CLR   C_YELLOW
+
+
+/*----------------------------------------------------------------------*/
+/*                             GLOBAL VARIABLES                        */
+/*----------------------------------------------------------------------*/
+
+static
+double charwidth, charheight;  /* Size of characters in NDC */
+
+static
+double  xp_min, xp_max,
+    yp_min, yp_max;            /* boundry of plot frame in NDC */
+static
+double  xa_min, xa_max,
+    ya_min, ya_max;            /* extent of axes in NDC */
+static
+double  xgw_min, xgw_max,
+    ygw_min, ygw_max;  /* boundary of graph in input coords */
+static
+double  xgn_min, xgn_max,
+    ygn_min, ygn_max;  /* boundy of graph in NDC */
+static
+double xt_min, xt_max,
+    yt_min, yt_max;            /* boundary of axis ticks */
+
+static
+double  xl_min, xl_max,
+    yl_min, yl_max;            /* boundary of legend box */
+
+static  double title_row;      /* y-coord of title row */
+
+static  double xtl_ofs;                /* Offset y-coord of x tick labels from axis */
+static double ytl_ofs;         /* Offset x-coord of y tick labels from axis */
+
+static double xlbl_row;        /* row of x label in world coord */
+static double ylbl_col;        /* column of y label in world coord */
+
+static
+double xw_tickinc, yw_tickinc; /* increment between major ticks in WC */
+
+static
+double xn_tickinc, yn_tickinc; /* increment between major ticks in NDC */
+
+static int x_nint, y_nint;     /* number of intervals along x & y axes */
+static int x_fldwid, x_frac;   /* numeric field sizes & number of digits   */
+static int y_fldwid, y_frac;   /* in fraction of number, used for printf() */
+
+static double xtl_wid, ytl_wid;        /* length of ticks labels in NDC */
+static double tl_height;       /* height of tick labels in NDC */
+
+static char x_numfmt[10];      /* format to print x tick labels */
+static char y_numfmt[10];      /* format to print y tick labels */
+
+
+/*----------------------------------------------------------------------
+ * FUNCTION IDENTICIFATION
+ *
+ *     Name:           EZPLOT
+ *     Programmer:     Kevin Rosenberg
+ *     Date:            5-83 Version 1
+ *                     11-84 Version 2
+ *
+ * SYNOPSIS
+ *     ezplot (x, y, n)
+ *     double x[]      x-coordinates of point  makeing up a curve 
+ *     double y[]      y-coordinates of points makeing up a curve
+ *     int    n        Number of points in curve
+ *
+ * DESCRIPTION
+ *         This is a sophisticated plotting program.
+ *
+ *----------------------------------------------------------------------*/
+
+
+SGP_ID
+ezplot (double x[], double y[], int num)
+{
+    unsigned int size, i;
+    SGP_ID gid = NULL;
+
+    if (ez.i_plotimmediate == TRUE) {
+       plot (&gid);
+       return (gid);
+    }
+
+    if (num < 1)
+       return (NULL);
+
+    if (ezplot_firstcall == TRUE)
+       ezinit();
+
+    if (ez.o_unknowncurves == FALSE && ez.i_numcurves >= ez.o_reqcurves)
+       ezclear ();
+
+    if (ez.i_numcurves < MAXCURVES &&
+       (ez.o_unknowncurves == TRUE || ez.i_numcurves < ez.o_reqcurves)) {
+       size = num * sizeof(double);
+       ez.curve[ez.i_numcurves].x = new double [size];
+       ez.curve[ez.i_numcurves].y = new double [size];
+       for (i = 0; i < num; i++) {
+           ez.curve[ez.i_numcurves].x[i] = x[i];
+           ez.curve[ez.i_numcurves].y[i] = y[i];
+       }
+       ez.curve[ez.i_numcurves].numpts = num;
+       ez.curve[ez.i_numcurves].color = ez.o_color;
+       ez.curve[ez.i_numcurves].linestyle = ez.o_linestyle;
+       ez.curve[ez.i_numcurves].symbol = ez.o_symbol;
+       ez.curve[ez.i_numcurves].symfreq = ez.o_symfreq;
+       strncpy (ez.curve[ez.i_numcurves].legend, ez.c_legend, MAXLEGEND);
+       ++ez.i_numcurves;
+    }
+    
+    if (ez.o_unknowncurves == FALSE && ez.i_numcurves >= ez.o_reqcurves) {
+       plot (&gid);
+       ezclear ();
+    }
+
+    return (gid);
+}
+
+
+/* NAME
+ *   plot              INTERNAL: Plots all curves collected by ezplot()
+ *
+ * SYNOPSIS
+ *   plot()
+ *
+ * DESCRIPTION
+ *   This routine plots the curves that have stored by ezplot().
+ *
+ * CALLED BY
+ *   EZPLOT() only
+ *
+ * CALLS
+ *   drawaxis() & make_numfmt()
+ */
+
+static int plot (SGP_ID *gid)
+{
+    double xmin, xmax;         /* extend of curves in world coord  */
+    double ymin, ymax;
+    double x_added_ticks;              /* number of tick spaces added to axis */
+    double y_added_ticks;
+    double symwidth, symheight;        /* size of symbol in NDC */
+    double leg_width, leg_height;      /* size of legend box */
+    int num_leg;                       /* number of legend titles */
+    int max_leg;                       /* longest legend in characters */
+    int i, j, ip, ic, n;
+
+    if (ez.i_numcurves <= 0)
+       return (FALSE);
+
+    if (ez.o_ustart == FALSE && *gid == NULL) {
+       *gid = sgp2_init (0, 0, "Ezplot");
+    }
+    
+    if (ez.s_textsize == TRUE)
+       charheight = ez.v_textsize;
+    else
+       charheight = DEF_CHARHEIGHT;
+    
+    gp_set_aspect (CRTDEV, 1.0);
+    
+    xmin = xmax = ez.curve[0].x[0];
+    ymin = ymax = ez.curve[0].y[0];
+    
+    for (ic = 0; ic < ez.i_numcurves; ic++) {
+       for (ip = 0; ip < ez.curve[ic].numpts; ip++) {
+           if (ez.curve[ic].x[ip] > xmax)
+               xmax = ez.curve[ic].x[ip];
+           else if (ez.curve[ic].x[ip] < xmin)
+               xmin = ez.curve[ic].x[ip];
+           if (ez.curve[ic].y[ip] > ymax)
+               ymax = ez.curve[ic].y[ip];
+           else if (ez.curve[ic].y[ip] < ymin)
+               ymin = ez.curve[ic].y[ip];
+       }
+    }
+    
+    /* extend graph limits for user defined axis cross positions */
+    
+    if (ez.s_xcross == TRUE)
+       {
+           if (ez.v_xcross < xmin)
+               xmin = ez.v_xcross;
+           else if (ez.v_xcross > xmax)
+               xmax = ez.v_xcross;
+       }
+    
+    if (ez.s_ycross == TRUE)
+       {
+           if (ez.v_ycross < ymin)
+               ymin = ez.v_ycross;
+           else if (ez.v_ycross > ymax)
+               ymax = ez.v_ycross;
+       }
+    
+    /* find nice endpoints for axes */
+
+    axis_scale (xmin, xmax, ez.o_xmajortick - 1, &xgw_min, &xgw_max, &x_nint);
+    axis_scale (ymin, ymax, ez.o_ymajortick - 1, &ygw_min, &ygw_max, &y_nint);
+    
+    /* check if user set x-axis extents */
+    
+    if (ez.s_xmin == TRUE) {
+       xgw_min = ez.v_xmin;
+       x_nint = ez.o_xmajortick - 1;
+    }
+    if (ez.s_xmax == TRUE) {
+       xgw_max = ez.v_xmax;
+       x_nint = ez.o_xmajortick - 1;
+    }
+    
+    /* check if user set y-axis extents */
+    
+    if (ez.s_ymin == TRUE) {
+       ygw_min = ez.v_ymin;
+       y_nint = ez.o_ymajortick - 1;
+    }
+    if (ez.s_ymax == TRUE) {
+       ygw_max = ez.v_ymax;
+       y_nint = ez.o_ymajortick - 1;
+    }
+    
+    /* calculate increment between major axis in world coordinates */
+    
+    xw_tickinc = (xgw_max - xgw_min) / x_nint;
+    yw_tickinc = (ygw_max - ygw_min) / y_nint;
+    
+    /* we have now calcuated xgw_min, xyw_max, ygw_min, & ygw_max */
+    
+    /* set the number of decimal point to users' setting or default */
+    /* Two formats for numbers
+       Fixed:    -nnn.f
+       Exponent: -n.fffE+eee
+    */
+    
+    if (ez.s_lxfrac == TRUE)
+       x_frac = ez.v_lxfrac;
+    else
+       x_frac = -1;
+    
+    if (ez.s_lyfrac == TRUE)
+       y_frac = ez.v_lyfrac;
+    else
+       y_frac = -1;
+    
+    make_numfmt (x_numfmt, &x_fldwid, &x_frac, xgw_min, xgw_max, x_nint);
+    make_numfmt (y_numfmt, &y_fldwid, &y_frac, ygw_min, ygw_max, y_nint);
+    
+    xtl_wid = x_fldwid * charwidth;            /* calc size of tick labels */
+    ytl_wid = y_fldwid * charwidth;
+    tl_height = charheight;
+    
+    /* calculate the extent of the plot frame */
+    
+    xp_min = ez.o_xporigin;
+    yp_min = ez.o_yporigin;
+    xp_max = xp_min + ez.o_xlength;
+    yp_max = yp_min + ez.o_ylength;
+
+    xp_min = clamp (xp_min, 0., 1.);
+    xp_max = clamp (xp_max, 0., 1.);
+    yp_min = clamp (yp_min, 0., 1.);
+    yp_max = clamp (yp_max, 0., 1.);
+    
+    xa_min = xp_min;           /* extent of axes */
+    xa_max = xp_max;
+    ya_min = yp_min;
+    ya_max = yp_max;
+    
+    /* adjust frame for title */
+    
+    if (strlen(ez.c_title) != 0)
+       ya_max -= 2.5 * charheight;
+    title_row = ya_max + 0.5 * charheight;
+    
+    /* calculate legend box boundaries */
+    
+    max_leg = 0;                       /* longest legend in characters */
+    num_leg = 0;                       /* number of legend titles */
+    for (i = 0; i < ez.i_numcurves; i++)
+       if ((n = strlen(ez.curve[i].legend)) > 0) {
+           ++num_leg;
+           max_leg = max(max_leg, n);
+       }
+    
+    if (num_leg > 0 && ez.o_legendbox != NOLEGEND) {
+       leg_width  = (max_leg + 2) * charwidth;
+       leg_height = num_leg * 3 * charheight;
+       
+       if (ez.s_xlegend == TRUE)
+           xl_max = ez.v_xlegend;
+       else {
+           xl_max = xa_max;
+           if (ez.o_legendbox == OUTSIDE)
+               xa_max -= (leg_width + 0.5 * charwidth);
+       }
+       xl_min = xl_max - leg_width;
+
+       if (ez.s_ylegend == TRUE)
+           yl_max = ez.v_ylegend;
+       else
+           yl_max = ya_max;
+
+       yl_min = yl_max - leg_height;
+
+       sgp2_window  (xl_min, yl_min, xl_max, yl_max);
+       sgp2_viewport (xl_min, yl_min, xl_max, yl_max);
+
+       sgp2_color (ez.clr_legend);
+       sgp2_draw_rect (xl_min, yl_min, xl_max, yl_max);
+
+       n = 0;                  /* current legend position */
+       for (i = 0; i < ez.i_numcurves; i++) {
+           double xmin, xmax, xinc, y;
+
+           if (strlen(ez.curve[i].legend) == 0)
+               continue;
+
+           xmin = xl_min + 1.0 * charwidth;
+           xmax = xl_max - 1.0 * charwidth;
+           y = yl_max - (2.0 + n * 3) * charheight;
+
+           sgp2_move_abs (xmin, y + 0.5 * charheight);
+           sgp2_draw_text (ez.curve[i].legend);
+           sgp2_color (ez.curve[i].color);
+           if (ez.curve[i].linestyle != LS_NOLINE) {
+               sgp2_line_style (ez.curve[i].linestyle);
+               sgp2_move_abs (xmin, y);
+               sgp2_line_abs (xmax, y);
+           }
+           if (ez.curve[i].symbol > 0) {
+               xinc = (xmax - xmin) / (5 - 1);
+               sgp2_line_style (LS_SOLID);
+               for (j = 0; j < 5; j++) {
+                   sgp2_move_abs (xmin + j * xinc, y);
+                   symbol(ez.curve[i].symbol,
+                          0.5 * charwidth, 0.5 * charheight);
+               }
+           }
+           ++n;                /* move to next legend position */
+       }
+    }   /* end legend printing */
+
+    /* calculate the extent of the axes */
+
+    /*-------------------------*/
+    /* adjust frame for labels */
+    /*-------------------------*/
+
+    /* x-label */
+
+    if (strlen(ez.c_xlabel) > 0)
+       ya_min += 3.0 * charheight;
+    xlbl_row = xp_min;         /* put x-label on bottom of plot frame */
+
+    /* y-label */
+
+    if (strlen(ez.c_ylabel) > 0)
+       xa_min += 3.0 * charwidth;      /* reverse charsize because writing */
+    /* text sideways */
+    ylbl_col = xp_min + 2 * charwidth;
+
+    /*------------------------------*/
+    /* adjust frame for tick labels */
+    /*------------------------------*/
+
+    /* calc offset of tick labels from axes */
+
+    if (ez.o_xaxis == NOAXIS || ez.o_xtlabel == FALSE)
+       xtl_ofs = 0.0;
+    else if (ez.o_xticks == BELOW)
+       xtl_ofs = -2.5 * charheight;
+    else if (ez.o_xticks == ABOVE)
+       xtl_ofs = 1.5 * charheight;
+
+    if (ez.o_yaxis == NOAXIS || ez.o_ytlabel == FALSE)
+       ytl_ofs = 0.0;
+    else if (ez.o_yticks == LEFT)
+       ytl_ofs = -(1 + y_fldwid) * charwidth;
+    else if (ez.o_yticks == RIGHT)
+       ytl_ofs = 1.5 * charwidth;
+
+    /* see if need to shrink axis extents and/or tick extents */
+
+    if (xtl_ofs != 0.0 && ez.s_ycross == FALSE) {
+       if (ez.o_xticks == BELOW) {
+           ya_min += 2.5 * charheight;
+           yt_min = ya_min;
+       } else if (ez.o_xticks == ABOVE) {
+           ya_min += 0.0;
+           yt_min = ya_min + 2.5 * charheight;
+       }
+    } else                     /* noaxis, no t-labels, or user set cross */
+       yt_min = ya_min;
+
+    if (ytl_ofs != 0.0 && ez.s_xcross == FALSE) {
+       if (ez.o_yticks == LEFT) {
+           xa_min += (1 + y_fldwid) * charwidth;
+           xt_min = xa_min;
+       } else if (ez.o_yticks == RIGHT) {
+           xa_min += 0.0;
+           xt_min = xa_min + ytl_ofs + y_fldwid * charwidth;
+       }
+    } else
+       xt_min = xa_min;
+
+    xt_max = xa_max;
+    yt_max = ya_max;
+
+    /* decrease size of graph, if necessary, to accommadate space */
+    /* between axis boundary and boundary of ticks */
+
+    x_added_ticks = -1;
+    y_added_ticks = -1;
+
+    if (ez.o_xaxis == NOAXIS || ez.o_xtlabel == FALSE)
+       x_added_ticks = 0;
+    if (ez.o_yaxis == NOAXIS || ez.o_ytlabel == FALSE)
+       y_added_ticks = 0;
+
+    if (ez.o_grid == TRUE) {
+       if (x_added_ticks < 0)
+           x_added_ticks = 2;
+       if (y_added_ticks < 0)
+           y_added_ticks = 2;
+    }
+
+    if (x_added_ticks < 0)
+       {
+           if (ez.o_yticks == LEFT || ez.s_ycross)
+               x_added_ticks = 1;
+           else
+               x_added_ticks = 2;
+       }
+
+    if (y_added_ticks < 0)
+       {
+           if (ez.o_xticks == BELOW || ez.s_xcross)
+               y_added_ticks = 1;
+           else
+               y_added_ticks = 2;
+       }
+
+    xn_tickinc = (xt_max - xt_min) / (x_nint + x_added_ticks);
+    yn_tickinc = (yt_max - yt_min) / (y_nint + y_added_ticks);
+
+    xt_min += 0.5 * x_added_ticks * xn_tickinc;
+    xt_max -= 0.5 * x_added_ticks * xn_tickinc;
+    yt_min += 0.5 * y_added_ticks * yn_tickinc;
+    yt_max -= 0.5 * y_added_ticks * yn_tickinc;
+
+    xgn_min = xt_min;
+    xgn_max = xt_max;
+    ygn_min = yt_min;
+    ygn_max = yt_max;
+
+    /*---------------------------------------------------------------------------*/
+
+    /* PLOT CURVES */
+
+    sgp2_line_style (LS_SOLID);
+    drawaxis();
+
+    /* Convert WC in graph boundary to axis boundary */
+    {
+       double xmin, xmax, ymin, ymax;
+
+       sgp2_window  (xgw_min, ygw_min, xgw_max, ygw_max);      /* Graph boundary */
+       sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
+
+       ndc_to_wc (xa_min, ya_min, &xmin, &ymin);       /* calc WC of axis */
+       ndc_to_wc (xa_max, ya_max, &xmax, &ymax);       /* boundaries */
+
+       sgp2_window  (xmin, ymin, xmax, ymax);          /* Set window to axis */
+       sgp2_viewport (xa_min, ya_min, xa_max, ya_max); /* boundaries */
+    }
+    symwidth = charwidth * (xgw_max - xgw_min);
+    symheight = charheight * (ygw_max - ygw_min);
+
+    for (ic = 0; ic < ez.i_numcurves; ic++) {
+       sgp2_color (ez.curve[ic].color);
+       if (ez.curve[ic].linestyle != LS_NOLINE) {
+           sgp2_line_style (ez.curve[ic].linestyle);
+           sgp2_polyline_abs (ez.curve[ic].x, ez.curve[ic].y, ez.curve[ic].numpts);
+       }
+       if (ez.curve[ic].symbol > 0) {
+           sgp2_line_style(LS_SOLID);
+           sgp2_move_abs (ez.curve[ic].x[0], ez.curve[ic].y[0]);
+           symbol (ez.curve[ic].symbol, symwidth, symheight);
+           for (i = 1; i < ez.curve[ic].numpts; i++)
+               if (i % ez.curve[ic].symfreq == 0 || i == ez.curve[ic].numpts - 1) {
+                   sgp2_move_abs (ez.curve[ic].x[i], ez.curve[ic].y[i]);
+                   symbol (ez.curve[ic].symbol, symwidth, symheight);
+               }
+       }
+    }
+    if (ez.o_ufinish == FALSE)
+       termgrf2 ();
+    return (TRUE);
+}
+
+
+/* NAME
+ *   drawaxis                  INTERNAL routine to draw axis & label them
+ *
+ * SYNOPSIS
+ *   drawaxis()
+ */
+
+static void drawaxis(void)
+{
+    double xticklen = 0, yticklen = 0; /* length of ticks in NDC */
+    double minorinc;           /* increment between minor axes */
+    double xaxispos, yaxispos; /* crossing of axes */
+    double x, y, x2, y2;
+    bool axis_near;                    /* TRUE if axis too close to print t-label */
+    int i, j;
+    char str[100];
+    char *numstr;
+
+    charsize (charwidth, charheight);
+    settextclr (1, -1);
+
+    if (ez.o_xticks == ABOVE)
+       xticklen = charheight;
+    else if (ez.o_xticks == BELOW)
+       xticklen = -charheight;
+
+    if (ez.o_yticks == RIGHT)
+       yticklen = charwidth;
+    else if (ez.o_yticks == LEFT)
+       yticklen = -charwidth;
+
+    sgp2_window  (xp_min, yp_min, xp_max, yp_max);
+    sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
+
+    if (strlen (ez.c_title) != 0) {
+       sgp2_move_abs (xa_min + (xa_max-xa_min)/2 - strlen(ez.c_title)*charwidth, title_row);
+       charsize (charwidth * 2.0, charheight * 2.0);
+       settextclr (ez.clr_title, -1);
+       sgp2_draw_text (ez.c_title);
+       charsize (charwidth, charheight);
+    }
+
+    if (ez.o_grid == TRUE || ez.o_box == TRUE) {
+       sgp2_color (ez.clr_axis);
+       sgp2_move_abs (xa_min, ya_min);
+       sgp2_line_abs (xa_max, ya_min);
+       sgp2_line_abs (xa_max, ya_max);
+       sgp2_line_abs (xa_min, ya_max);
+       sgp2_line_abs (xa_min, ya_min);
+    }
+
+    /* calculate position of axes */
+
+    /* x-axis */
+    if (ez.s_ycross == TRUE) { /* convert users' world-coord */
+       xaxispos = ez.v_ycross; /* axis to its position in NDC */
+       sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max);
+       sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
+       x = xgw_min;
+       wc_to_ndc (x, xaxispos, &x, &xaxispos);
+    } else
+       xaxispos = ya_min;
+
+    /* y-axis */
+    if (ez.s_xcross == TRUE) { /* convert users' world-coord */
+       yaxispos = ez.v_xcross; /* axis to its NDC position */
+       sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max);
+       sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
+       y = ygw_min;
+       wc_to_ndc (yaxispos, y, &yaxispos, &y);
+    } else
+       yaxispos = xa_min;
+
+    /*-------------*/
+    /* draw x-axis */
+    /*-------------*/
+
+    if (ez.o_xaxis == LINEAR) {
+       sgp2_window (xp_min, yp_min, xp_max, yp_max);
+       sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
+
+       /* draw axis line */
+
+       sgp2_color (ez.clr_axis);
+       if (ez.o_tag && !ez.o_grid && !ez.o_box && ez.s_xcross) {
+           sgp2_move_abs (xa_min, xaxispos - charheight);
+           sgp2_line_abs (xa_min, xaxispos + charheight);
+       }
+       sgp2_move_abs (xa_min, xaxispos);
+       sgp2_line_abs (xa_max, xaxispos);
+       if (ez.o_tag && !ez.o_grid && !ez.o_box) {
+           sgp2_move_abs (xa_max, xaxispos - charheight);
+           sgp2_line_abs (xa_max, xaxispos + charheight);
+       }
+
+       if (ez.o_grid == TRUE) {
+           sgp2_color (ez.clr_grid);
+           for (i = 0; i <= x_nint; i++) {
+               sgp2_move_abs (xt_min + xn_tickinc * i, ya_max);
+               sgp2_line_abs (xt_min + xn_tickinc * i, ya_min);
+           }
+       }
+       sgp2_move_abs (xa_min + (xa_max-xa_min)/2 - strlen(ez.c_xlabel)*charwidth, xlbl_row);
+       charsize (charwidth * 2.0, charheight * 2.0);
+       settextclr (ez.clr_label, -1);
+       sgp2_draw_text (ez.c_xlabel);
+       charsize (charwidth, charheight);
+       minorinc = xn_tickinc / (ez.o_xminortick + 1);
+
+       for (i = 0; i <= x_nint; i++) {
+           x = xt_min + xn_tickinc * i;
+           sgp2_color (ez.clr_axis);
+           sgp2_move_abs (x, xaxispos);
+           sgp2_line_abs (x, xaxispos + xticklen);
+           if (i != x_nint)
+               for (j = 1; j <= ez.o_xminortick; j++) {
+                   x2 = x + minorinc * j;
+                   sgp2_move_abs (x2, xaxispos);
+                   sgp2_line_abs (x2, xaxispos + TICKRATIO * xticklen);
+               }
+           axis_near = FALSE;
+           if (xaxispos + xtl_ofs > ya_min && ez.o_yaxis != NOAXIS) {
+               double xw, x, y, d;
+
+               xw = xgw_min + i * xw_tickinc;
+               sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max);
+               sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
+               wc_to_ndc (xw, y, &x, &y);
+               sgp2_window (xp_min, yp_min, xp_max, yp_max);
+               sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
+               d = x - yaxispos;
+               if (ez.o_yticks == RIGHT && d >= 0  && d < 0.9 * xn_tickinc)
+                   axis_near = TRUE;
+               if (ez.o_yticks == LEFT && d <= 0 && d > -0.9 * xn_tickinc)
+                   axis_near = TRUE;
+           }
+
+           if (ez.o_xtlabel == TRUE && axis_near == FALSE) {
+               snprintf (str, sizeof(str), x_numfmt, xgw_min + xw_tickinc * i);
+               numstr = str_skip_head (str, " ");
+               sgp2_move_abs (x-strlen(numstr)*charwidth/2,xaxispos + xtl_ofs);
+               settextclr (ez.clr_number, -1);
+               sgp2_draw_text (numstr);
+           }
+       }
+    }          /* x - axis */
+
+
+    /*--------*/
+    /* y-axis */
+    /*--------*/
+
+    if (ez.o_yaxis == LINEAR) {
+       sgp2_window  (xp_min, yp_min, xp_max, yp_max);
+       sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
+
+       sgp2_color (ez.clr_axis);
+       if (ez.o_tag && !ez.o_grid && !ez.o_box && ez.s_ycross) {
+           sgp2_move_abs (yaxispos - charwidth, ya_min);
+           sgp2_line_abs (yaxispos + charwidth, ya_min);
+       }
+       sgp2_move_abs (yaxispos, ya_min);
+       sgp2_line_abs (yaxispos, ya_max);
+       if (ez.o_tag && !ez.o_grid && !ez.o_box) {
+           sgp2_move_abs (yaxispos - charwidth, ya_max);
+           sgp2_line_abs (yaxispos + charwidth, ya_max);
+       }
+
+       if (ez.o_grid == TRUE) {
+           sgp2_color (ez.clr_grid);
+           for (i = 0; i <= y_nint; i++) {
+               y = yt_min + yn_tickinc * i;
+               sgp2_move_abs (xa_max, y);
+               sgp2_line_abs (xa_min, y);
+           }
+       }
+       sgp2_move_abs (ylbl_col,ya_min + (ya_max-ya_min)/2 - strlen(ez.c_ylabel)*charheight);
+       textangle (HALFPI);
+       charsize (2 * charheight, 2 * charwidth);       /* axis reversed */
+       settextclr (ez.clr_label, -1);
+       sgp2_draw_text (ez.c_ylabel);
+       textangle (0.0);
+       charsize (charwidth, charheight);
+       minorinc = yn_tickinc / (ez.o_yminortick + 1);
+
+       for (i = 0; i <= y_nint; i++) {
+           y = yt_min + yn_tickinc * i;
+           sgp2_color (ez.clr_axis);
+           sgp2_move_abs (yaxispos, y);
+           sgp2_line_abs (yaxispos + yticklen, y);
+           if (i != y_nint)
+               for (j = 1; j <= ez.o_yminortick; j++) {
+                   y2 = y + minorinc * j;
+                   sgp2_move_abs (yaxispos, y2);
+                   sgp2_line_abs (yaxispos + TICKRATIO * yticklen, y2);
+               }
+           axis_near = FALSE;
+           if (yaxispos + ytl_ofs > xa_min && ez.o_xaxis != NOAXIS) {
+               double yw, x, y, d;
+
+               yw = ygw_min + i * yw_tickinc;
+               sgp2_window (xgw_min, ygw_min, xgw_max, ygw_max);
+               sgp2_viewport (xgn_min, ygn_min, xgn_max, ygn_max);
+               wc_to_ndc (x, yw, &x, &y);
+               sgp2_window (xp_min, yp_min, xp_max, yp_max);
+               sgp2_viewport (xp_min, yp_min, xp_max, yp_max);
+               d = y - xaxispos;
+               if (ez.o_xticks == ABOVE && d >= 0 && d < 0.9 * yn_tickinc)
+                   axis_near = TRUE;
+               if (ez.o_xticks == BELOW && d <= 0 && d > -0.9 * yn_tickinc)
+                   axis_near = TRUE;
+           }
+           if (ez.o_ytlabel == TRUE && axis_near == FALSE) {
+               snprintf (str, sizeof(str), y_numfmt, ygw_min + yw_tickinc * i);
+               sgp2_move_abs (yaxispos + ytl_ofs, y - 0.5 * charheight);
+               settextclr (ez.clr_number, -1);
+               sgp2_draw_text (str);
+           }
+       }
+    }          /* y - axis */
+}
+
+
+static void 
+symbol (int sym, double symwidth, double symheight)
+{
+    if (sym <= 0)
+       return;
+
+    if (sym == SB_CROSS) {
+       sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight);
+       sgp2_line_rel (symwidth, symheight);
+       sgp2_move_rel (-symwidth, 0.0);
+       sgp2_line_rel (symwidth, -symheight);
+       sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight);
+    } else if (sym == SB_PLUS) {
+       sgp2_move_rel (-0.5 * symwidth, 0.0);
+       sgp2_line_rel (symwidth, 0.0);
+       sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight);
+       sgp2_line_rel (0.0, symheight);
+       sgp2_move_rel (0.0, -0.5 * symheight);
+    } else if (sym == SB_BOX) {
+       sgp2_move_rel (-0.5 * symwidth, -0.5 * symheight);
+       sgp2_line_rel (symwidth, 0.0);
+       sgp2_line_rel (0.0, symheight);
+       sgp2_line_rel (-symwidth, 0.0);
+       sgp2_line_rel (0.0, -symheight);
+       sgp2_move_rel (0.5 * symwidth, 0.5 * symheight);
+    } else if (sym == SB_CIRCLE) {
+       sgp2_draw_circle (symwidth);
+    } else if (sym == SB_ERRORBAR) {
+       sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight);
+       sgp2_line_rel (symwidth, 0.0);
+       sgp2_move_rel (-0.5 * symwidth, 0.0);
+       sgp2_line_rel (0.0, -symheight);
+       sgp2_move_rel (-0.5 * symwidth, 0.0);
+       sgp2_line_rel (symwidth, 0.0);
+       sgp2_move_rel (-0.5 * symwidth, 0.5 * symheight);
+    }
+}
+
+
+void ezinit(void)
+{
+    /* EZPLOT Variables */
+
+    charwidth = DEF_CHARWIDTH; /* KR_FIX: Make these ez.o_ variables */
+    charheight = DEF_CHARHEIGHT;
+
+    /* EZPLOT & EZSET Variables */
+
+    strcpy (ez.c_xlabel, "X axis");
+    strcpy (ez.c_ylabel, "Y axis");
+    strcpy (ez.c_title, "");
+    strcpy (ez.c_legend, "");
+
+    ezplot_firstcall = FALSE;
+
+    ez.i_numcurves = 0;
+    ez.i_plotimmediate = FALSE;
+
+    ez.o_reqcurves = 1;
+    ez.o_unknowncurves = FALSE;
+
+    ez.o_ustart = FALSE;
+    ez.o_ufinish = FALSE;
+
+    ez.o_xporigin = 0.0;
+    ez.o_yporigin = 0.0;
+    ez.o_xlength  = 1.0;
+    ez.o_ylength  = 1.0;
+
+    ez.o_xaxis = LINEAR;
+    ez.o_yaxis = LINEAR;
+
+    ez.o_grid = FALSE;
+    ez.o_box = FALSE;
+
+    ez.o_xmajortick = 10;
+    ez.o_ymajortick =  8;
+    ez.o_xminortick =  4;
+    ez.o_yminortick =  4;
+
+    ez.o_color = DEF_CURVE_CLR;
+    ez.o_symfreq = 1;
+    ez.o_symbol = -1;
+    ez.o_linestyle = LS_SOLID;
+
+    ez.o_xtlabel = TRUE;
+    ez.o_ytlabel = TRUE;
+    ez.o_xticks = BELOW;
+    ez.o_yticks = LEFT;
+
+    ez.o_legendbox = INSIDE;
+    ez.o_tag = FALSE;
+
+    ez.s_xtitle   = FALSE;
+    ez.s_ytitle   = FALSE;
+    ez.s_xcross   = FALSE;
+    ez.s_ycross   = FALSE;
+    ez.s_lxfrac   = FALSE;
+    ez.s_lyfrac   = FALSE;
+    ez.s_xlegend  = FALSE;
+    ez.s_ylegend  = FALSE;
+    ez.s_textsize = FALSE;
+
+    ez.d_usecrt = TRUE;
+    ez.d_useprt = FALSE;
+    ez.d_crtmode = DEF_CRTMODE;
+    ez.d_prtmode = PRTMODE_DEF;
+    ez.d_xprtbuf = XBUF_DEF;
+    ez.d_yprtbuf = YBUF_DEF;
+
+    ez.clr_axis   = C_WHITE;           /* set fixed colors */
+    ez.clr_title  = (C_CYAN+8);
+    ez.clr_label  = (C_CYAN+8);
+    ez.clr_legend = (C_RED+8);
+    ez.clr_number = (C_GREEN+8);
+    ez.clr_grid   = (C_BLACK+8);
+}
+
+void ezfree(void)
+{
+    static char errmsg[] = "EZFREE in EZPLOT";
+    int i;
+    
+    for (i = 0; i < ez.i_numcurves; i++) {
+       delete ez.curve[i].x;
+       delete ez.curve[i].y;
+    }
+    ez.i_numcurves = 0;
+}
+
+void ezclear(void)
+{
+    ezfree();
+    ezinit();
+}
diff --git a/libctgraphics/ezpol.cpp b/libctgraphics/ezpol.cpp
new file mode 100644 (file)
index 0000000..54932f3
--- /dev/null
@@ -0,0 +1,1172 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: ezpol.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+/*----------------------------------------------------------------------*/
+/*                     POL - Problem Oriented Language                 */
+/*                                                                     */
+/*----------------------------------------------------------------------*/
+
+#include <math.h>
+#include "ascii.h"
+#include "stdio.h"
+#include "kstddef.h"
+#include "ctype.h"
+#include "pol.h"
+
+#define HASHSIZE 20
+
+/* Tables words stored with install() & found with lookup() */
+
+static SYMBOL *skiptable[HASHSIZE];            /* words to ignore and skip */
+static SYMBOL *cmdtable[HASHSIZE];             /* pol parameter commands */
+static SYMBOL *usertable[HASHSIZE];            /* user defined symbols */
+
+static struct token_st token;                          /* current token */
+
+static struct metachar {
+    char eoc;          /* end of command character */
+    char str;          /* string delimiter */
+    char com;          /* comment character */
+    char cmd;          /* pol parameter command character */
+    char prg;          /* program load character */
+    char con;          /* continuation across newline character */
+    char out;          /* character that delimits output to terminal */
+    char ter;          /* character indicates insertion of input from terminal */
+    char inb;          /* input from graphics device */
+} meta;
+
+/* current pol state */
+
+static struct pol_st {
+    char skipchars[MAXSKIPCHAR];       /* characters to skip */
+    int nl_eoc;                                /* TRUE if newline character ends a command */
+    int trace;                         /* TRUE if trace is on */
+} pol;
+
+struct key {
+    char *keyword;
+    int  code;
+};
+
+/* internal codes for pol commands */
+
+#define PC_EOC     1
+#define PC_STR     2
+#define PC_COM     3
+#define PC_CMD     4
+#define PC_PRG     5
+#define PC_CON     6
+#define PC_OUT     7
+#define PC_TER     8
+#define PC_INB     9
+#define PC_NL_EOC  10
+#define PC_NL_NEOC 11
+#define PC_TRON           12
+#define PC_TROFF   13
+#define PC_FILE           14
+#define PC_DUMP           15
+
+static struct key cmdlist[] = {
+  {    "eoc",  PC_EOC,},
+  {    "str",  PC_STR,},
+  {    "com",  PC_COM,},
+  {    "cmd",  PC_CMD,},
+  {    "prg",  PC_PRG,},
+  {    "con",  PC_CON,},
+  {    "out",  PC_OUT,},
+  {    "ter",  PC_TER,},
+  {    "inb",  PC_INB,},
+
+  {    "nl_eoc",PC_NL_EOC,},
+  {    "nl_neoc", PC_NL_NEOC,},
+  {    "tron",  PC_TRON,},
+  {    "troff", PC_TROFF,},
+  {    "file",  PC_FILE,},
+  {    "dump",  PC_DUMP,},
+};
+
+#define NUMCMD (sizeof(cmdlist) / sizeof (struct key))
+
+static int ignorecase = TRUE;
+
+static int skiptok(char term[]);
+static int pol_tok(struct token_st *token);
+static void dumptok(struct token_st *token);
+
+
+static int getpol_tok(struct token_st *token);
+static int getcmd(void);
+static int gettok (TOKEN *tok);
+static void getblank(char *s, int toksiz);
+static int getalpha(char *s, int toksiz);
+static void getquote(char *qs, int toksiz);
+static void getescape(char *s, int delim, int toksiz);
+static int getnumber (char str[], int strsize, double *fnum, int *inum);
+static void eatline(void);
+static int type(int c);
+static void inittable(SYMBOL *table[]);
+static void freetable(SYMBOL *table[]);
+static int hash(char *s);
+static SYMBOL *lookup(SYMBOL *table[], char *s);
+static SYMBOL *install(SYMBOL *table[], char *s, int def);
+static void outch(int c);
+static void inc_line(void);
+static int getlinect(void);
+static void setlinect(int n);
+static void synerr(char *msg);
+static int pol_getch(FILE *fp);
+static void ungets(char *s);
+
+
+void pol_init (void)
+{
+       int i;
+
+       meta.eoc    = SEMICOL;
+       meta.str    = DQUOTE;
+       meta.com    = SHARP;
+       meta.cmd    = EXCLAM;
+       meta.prg    = ATSIGN;
+       meta.con    = AMPERSAND;
+       meta.out    = DOLLAR;
+       meta.ter    = PERCENT;
+       meta.inb    = LBRACK;
+
+       pol.nl_eoc = TRUE;
+       pol.skipchars[0] = EOS;
+
+       inittable (cmdtable);           /* initialize symbol tables */
+       inittable (usertable);
+       inittable (skiptable);
+
+       for (i = 0; i < NUMCMD; i++)
+           install (cmdtable, cmdlist[i].keyword, cmdlist[i].code);
+
+       token.ready = FALSE;            /* no token read yet */
+}
+
+/* pol_skpword (w)
+ *
+ * char *w - word for pol to ignore and skip over in input
+ *
+ * pol_tok() compares all tokens to words given to this routine. If it finds it,
+ * it will immediately read another token. 
+ */
+
+void 
+pol_skpword (char *w)
+{
+       if (install (skiptable, w, 0) == NULL)
+           synerr ("Too many skip words defined");
+}
+
+/* pol_skpchar (s)
+ *
+ * skip all characters that appear in string s
+ */
+void 
+pol_skpchar (char *s)
+{
+       strncpy (pol.skipchars, s, MAXSKIPCHAR);
+}
+
+/* pol_install (str, code)
+ *
+ * char *str - token string to install
+ * int code  - code to return for token
+ *
+ * pol_tok() looks for these user defined tokens.  If it finds one,
+ * it stores the tokens code in the token structure and returns TT_USERTOK
+ */
+int 
+pol_install (char *str, int code)
+{
+    if (install (usertable, str, code) == NULL)
+       {
+           synerr ("Out ot memory installing user tokens");
+           return (FALSE);
+       }
+    
+    return(TRUE);
+}
+
+/* get_word - matches tokens on a letter by letter basis
+ *
+ * char *search - string to search for
+ * int  nlet   - maximum number of chars to search for match
+ */
+
+int 
+pol_word (char *search, int nlet)
+{
+       pol_tok (&token);
+       if (pol.trace == TRUE)
+           printf ("matching current token %s against word %s\n", token.tokstr, search);
+
+       if (strncasecmp (search, token.tokstr, nlet) == 0) {
+           dumptok (&token);
+           return (TRUE);
+       } else
+           return (FALSE);
+}
+
+/* pol_usertok (str,code)
+ *     see if current token is a user defined token set with pol_install()
+ *
+ *    char *str - token string as read from input
+ *    int *code - returned code for user defined symbol
+ *    return value - TRUE if current token has been user defined
+ *                  FALSE if current token is not user defined
+ */
+int 
+pol_usertok (char *str, int *code)
+{
+       pol_tok (&token);
+
+       if (pol.trace == TRUE)
+           printf ("checking if current token '%s' is user defined\n", token.tokstr);
+
+       if (token.type == TT_USERTOK) {
+           *code = token.code;
+           strcpy (str, token.tokstr);
+           dumptok (&token);
+           return (TRUE);
+       } else {
+           *code = 0;
+           return (FALSE);
+       }
+}
+
+/* isstring (s) - returns TRUE if current token is a string
+ *
+ * char *s - pointer to place to store token string
+*/
+int 
+pol_string (char *str)
+{
+       pol_tok (&token);
+
+       if (token.type == TT_STRING) {
+           strcpy (str, token.tokstr);
+           dumptok (&token);
+           return (TRUE);
+       } else
+           return (FALSE);
+}
+
+/* pol_integer - test for an integer
+ *
+ * int *n:     returned integer value
+ * int typecode = TT_INT if accept only integer values
+ *             = TT_REAL if accept both real and integer values
+ * int boundcode= TRUE if force to lie between boundries
+ *             = FALSE can take any value it likes
+ * int bb1:    lower bound
+ * int bb2:    upper bound
+*/
+int 
+pol_integer (int *n, int typecode, int boundcode, int bb1, int bb2)
+{
+       pol_tok (&token);
+
+       if (pol.trace == TRUE)
+           printf ("checking if current token %s is an integer\n", token.tokstr);
+
+       if (token.type == TT_INT || token.type == TT_REAL) {
+          if (boundcode == TRUE) {
+               if (token.inum < bb1)
+                  *n = bb1;
+               else if (token.inum > bb2)
+                  *n = bb2;
+               else
+                   *n = token.inum;
+           } else
+               *n = token.inum;
+           dumptok (&token);
+           return (TRUE);
+       }
+       *n = 0;
+       return (FALSE);
+}
+
+int 
+pol_float (double *n, double typecode, double boundcode, double bb1, double bb2)
+{
+       pol_tok (&token);
+
+       if (pol.trace == TRUE)
+           printf ("checking if current token %s is an floating point number\n", token.tokstr);
+
+       if (token.type == TT_INT || token.type == TT_REAL) {
+          if (boundcode == TRUE) {
+               if (token.fnum < bb1)
+                  *n = bb1;
+               else if (token.fnum > bb2)
+                  *n = bb2;
+               else
+                   *n = token.fnum;
+           } else
+               *n = token.fnum;
+           dumptok (&token);
+           return (TRUE);
+       }
+       *n = 0.0;
+       return (FALSE);
+}
+
+/*----------------------------------------------------------------------*/
+/* pol_skip() - skip over any token except for end of command sequence */
+/*                                                                     */
+/*             returns TRUE if succesful skip                          */
+/*             returns FALSE if already at end of command or EOF       */
+/*----------------------------------------------------------------------*/
+
+int pol_skip(void)
+{
+       char term[5];           /* string of characters not to skip */
+
+       term[0] = meta.eoc;
+       if (pol.nl_eoc == TRUE) {
+           term[1] = NEWLINE;
+           term[2] = EOS;
+       } else
+           term[1] = EOS;
+
+       return (skiptok (term));
+}
+
+void pol_reader(void)
+{
+       while (pol_skip() == TRUE)
+           ;
+
+       dumptok (&token);               /* skip end of command token */
+}
+
+/* skiptok (term) - skip a token unless the first character of a token is
+ *                 in the string of terminators, term.
+ * char *term - string of termination characters, don't skip these characters
+ *             skiptok() also does NOT skip TT_EOF
+ * returns (TRUE) if succesful skip of a token
+ * returns (FALSE) if didn't skip, read termination character or TT_EOF
+ */
+
+static int 
+skiptok (char term[])
+{
+       pol_tok (&token);
+
+       if (token.type == TT_EOF
+       || (token.type == TT_SPECLCHAR && strchr(term, token.tokstr[0]) != NULL))
+               return (FALSE);
+       else {
+           dumptok (&token);
+           return (TRUE);
+       }
+}
+
+static int 
+pol_tok (struct token_st *token)
+{
+       if (token->ready == FALSE)
+           getpol_tok(token);
+       else
+           if (token->type == TT_EOF && pol_lookchar() != EOF)
+               getpol_tok(token);
+       return (token->type);
+}
+
+static void 
+dumptok (struct token_st *token)
+{
+       if (token->ready == FALSE)
+           getpol_tok(token);
+       token->ready = FALSE;
+}
+
+static int 
+getpol_tok (struct token_st *token)
+{
+       SYMBOL *sym;
+
+       token->ready = FALSE;
+nexttok:
+       gettok (token);
+
+       if (token->type == TT_BLANK)
+           goto nexttok;
+       if (token->type == TT_SPECLCHAR) {
+           if (strchr(pol.skipchars, token->tokstr[0]) != NULL)
+               goto nexttok;
+           if (token->tokstr[0] == NEWLINE)
+               goto nexttok;
+           if (token->tokstr[0] == meta.cmd) {
+               getcmd();
+               goto nexttok;
+           }
+           if (token->tokstr[0] == meta.com) {         /* skip comment */
+               eatline ();
+               goto nexttok;
+           }
+           if (token->tokstr[0] == meta.out) {
+               getescape(token->tokstr, meta.out, MAXTOK);
+               fputs (token->tokstr, stderr);
+               goto nexttok;
+           }
+           if (token->tokstr[0] == meta.con) {         /* continuation across NEWLINE */
+               while (pol_lookchar() == BLANK || pol_lookchar() == TAB)
+                   pol_inchar();
+               if (pol_lookchar() == NEWLINE)
+                   pol_inchar();
+           }
+           if (token->tokstr[0] == meta.ter) {         /* get input from terminal */
+               pol_usefile (P_USE_FILE, "");
+               pol_tok (token);
+               pol_closefile();
+               return (token->type);
+           }
+       }
+
+       /* look for filler words */
+
+       if (lookup (skiptable, token->tokstr) != NULL)  /* ignore words in skip table */
+           goto nexttok;
+
+       /* look for user defined symbols */
+
+       if ((sym = lookup (usertable, token->tokstr)) != NULL) {
+           token->type = TT_USERTOK;
+           token->code = sym->code;
+       } else
+           token->code = 0;
+
+       if (pol.trace == TRUE)
+           printf ("Read token '%s', type = %d\n", token->tokstr, token->type);
+
+       return (token->type);
+}
+
+
+static int getcmd(void)
+{
+       int tt, found;
+       char str[MAXTOK+1];
+       SYMBOL *cmd;
+       TOKEN tok;
+
+       tt = getalpha (str, MAXTOK);
+       if (tt == TT_ERROR) {
+           synerr ("error in pol parameter command");
+           pol_reader();
+           return(FALSE);
+       }
+       if ((cmd = lookup (cmdtable,str)) == NULL) {
+           synerr ("unrecognized command");
+           pol_reader();
+           return (FALSE);
+       } else {
+           found = FALSE;
+           switch (cmd->code) {
+               case PC_TRON:
+                   pol.trace = TRUE;
+                   found = TRUE;
+                   break;
+               case PC_TROFF:
+                   pol.trace = FALSE;
+                   found = TRUE;
+                   break;
+               case PC_FILE:
+                   found = TRUE;
+                   tt = gettok (&tok);
+                   pol_usefile (P_USE_FILE, tok.tokstr);
+                   break;
+               case PC_NL_EOC:
+                   found = TRUE;
+                   pol.nl_eoc = TRUE;
+                   break;
+               case PC_NL_NEOC:
+                   found = TRUE;
+                   pol.nl_eoc = FALSE;
+                   break;
+               case PC_DUMP:
+                   found = TRUE;
+                   printf("eoc = %c  str = %c  com = %c  cmd = %c  prg = %c\n",
+                       meta.eoc, meta.str, meta.com, meta.cmd, meta.prg);
+                   printf("con = %c  out = %c  ter = %c  inb = %c\n",
+                       meta.con, meta.out, meta.ter, meta.inb);
+                   break; 
+           }
+           if (found == FALSE) {
+               tt = gettok (&tok);
+               if (tt != TT_SPECLCHAR) {
+                   synerr("illegal command character");
+                   return (FALSE);
+               }
+               switch(cmd->code) {
+                   case PC_EOC:
+                       meta.eoc = tok.tokstr[0];
+                       break;
+                   case PC_STR:
+                       meta.str = tok.tokstr[0];
+                       break;
+                   case PC_COM:
+                       meta.com = tok.tokstr[0];
+                       break;
+                   case PC_CMD:
+                       meta.cmd = tok.tokstr[0];
+                       break;
+                   case PC_PRG:
+                       meta.prg = tok.tokstr[0];
+                       break;
+                   case PC_CON:
+                       meta.con = tok.tokstr[0];
+                       break;
+                   case PC_OUT:
+                       meta.out = tok.tokstr[0];
+                       break;
+                   case PC_TER:
+                       meta.ter = tok.tokstr[0];
+                       break;
+                   case PC_INB:
+                       meta.inb = tok.tokstr[0];
+                       break;
+                   default:
+                       printf("command not implemented\n");
+                       break;
+               }                               /* switch (tok->type) */
+           }                                   /* if (found == FALSE) */
+           pol_reader();                       /* clean up command */
+       }                                       /* if legal command */
+
+       return (TRUE);
+}
+
+
+static int 
+gettok (TOKEN *tok)
+{
+       int c, toktype;
+       int inum;
+       double fnum;
+       int toksiz = MAXTOK;            /* maximum length of token string */
+
+       while ((c = pol_inchar()) == BLANK || c == TAB)
+           ;
+       pol_ungetch (c);
+
+       c = pol_lookchar();
+       toktype = type(c);
+
+       fnum = 0.0;
+       inum = 0;
+
+       if (c == BLANK || c == TAB) {                   /* skip white space */
+           getblank(tok->tokstr, toksiz);
+           toktype = TT_BLANK;
+       } else if (toktype == LETTER) {
+           toktype = getalpha (tok->tokstr, toksiz);
+       } else if (c == meta.str) {                     /* quoted string */
+           getquote (tok->tokstr, toksiz);
+           toktype = TT_STRING;
+       } else if (type(c) == DIGIT || c == PLUS || c == HYPHEN || c == PERIOD) {
+           toktype = getnumber (tok->tokstr, toksiz, &fnum, &inum);
+       } else if (c == EOF) {
+           tok->tokstr[0] = EOS;
+           toktype = TT_EOF;
+       } else {
+           c = pol_inchar();
+           tok->tokstr[0] = c;
+           tok->tokstr[1] = EOS;
+           toktype = TT_SPECLCHAR;
+       }
+
+       tok->type = toktype;
+       tok->ready = TRUE;
+       if (tok->type == TT_REAL || tok->type == TT_INT) {
+           tok->fnum = fnum;
+           tok->inum = inum;
+       } else {
+           tok->fnum = 0.0;
+           tok->inum = 0;
+       }
+
+       return (toktype);
+}
+
+
+static void 
+getblank (char *s, int toksiz)
+{
+       int c;
+
+       while ((c = pol_inchar()) == BLANK || c == TAB)
+             ;
+       pol_ungetch(c);
+
+       s[0] = BLANK;
+       s[1] = EOS;
+}
+
+
+static int 
+getalpha (char *s, int toksiz)
+{
+       int i, chartype, alphatype;
+
+       if (type(pol_lookchar()) != LETTER) {
+           s[0] = EOS;
+           return (TT_ERROR);
+       }
+
+       alphatype = TT_ALPHA;
+       for (i = 0; i < toksiz; i++) {          /* get alphanumeric token */
+           s[i] = pol_inchar();
+           chartype = type (s[i]);
+           if (chartype != LETTER && chartype != DIGIT)
+               break;
+           if (chartype == DIGIT)
+               alphatype = TT_ALPNUM;
+       }
+       pol_ungetch(s[i]);
+
+       if (i >= toksiz)
+           synerr("token too long.");
+
+       s[i] = EOS;                     /* terminate token */
+       return (alphatype);
+}
+
+
+/* getquote - get quoted string from file */
+/* have already gotten delimiter in qs[0] */
+static void 
+getquote (char *qs, int toksiz)
+{
+       int delim;
+
+       delim = pol_inchar();                   /* char = delimiter */
+       getescape(qs, delim, toksiz);
+}
+
+
+static void 
+getescape (    /* reads up to delim */
+    char *s,
+    int delim,
+    int toksiz
+)
+{
+       int i, c;
+
+       for (i = 0; (c = pol_inchar()) != delim; i++) {
+           if (c == NEWLINE) {
+               synerr ("Missing closing delimiter.");
+               break;
+           }
+           if (i >= toksiz) {
+               synerr("string too long.");
+               break;
+           }
+           if (c == EOF) {
+               pol_ungetch(c);
+               synerr("end of file inside quotation");
+               break;
+           } else if (c == BSLASH) {   /* escape character */
+               s[i++] = c;
+               c = pol_inchar();               /* get escaped character */
+           }
+           s[i] = c;
+       }
+       s[i] = EOS;
+}
+
+void 
+gettext (char *str, int lim)
+{
+       int c, i;
+
+       while ((c = pol_inchar()) == BLANK || c == TAB)
+           ;
+       pol_ungetch (c);
+
+       for (i = 0; i < lim && (c = pol_inchar()) != EOF && c != NEWLINE; i++)
+           str[i] = c;
+       pol_ungetch (c);
+       str[i] = EOS;
+}
+
+/*----------------------------------------------*/
+/* Get a number for gettok()                   */
+/*----------------------------------------------*/
+
+static int 
+getnumber (
+    char str[],                                /* string to return token in */
+    int strsize,                               /* maximum length of token string */
+    double *fnum,                              /* floating point value of number read */
+    int *inum                          /* integer value of number read */
+)
+{
+       int c, sp, isSigned;
+       double sign, whole, frac, powerof10, exp, expsign;
+
+       sp = 0;
+       sign = 1.0;
+       isSigned = FALSE;               /* TRUE if number prefixed by '+' or '-' */ 
+       *fnum = 0.0;
+       *inum = 0;
+       str[0] = EOS;
+
+       c = pol_inchar();
+       if (c == HYPHEN) {
+           str[sp++] = c;
+           isSigned = TRUE;
+           sign = -1.0;
+       } else if (c == PLUS) {
+           str[sp++] = c;
+           isSigned = TRUE;
+           sign = 1.0;
+       } else if (c == PERIOD) {
+           if (type(pol_lookchar()) != DIGIT) {
+               str[0] = PERIOD;
+               str[1] = EOS;
+               return (TT_SPECLCHAR);
+           } else
+               pol_ungetch (PERIOD);
+       } else if (type(c) != DIGIT) {
+           pol_ungetch (c);
+           return (TT_ERROR);
+       } else
+           pol_ungetch (c);
+
+       if (isSigned == TRUE) {
+           c = pol_lookchar();
+           if (c == PERIOD) {
+               pol_inchar();           /* get period */
+               c = pol_lookchar();             /* look at character past period */
+               pol_ungetch (PERIOD);   /* put back period */
+               if (type(c) != DIGIT) {
+                   str[sp] = EOS;
+                   return (TT_SPECLCHAR);
+               }
+           } else if (type (c) != DIGIT) {
+               str[sp] = EOS;
+               return (TT_SPECLCHAR);
+           }
+       }
+
+       whole = 0.0;
+       while (type(c = pol_inchar()) == DIGIT) {
+           if (sp < strsize)
+               str[sp++] = c;
+           whole = 10.0 * whole + (c - '0');
+       }
+       pol_ungetch (c);                /* put back non-numeric character */
+
+       if (c != PERIOD && tolower(c) != 'e') {
+           str[sp] = EOS;
+           *fnum = whole * sign;
+           if (*fnum < MIN_INT)
+               *inum = MIN_INT;
+           else if (*fnum > MAX_INT)
+               *inum = MAX_INT;
+           else
+               *inum = (int) *fnum;
+           return (TT_INT);
+       }
+
+       if (pol_lookchar() == PERIOD) {
+           pol_inchar();
+           if (sp < strsize)
+               str[sp++] = PERIOD;
+       }
+
+       frac = 0.0;
+       powerof10 = 10.0;
+
+       while (type(c = pol_inchar()) == DIGIT) {
+           if (sp < strsize)
+               str[sp++] = c;
+           frac += (double) (c - '0') / powerof10;
+           powerof10 *= 10.0;
+       }
+       pol_ungetch (c);
+
+       exp = 0.0;
+       expsign = 1.0;
+       c = pol_inchar();
+       if (tolower(c) != 'e')
+           pol_ungetch (c);
+       else {
+           if (sp < strsize)
+               str[sp++] = c;
+           if ((c = pol_inchar()) == PLUS) {
+               if (sp < strsize)
+                   str[sp++] = c;
+               expsign = 1.0;
+           } else if (c == HYPHEN) {
+               if (sp < strsize)
+                   str[sp++] = c;
+               expsign = -1.0;
+           } else if (type(c) != DIGIT) {
+               --sp;                           /* erase 'e' */
+               pol_ungetch (c);
+               pol_ungetch ('e');
+               goto getnumexit;
+           } else
+               pol_ungetch(c);
+
+           exp = 0;
+           while (type(c = pol_inchar()) == DIGIT) {
+               if (sp < strsize)
+                   str[sp++] = c;
+               exp = 10 * exp + (c - '0');
+           }
+           pol_ungetch (c);
+       }
+
+getnumexit:
+       str[sp] = EOS;
+       *fnum = sign * (whole + frac) * pow (10.0, expsign * exp);
+       if (*fnum < MIN_INT)
+           *inum = MIN_INT;
+       else if (*fnum > MAX_INT)
+           *inum = MAX_INT;
+       else
+           *inum = (int) *fnum;
+       return (TT_REAL);
+}
+
+static void 
+eatline (void)
+{
+       char term [2];
+
+       term[0] = NEWLINE;
+       term[1] = EOS;
+       skiptok (term);
+}
+
+static int 
+type (         /* return type of ASCII character */
+    int c
+)
+{
+       if (isalpha(c) || c == UNDERLIN)
+           return (LETTER);
+       else if (isdigit(c))
+           return (DIGIT);
+       else
+           return (c);
+}
+
+/*----------------------------------------------------------------------*/
+/*                                                                     */
+/*  hash table routines. Kernighan & Ritchie                           */
+/*                                                                     */
+/*----------------------------------------------------------------------*/
+
+/* inittable (table)
+ *     clear symbol table
+*/
+
+static void 
+inittable (SYMBOL *table[])
+{
+       int i;
+
+       for (i = 0; i < HASHSIZE; i++)
+           table[i] = NULL;
+}
+
+/* freetable (table)
+ *     free all memory allocated to table, then clear table
+ */
+
+static void 
+freetable (SYMBOL *table[])
+{
+       int i;
+       SYMBOL *p, *np;
+
+       for (i = 0; i < HASHSIZE; i++) {
+           np = table[i];
+           while (np != NULL) {
+               p = np->next;
+               free (np);
+               np = p;
+           }
+       }
+       inittable (table);
+}
+
+static int 
+hash (         /* form hash value of string s */
+    char *s
+)
+{
+       int hashval;
+
+       for (hashval = 0; *s != EOS; )
+           hashval += *s++;
+       return (hashval % HASHSIZE);
+}
+
+/* Look for s in hash table */
+static SYMBOL *
+lookup ( SYMBOL *table[], char *s )
+{
+    SYMBOL *np;
+    SYMBOL *found = NULL;
+
+    for (np = table[hash(s)]; np != NULL; np = np->next)
+       if (strcasecmp(s, np->name) == 0) {
+           found = np;         /* found it */
+           break;
+       }
+
+    return (found);
+}
+
+static SYMBOL *
+install (SYMBOL *table[], char *name, int def)
+{
+    static char installerr[] = "install: out of memory";
+    SYMBOL *np;
+    int hashval;
+
+    if ((np = lookup (table, name)) == NULL) { /* not found */
+       np = (SYMBOL *) malloc (sizeof(*np));
+       if (np == NULL) {
+           synerr(installerr);
+           return (NULL);
+       }
+       if ((np->name = strdup(name)) == NULL) {
+           synerr(installerr);
+           return (NULL);
+       }
+       str_lower (np->name);
+       np->code = def;
+       hashval = hash(np->name);
+       np->next = table[hashval];
+       table[hashval] = np;
+    } else                                     /* already there */
+       np->code = def;
+    return (np);
+}
+
+/*----------------------------------------------------------------------*/
+/*                             POL OUTPUT                              */
+/*----------------------------------------------------------------------*/
+
+#define MAXFILE 8
+
+static int currentf = -1;              /* pointer to current fp */
+static FILE *filep[MAXFILE];           /* == NULL for string input */
+static char *fname[MAXFILE];           /* pointer to filename */
+static int  linect[MAXFILE];           /* line count in file */
+
+static char inputline[MAXLINE];                /* current input line */
+static int lineptr;                    /* current position in inputline */
+
+static void 
+outch (int c)
+{
+       putchar (c);
+}
+
+
+static void inc_line(void)
+{
+       if (currentf >= 0)
+          ++linect[currentf];
+}
+
+static int getlinect(void)
+{
+       return (linect[currentf]);
+}
+
+static void 
+setlinect (int n)
+{
+       if (currentf >= 0)
+           linect[currentf] = n;
+}
+
+static void 
+synerr (char *msg)
+{
+       fputs (fname[currentf], stderr);
+        fprintf(stderr, "%d", linect[currentf]);
+       fputc (COLON, stderr);
+       fputs (msg, stderr);
+       fputc (NEWLINE, stderr);
+}
+
+/*----------------------------------------------------------------------*/
+/*                             POL INPUT                               */
+/*----------------------------------------------------------------------*/
+
+#define BUFSIZE 100
+static int bp = 0;             /* pointer to next free position */
+static int buf[BUFSIZE];       /* pushed back input characters */
+
+/* pol_usefile - set source of POL input
+ *
+ *    int source - source of input
+ *                P_USE_STR  - have POL use strings as input
+ *                P_USE_FILE - use file.  filename is in str
+ *
+*/
+
+void 
+pol_usefile (int source, char *fn)
+{
+       FILE *fp;
+
+       ++currentf;
+       if (currentf >= MAXFILE) {
+           --currentf;
+           synerr ("files nested too deeply");
+           return;
+       }
+
+       bp = 0;                         /* clear any pushed back input */
+
+       if (source == P_USE_STR) {
+           filep[currentf] = NULL;
+           linect[currentf] = 1;
+       } else if (source == P_USE_FILE) {
+           if (fn == NULL || strlen(fn) == 0) {
+               fp = stdin;
+           } else if ((fp = fopen(fn, "r")) == NULL) {
+               --currentf;
+               synerr ("can't open file");
+               return;
+           }
+           filep[currentf] = fp;
+           linect[currentf] = 1;
+           fname[currentf] = strdup (fn);
+       }
+}
+
+void pol_closefile(void)
+{
+       if (currentf >= 0) {
+           if (filep[currentf] != NULL)
+               fclose (filep[currentf]);
+           --currentf;
+       }
+}
+
+/*-----------------------------*/
+/* Lowest Level Input Routines */
+/*-----------------------------*/
+
+
+int pol_lookchar(void)
+{
+       int c;
+
+       c = pol_inchar();
+       pol_ungetch (c);
+       return (c);
+}
+
+int pol_inchar(void)
+{
+       int c;
+
+       if (currentf < 0)
+           return (EOF);
+
+       while (currentf >= 0 && (c = pol_getch(filep[currentf])) == EOF && filep[currentf] != NULL) {
+          pol_closefile ();
+       }
+
+       return (c);
+}
+
+/*--------------------------------------------------------------*/
+/* getch - get a (possibly pushed back) character              */
+/*        if fp == NULL, then get character from inputline     */
+/*--------------------------------------------------------------*/
+
+static int 
+pol_getch (FILE *fp)
+{
+       int c;
+
+       if (bp > 0)
+           return (buf[--bp]);
+
+       if (fp == NULL) {
+           if ((c = inputline[lineptr]) == EOS)
+               return (EOF);
+           else {
+               ++lineptr;
+               return (c);
+           }
+       } else
+           c = fgetc(fp);
+
+       return (c);
+}
+
+/* push character back on input */
+void 
+pol_ungetch (int c)
+{
+       if (bp > BUFSIZE)
+           sys_error (ERR_SEVERE, "too many characters pushed back [pol_ungetch]");
+       else
+           buf[bp++] = c;
+}
+
+
+/* push back string onto input */
+static void 
+ungets (char *s)
+{
+       int i;
+
+       for (i = strlen(s) - 1; i >= 0; i--)
+           pol_ungetch (s[i]);
+}
+
+int 
+get_inputline (FILE *fp)
+{
+       lineptr = 0;
+       bp = 0;
+       if (fgets (inputline, MAXLINE, fp) == NULL)
+           return (EOF);
+       else
+           return (OK);
+}
+
+void 
+set_inputline (char *line)
+{
+       lineptr = 0;
+       bp = 0;
+       strncpy (inputline, line, MAXLINE);
+}
diff --git a/libctgraphics/ezset.cpp b/libctgraphics/ezset.cpp
new file mode 100644 (file)
index 0000000..b850f56
--- /dev/null
@@ -0,0 +1,666 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: ezset.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+/*----------------------------------------------------------------------*/
+/*                     EZSET - Parameter control for EZPLOT            */
+/*                                                                     */
+/*----------------------------------------------------------------------*/
+
+#include "ezplot.h"
+#include "pol.h"
+#include "cio.h"
+
+static int ezcmd (char *comm);
+static int do_cmd(int lx);
+static void do_data(void);
+static void do_help(void);
+static void bad_option(char *opt);
+static void initkw(void);
+
+static int modeinteract = FALSE;
+static int curveinteract = -1;
+static int ezset_firstcall = TRUE;
+static int eztrace = TRUE;
+
+int 
+ezset (char *command)
+{
+    if (ezplot_firstcall == TRUE) {
+       ezinit ();
+    }
+    if (ezset_firstcall == TRUE) {
+       pol_init();
+       initkw();
+       pol_skpword ("please");
+       pol_skpword ("use");
+       pol_skpword ("are");
+       pol_skpword ("and");
+       pol_skpword ("is");
+       pol_skpword ("the");
+       pol_skpword ("equals");
+       pol_skpchar ("=");
+       ezset_firstcall = FALSE;
+
+       pol_usefile (P_USE_STR,"");
+       set_inputline ("!eoc ,");
+       pol_reader ();
+       pol_closefile ();
+    }
+    return (ezcmd (command));
+}
+
+static int 
+ezcmd (char *comm)
+{
+       char str[MAXTOK+1];
+       int code, retval;
+
+       retval = TRUE;
+       pol_usefile (P_USE_STR, "");
+       set_inputline (comm);
+
+       if (pol_usertok (str, &code) == FALSE) {
+           fputs("Illegal EZSET command\n", stderr);
+           pol_reader();
+           retval = FALSE;
+           goto ezexit;
+       }
+
+       if (code != S_INTERACTIVE) {
+           retval = do_cmd (code);
+       } else {
+           modeinteract = TRUE;
+           pol_reader();
+           do {
+               fputs ("Enter EZSET command, DATA, EXIT, or HELP\n>", stderr);
+               if (get_inputline (stdin) != TRUE)
+                   goto ezexit;
+               while (pol_lookchar() != EOF) {
+                   if (pol_usertok (str, &code) == FALSE) {
+                       if (pol_lookchar() != EOF) {
+                           fputs ("illegal EZSET command\n", stderr);
+                           pol_reader();
+                       }
+                   } else if (code == S_DATA) {
+                       pol_reader ();
+                       do_data ();
+                   } else if (code == S_HELP) {
+                       pol_reader();
+                       do_help ();
+                   } else if (code == S_EXIT) {
+                       pol_reader();
+                       goto ezexit;
+                   } else
+                       do_cmd (code);
+               }
+               putc (NEWLINE, stderr);
+           } while (TRUE);
+           modeinteract = FALSE;
+           curveinteract = -1;
+       }
+ezexit:
+       pol_closefile();                        /* close input string file */
+       return (retval);
+}
+
+
+static int 
+do_cmd (int lx)
+{
+       char str [MAXTOK+1];
+       int n;
+       double f;
+
+       switch (lx) {
+           case S_CRT:
+               if (pol_word("no", 2) == TRUE)
+                   ez.d_usecrt = FALSE;
+               else {
+                   ez.d_usecrt = TRUE;
+               }
+               break;
+           case S_EPSON:
+               if (pol_word("no", 2) == TRUE)
+                   ez.d_useprt = FALSE;
+               else
+                   ez.d_useprt = TRUE;
+               break;
+           case S_TEXTSIZE:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE)
+                 {
+                   if (f >= 0.0 && f <= 1.0) {
+                       ez.v_textsize = f;
+                       ez.s_textsize = TRUE;
+                   } else
+                       ez.s_textsize = FALSE;
+                 }
+               break;
+           case S_PRTMODE:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE)
+                 {
+                   if (n >= 0 && n <= 6)
+                       ez.d_prtmode = n;
+                   else
+                       ez.d_prtmode = PRTMODE_DEF;
+                 }
+               break;
+           case S_XBUF:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE)
+                 {
+                   if (n > 2 && n <= 960)
+                       ez.d_xprtbuf = n;
+                   else
+                       ez.d_xprtbuf = XBUF_DEF;
+                 }
+               break;
+           case S_YBUF:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE)
+                 {
+                   if (n > 2 && n <= 960)
+                       ez.d_yprtbuf = n;
+                   else
+                       ez.d_yprtbuf = YBUF_DEF;
+                 }
+               break;
+           case S_REPLOT:
+               ez.i_plotimmediate = TRUE;
+               ezplot (NULL, NULL, 0);
+#if 0
+               if (modeinteract == TRUE)
+                   WAITKEY();
+#endif
+               ez.i_plotimmediate = FALSE;
+               break;
+           case S_CLEAR:
+               ezclear ();
+               break;
+           case S_TITLE:
+               gettext (ez.c_title, MAXTITLE);
+               break;
+           case S_LEGEND:
+               gettext (ez.c_legend, MAXLEGEND);
+               if (modeinteract == TRUE && curveinteract >= 0)
+                   strncpy (ez.curve[curveinteract].legend, ez.c_legend, MAXLEGEND);
+               break;
+           case S_XLABEL:
+               gettext (ez.c_xlabel, MAXLABEL);
+               break;
+           case S_YLABEL:
+               gettext (ez.c_ylabel, MAXLABEL);
+               break;
+           case S_XCROSS:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) {
+                   ez.v_xcross = f;
+                   ez.s_xcross = TRUE;
+               } else
+                   ez.s_xcross = FALSE;
+               break;
+           case S_YCROSS:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) {
+                   ez.v_ycross = f;
+                   ez.s_ycross = TRUE;
+               } else
+                   ez.s_ycross = FALSE;
+               break;
+           case S_NOXAXIS:
+               ez.o_xaxis = NOAXIS;
+               break;
+           case S_NOYAXIS:
+               ez.o_yaxis = NOAXIS;
+               break;
+           case S_XLIN:
+               ez.o_xaxis = LINEAR;
+               break;
+           case S_YLIN:
+               ez.o_yaxis = LINEAR;
+               break;
+           case S_XLOG:
+               ez.o_xaxis = LOG;
+               break;
+           case S_YLOG:
+               ez.o_yaxis = LOG;
+               break;
+           case S_XAUTOSCALE:
+               ez.s_xmin = FALSE;
+               ez.s_xmax = FALSE;
+               break;
+           case S_YAUTOSCALE:
+               ez.s_ymin = FALSE;
+               ez.s_ymax = FALSE;
+               break;
+           case S_XMIN:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) {
+                   ez.v_xmin = f;
+                   ez.s_xmin = TRUE;
+               }
+               break;
+           case S_XMAX:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) {
+                   ez.v_xmax = f;
+                   ez.s_xmax = TRUE;
+               }
+               break;
+           case S_YMIN:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) {
+                   ez.v_ymin = f;
+                   ez.s_ymin = TRUE;
+               }
+               break;
+           case S_YMAX:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE) {
+                   ez.v_ymax = f;
+                   ez.s_ymax = TRUE;
+               }
+               break;
+           case S_SOLID:
+               ez.o_linestyle = LS_SOLID;
+               if (modeinteract == TRUE && curveinteract >= 0)
+                   ez.curve[curveinteract].linestyle = LS_SOLID;
+               break;
+           case S_DASH:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) {
+                   if (n == 1)
+                       ez.o_linestyle = LS_DASH1;
+                   else if (n == 2)
+                       ez.o_linestyle = LS_DASH2;
+                   else if (n == 3)
+                       ez.o_linestyle = LS_DASH3;
+                   else if (n == 4)
+                       ez.o_linestyle = LS_DASH4;
+                   else
+                       ez.o_linestyle = LS_DASH1;
+               } else
+                   ez.o_linestyle = LS_DASH1;
+               if (modeinteract == TRUE && curveinteract >= 0)
+                   ez.curve[curveinteract].linestyle = ez.o_linestyle;
+               break;
+           case S_NOLINE:
+               ez.o_linestyle = LS_NOLINE;
+               if (modeinteract == TRUE && curveinteract >= 0)
+                   ez.curve[curveinteract].linestyle = LS_NOLINE;
+               break;
+           case S_PEN:
+           case S_COLOR:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE)
+                 {
+                   if (n >= 0 && n <= MAXCOLOR)
+                       ez.o_color = n;
+                   else
+                       bad_option("The color you picked");
+                 }
+               if (modeinteract == TRUE && curveinteract >= 0)
+                   ez.curve[curveinteract].color = ez.o_color;
+               break;
+           case S_BOX:
+               ez.o_box = TRUE;
+               break;
+           case S_NOBOX:
+               ez.o_box = FALSE;
+               break;
+           case S_GRID:
+               ez.o_grid = TRUE;
+               break;
+           case S_NOGRID:
+               ez.o_grid = FALSE;
+               break;
+           case S_XLENGTH:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE)
+                   if (f > 0.0 && f <= 1.0)
+                       ez.o_xlength = f;
+               break;
+           case S_YLENGTH:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE)
+                   if (f > 0.0 && f <= 1.0)
+                       ez.o_ylength = f;
+               break;
+           case S_XPORIGIN:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE)
+                   if (f >= 0.0 && f < 1.0)
+                       ez.o_xporigin = f;
+               break;
+           case S_YPORIGIN:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE)
+                   if (f >= 0.0 && f < 1.0)
+                       ez.o_yporigin = f;
+               break;
+           case S_TAG:
+               if (pol_word("no", 2) == TRUE)
+                   ez.o_tag = FALSE;
+               else if (pol_word("off", 2) == TRUE)
+                   ez.o_tag = FALSE;
+               else
+                   ez.o_tag = TRUE;
+               break;
+           case S_LEGENDBOX:
+               if (pol_word("inside", 2) == TRUE)
+                   ez.o_legendbox = INSIDE;
+               else if (pol_word("outside", 3) == TRUE)
+                   ez.o_legendbox = OUTSIDE;
+               else if (pol_word("none",2) == TRUE)
+                   ez.o_legendbox = NOLEGEND;
+               else {
+                   gettext (str, MAXTOK);
+                   bad_option(str);
+               }
+               break;
+           case S_XLEGEND:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE)
+                 {
+                   if (f >= 0.0 && f < 1.0) {
+                       ez.v_xlegend = f;
+                       ez.s_xlegend = TRUE;
+                   }
+                   else
+                     ez.s_xlegend = FALSE;
+                 }
+               break;
+           case S_YLEGEND:
+               if (pol_float (&f, TT_REAL, FALSE, 0.0, 0.0) == TRUE)
+                 {
+                   if (f >= 0.0 && f < 1.0) {
+                       ez.v_ylegend = f;
+                       ez.s_ylegend = TRUE;
+                   }
+                   else
+                     ez.s_ylegend = FALSE;
+                 }
+               break;
+           case S_CURVES:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) {
+                   if (n < 1)
+                       n = 1;
+                   else if (n > MAXCURVES)
+                       n = MAXCURVES;
+                   if (modeinteract == TRUE) {
+                       curveinteract = n - 1;
+                       if (ez.o_unknowncurves == FALSE && ez.o_reqcurves < n)
+                            ez.o_reqcurves = n;
+                   } else {
+                       ezfree ();
+                       ez.o_reqcurves = n;
+                   }
+               } else {
+                   if (pol_word ("unknown", 7) == TRUE)
+                       ez.o_unknowncurves = TRUE;
+                   else if (pol_word ("end", 3) == TRUE) {
+                       ez.o_unknowncurves = FALSE;
+                       ez.o_reqcurves = ez.i_numcurves;
+                       ez.i_plotimmediate = TRUE;
+                       ezplot (NULL, NULL, 0);
+                       ez.i_plotimmediate = FALSE;
+                   }
+               }
+               break;
+           case S_SYMBOL:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) {
+                   if (n > 0 && n <= MAXSYMBOL)
+                       ez.o_symbol = n;
+                   else
+                       ez.o_symbol = 1;
+                   if (modeinteract == TRUE && curveinteract >= 0)
+                       ez.curve[curveinteract].symbol = ez.o_symbol;
+               } else {
+                   if (pol_word("every",5) == TRUE) {
+                       if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) {
+                           if (n > 0)
+                               ez.o_symfreq = n;
+                           else
+                               ez.o_symfreq = 1;
+                           if (modeinteract == TRUE && curveinteract >= 0)
+                               ez.curve[curveinteract].symfreq = ez.o_symfreq;
+                       }
+                   } else if (pol_word ("none",4) == TRUE) {
+                       ez.o_symbol = -1;
+                       if (modeinteract == TRUE && curveinteract >= 0)
+                           ez.curve[curveinteract].symbol = ez.o_symbol;
+                   }
+               }
+               break;
+           case S_XTICKS:
+               if (pol_usertok(str,&lx) == FALSE)
+                   break;
+               if (lx == S_ABOVE)
+                   ez.o_xticks = ABOVE;
+               else if (lx == S_BELOW)
+                   ez.o_xticks = BELOW;
+               else if (lx == S_NOLABEL)
+                   ez.o_xtlabel = FALSE;
+               else if (lx == S_LABEL)
+                   ez.o_xtlabel = TRUE;
+               else if (lx == S_MAJOR) {
+                    if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE)
+                       if (n > 1 && n < 100)
+                           ez.o_xmajortick = n;
+               } else if (lx == S_MINOR)
+                    if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE)
+                       if (n >= 0 && n < 100)
+                           ez.o_xminortick = n;
+               break;
+           case S_YTICKS:
+               if (pol_usertok(str,&lx) == FALSE)
+                   break;
+               if (lx == S_RIGHT)
+                   ez.o_yticks = RIGHT;
+               else if (lx == S_LEFT)
+                   ez.o_yticks = LEFT;
+               else if (lx == S_NOLABEL)
+                   ez.o_ytlabel = FALSE;
+               else if (lx == S_LABEL)
+                   ez.o_ytlabel = TRUE;
+               else if (lx == S_MAJOR) {
+                    if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE)
+                       if (n > 1 && n < 100)
+                           ez.o_ymajortick = n;
+               } else if (lx == S_MINOR)
+            if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE)
+                       if (n >= 0 && n < 100)
+                           ez.o_yminortick = n;
+               break;
+           case S_LXFRAC:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) {
+                   if (n >= 0) {
+                       ez.v_lxfrac = n;
+                       ez.s_lxfrac = TRUE;
+                   }
+               } else
+                   ez.s_lxfrac = FALSE;
+               break;
+           case S_LYFRAC:
+               if (pol_integer (&n, TT_REAL, FALSE, 0, 0) == TRUE) {
+                   if (n >= 0) {
+                       ez.v_lyfrac = n;
+                       ez.s_lyfrac = TRUE;
+                   }
+               } else
+                   ez.s_lyfrac = FALSE;
+               break;
+           case S_USTART:
+               if (pol_word("no", 2) == TRUE)
+                   ez.o_ustart = FALSE;
+               else
+                   ez.o_ustart = TRUE;
+               break;
+           case S_UFINISH:
+               if (pol_word("no", 2) == TRUE)
+                   ez.o_ufinish = FALSE;
+               else
+                   ez.o_ufinish = TRUE;
+               break;
+           default:
+               fprintf (stderr, "Unimplemented EZPLOT command\n");
+               break;
+       }
+
+       pol_reader ();
+       return (TRUE);
+}
+
+static void do_data (void)
+{
+       double x[MAXPTS], y[MAXPTS], d;
+       int c, i;
+
+       printf ("Enter your data in free format\n");
+       printf ("Alternate X and Y coordinates\n");
+       printf ("Type ^Z (control Z) to terminate data entry\n");
+
+       pol_usefile (P_USE_FILE, "");
+       for (i = 0; i < MAXPTS; i++) {
+           if (pol_float (&d, TT_REAL, FALSE, 0, 0) == TRUE)
+               x[i] = d;
+           else
+               break;
+           if (pol_float (&d, TT_REAL, FALSE, 0, 0) == TRUE)
+               y[i] = d;
+           else
+               break;
+       }
+
+       if ((c = pol_inchar()) != EOF) {
+           ungetc (c, stdin);
+           printf("Error reading in points, read char %d, plotting %d points\n", c, i);
+       }
+       if (i > 0)
+           ezplot (x, y, i);
+       pol_closefile ();
+}
+
+
+static void do_help (void )
+{
+       fputs ("EZSET Help: not available\n", stderr);
+}
+
+
+static void 
+bad_option (char *opt)
+{
+       fprintf(stderr,"%s is an INVALID option (sorry!)\n", opt);
+}
+
+/*----------------------------------------------------------------------*/
+/*                     LEXIGRAPHICAL CODES                             */
+/*----------------------------------------------------------------------*/
+
+static struct key {
+       char *keyword;
+       int code;
+} keytab[] = {
+       "solid",        S_SOLID,
+       "dash",         S_DASH,
+       "noline",       S_NOLINE,
+       "black",        S_BLACK,
+       "red",          S_RED,
+       "blue",         S_BLUE,
+       "green",        S_GREEN,
+       "pen",          S_PEN,
+       "symbol",       S_SYMBOL,
+/*     "every",        S_EVERY,        */
+/*     "none",         S_NONE,         */
+
+       "curves",       S_CURVES,
+       "curve",        S_CURVES,
+/*     "unknown",      S_UNKNOWN,      */
+/*     "end",          S_END,          */
+
+       "legend",       S_LEGEND,
+       "xlegend",      S_XLEGEND,
+       "ylegend",      S_YLEGEND,
+
+       "xlin",         S_XLIN,
+       "ylin",         S_YLIN,
+       "xlog",         S_XLOG,
+       "ylog",         S_YLOG,
+       "xlabel",       S_XLABEL,
+       "ylabel",       S_YLABEL,
+       "xlength",      S_XLENGTH,
+       "ylength",      S_YLENGTH,
+
+       "xticks",       S_XTICKS,
+       "yticks",       S_YTICKS,
+       "above",        S_ABOVE,
+       "label",        S_LABEL,
+       "below",        S_BELOW,
+       "nolabel",      S_NOLABEL,
+       "right",        S_RIGHT,
+       "left",         S_LEFT,
+
+       "xautoscale",   S_XAUTOSCALE,
+       "yautoscale",   S_YAUTOSCALE,
+       "xmin",         S_XMIN,
+       "ymin",         S_YMIN,
+       "xmax",         S_XMAX,
+       "ymax",         S_YMAX,
+       "lxfrac",       S_LXFRAC,
+       "lyfrac",       S_LYFRAC,
+       "xcross",       S_XCROSS,
+       "ycross",       S_YCROSS,
+       "noxaxis",      S_NOXAXIS,
+       "noyaxis",      S_NOYAXIS,
+       "xporigin",     S_XPORIGIN,
+       "yporigin",     S_YPORIGIN,
+       "title",        S_TITLE,
+       "xtitle",       S_XTITLE,
+       "ytitle",       S_YTITLE,
+
+       "replot",       S_REPLOT,
+       "clear",        S_CLEAR,
+       "store",        S_STORE,
+       "restore",      S_RESTORE,
+       "ustart",       S_USTART,
+       "ufinish",      S_UFINISH,
+       "amark",        S_AMARK,
+       "interactive",  S_INTERACTIVE,
+       "units",        S_UNITS,
+       "inches",       S_INCHES,
+       "user",         S_USER,
+
+       "data",         S_DATA,
+       "help",         S_HELP,
+       "exit",         S_EXIT,
+
+       "box",          S_BOX,
+       "nobox",        S_NOBOX,
+       "grid",         S_GRID,
+       "nogrid",       S_NOGRID,
+       "major",        S_MAJOR,
+       "minor",        S_MINOR,
+       "color",        S_COLOR,
+       "legendbox",    S_LEGENDBOX,
+
+       "epson",        S_EPSON,
+       "crt",          S_CRT,
+       "no",           S_NO,
+
+       "textsize",     S_TEXTSIZE,
+       "xbuf",         S_XBUF,
+       "ybuf",         S_YBUF,
+       "prtmode",      S_PRTMODE,
+};
+
+#define NKEYS  (sizeof(keytab) / sizeof(struct key))
+
+static void initkw(void)
+{
+       int i;
+
+       for (i = 0; i < NKEYS; i++)
+           if (pol_install(keytab[i].keyword, keytab[i].code) == FALSE)
+               sys_error(ERR_SEVERE, "error installing ezset keywords [initkw]");
+}
diff --git a/libctgraphics/ezsupport.cpp b/libctgraphics/ezsupport.cpp
new file mode 100644 (file)
index 0000000..51f9742
--- /dev/null
@@ -0,0 +1,216 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: ezsupport.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+
+#include <math.h>
+#include <algorithm>
+#include "kstddef.h"
+#include "ezplot.h"
+
+
+/* NAME
+ *    axis_scale                       calculates graph axis scaling
+ *
+ *  SYNOPSIS:
+ *    retval = axis_scale (min, max, nint, minp, maxp, nintp, 
+ *                        rec_total, rec_frac)
+ *
+ *    INPUT:
+ *     double min         Smallest value to plot
+ *     double max         Largest value to plot
+ *     int    nint        Number of intervals desired
+ *
+ *    OUTPUT:
+ *     int   retval       FALSE if illegal parameters, else TRUE
+ *     double *minp       Minimum graph value
+ *     double *maxp       Maximum graph value
+ *     int    *nintp      Number of intervals for graph
+ *      int    *rec_total  Recommended field width for printing out the number
+ *     int    *rec_frac   Recommended number of digits for print fraction
+ */
+
+int 
+axis_scale (double min, double max, int nint, double *minp, double *maxp, int *nintp)
+{
+    double eps, a, scale, mina, maxa, d, j, e, f, v, wdt, g, h;
+
+    if (min >= max || nint < 1) {
+       sys_error (ERR_WARNING, "Invalid params: min=%lf, min=%lf, num intervals=%d [axis_scale]", min, max, nint);
+           return (FALSE);
+       }
+
+    eps = 0.025;
+    a = fabs(min);
+    if (fabs(min) < fabs(max))
+       a = fabs(max);
+    scale = pow (10.0, floor(log10(a)));
+ loop:
+    mina = min / scale;
+    maxa = max / scale;
+    d = (maxa - mina) / nint;
+    j = d * eps;
+    e = floor (log10(d));
+    f = d / pow (10.0, e);
+    v = 10.0;
+    if (f < sqrt(2.0))
+       v = 1.0;
+    else if (f < sqrt (10.0))
+       v = 2.0;
+    else if (f < sqrt (50.0))
+       v = 5.0;
+    wdt = v * pow (10.0, e);
+    g = floor (mina / wdt);
+    if (fabs(g + 1 - mina / wdt) < j)
+       g = g + 1;
+    *minp = wdt * g;
+    h = floor (maxa / wdt) + 1.0;
+    if (fabs(maxa / wdt + 1 - h) < j)
+       h = h - 1;
+    *maxp = wdt * h;
+    *nintp = static_cast<int>(h - g);
+    if (fabs(*maxp) >= 10.0 || fabs(*minp) >= 10.0) {
+       scale = scale * 10.0;
+       goto loop;
+    }
+    
+    *minp *= scale;
+    *maxp *= scale;
+    
+    return (TRUE);
+}
+
+
+/* NAME
+ *   make_numfmt               Make a numeric format string
+ *
+ * SYNOPSIS
+ *   make_numfmt (fmtstr, fldwid, nfrac, min, max, nint)
+ *   char *fmtstr              Returned format string for printf()
+ *   int  *fldwid              Returned field width
+ *   int  *nfrac               If < 0, then calculate best number of
+ *                             fraction places & return that value
+ *                             If >= 0, then use that number of places
+ *   double min                        Minimum value
+ *   double max                        Maximum value
+ *   int nint                  Number of intervals between min & max
+ *
+ * DESCRIPTION
+ *   This  routine is written as an INTERNAL routine for EZPLOT
+ */
+
+static inline double 
+trunc (double x)
+{
+  double integer;
+  
+  double frac = modf (x, &integer);
+  
+  return (integer);
+}
+
+void 
+make_numfmt (char *fmtstr, int *fldwid, int *nfrac, double minval, double maxval, int nint)
+{
+  int wid, frac, expon;
+
+  double delta = (maxval - minval) / nint;
+  double absmin = fabs(minval);
+  double absmax = fabs(maxval);
+  double logt = log10( max(absmin, absmax) );
+
+  if (fabs(logt) >= 6) {               /* use exponential format */
+    if (fabs(logt) > 99)
+      expon = 5;               /*  E+102 */
+    else
+      expon = 4;               /*  E+00 */
+    
+    if (*nfrac < 0) {          /* calculate frac */
+      delta /= pow (10., floor(logt)); /* scale delta */
+      frac = static_cast<int>(fabs(trunc(log10(delta)))) + 1;
+      if (frac < 1)
+       frac = 1;               /* to be safe, add decimal pt */
+    } else                     /* use users' frac */
+      frac = *nfrac;
+    
+    wid = 2 + frac + expon;
+    if (minval < 0. || maxval < 0.)
+      ++wid;
+    snprintf (fmtstr, sizeof(fmtstr), "%%%d.%dle", wid, frac);
+  } else {                     /* use fixed format */
+    wid = static_cast<int>(trunc(logt)) + 1;
+    if (wid < 1)
+      wid = 1;
+    if (minval < 0. || maxval < 0.)
+      ++wid;
+    
+    if (*nfrac < 0) {          /* calculate frac */
+      if (delta >= 0.999999)
+       frac = 1;               /* add a decimal pt to be safe */
+      else
+       frac = static_cast<int>(fabs(trunc(log10(delta)))) + 1;
+    } else                     /* use users' frac */
+      frac = *nfrac;
+    
+    wid += 1 + frac;
+    snprintf (fmtstr, sizeof(fmtstr), "%%%d.%dlf", wid, frac);
+  }
+  
+  *fldwid = wid;
+  *nfrac = frac;
+}
+
+#ifdef TEST
+int 
+main (void)
+{
+  double min, max;
+  double x, xinc;
+  int i, nint, wid, frac;
+  char fmtstr[10];
+  
+  printf ("Enter min, max, & number of intervals -- ");
+  scanf ("%lf %lf %d", &min, &max, &nint);
+  
+  frac = -1;   /* let makefmt determine fraction */
+  
+  makefmt (fmtstr, &wid, &frac, min, max, nint);
+  
+  printf ("Format string = %s\n", fmtstr);
+
+  xinc = (max - min) / nint;
+  
+  x = min;
+  for (i = 0; i <= nint; i++) {
+    printf (fmtstr, x);
+    x += xinc;
+    printf ("\n");
+  }
+}
+#endif
+
+void 
+ezplot_1d (double *y, int n)
+{
+  double x [n];
+
+  for (int i = 0; i < n; i++)
+    x[i] = i;
+
+  ezplot (x, y, n);
+}
diff --git a/libctgraphics/sgp.cpp b/libctgraphics/sgp.cpp
new file mode 100644 (file)
index 0000000..e3241a8
--- /dev/null
@@ -0,0 +1,558 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: sgp.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**  $Log: sgp.cpp,v $
+**  Revision 1.1  2000/06/19 18:05:03  kevin
+**  initial cvs import
+**
+**  Revision 1.1  2000/06/13 16:20:31  kevin
+**  finished c++ conversions
+**
+**  Revision 1.4  2000/05/24 22:49:01  kevin
+**  Updated SGP: first function X-windows version
+**
+**  Revision 1.3  2000/05/11 14:07:23  kevin
+**  Fixed compilation warnings
+**
+**  Revision 1.2  2000/05/08 20:08:15  kevin
+**  *** empty log message ***
+**
+**  Revision 1.1.1.1  2000/04/28 13:02:44  kevin
+**  Initial CVS import for first public release
+**
+**
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+
+/*-----------------------------------------------------------------------------
+ * FILE IDENTIFICATION
+ *
+ *     Name:       sgp.c               Simple Graphics Package
+ *     Programmer: Kevin Rosenberg
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "stdio.h"
+#include "kstddef.h"
+#include "math.h"
+#include "kmath.h"
+#include "sgp.h"
+static SGP_ID _sgp2_cwin = NULL;
+
+extern CHARSPEC cspec;
+
+
+/* NAME
+ *   sgp2_init                         Initialize 2 graphics system
+ *
+ * SYNOPSIS
+ *   sgp2_init()
+ */
+
+SGP_ID
+sgp2_init (int xsize, int ysize, const char *win_title )
+{
+    SGP_ID gid;
+
+    gid = new SGP_WINDOW;
+    _sgp2_cwin = gid;
+    if (xsize <= 0)
+       xsize = 640;
+    if (ysize <= 0)
+       ysize = 480;
+
+    gid->pw_xsize = xsize;
+    gid->pw_ysize = ysize;
+    strncpy(gid->title, win_title, sizeof(gid->title));
+
+    gid->recalc_mc_to_ndc = TRUE;
+    gid->recalc_ndc_to_mc = TRUE;
+    ident_gmtx_2 (gid->wc_to_ndc_x);
+    ident_gmtx_2 (gid->mc_to_ndc_x);
+    ident_gmtx_2 (gid->ndc_to_mc_x);
+    ident_gmtx_2 (gid->ctm_2_x);
+
+    sgp2_window (0., 0., 1., 1.);
+    sgp2_viewport (0., 0., 1., 1.);
+    ctm_clr_2 ();
+    sgp2_move_abs (0., 0.);
+
+#if HAVE_G2_H
+    gid->g2_id = g2_open_X11X (gid->pw_xsize, gid->pw_ysize, 10, 10, gid->title, gid->title, NULL, -1, -1);
+#endif
+
+    _sgp2_init_dev (_sgp2_cwin);
+    
+    return (gid);
+}
+
+
+void
+sgp2_close (SGP_ID gid)
+{
+#if HAVE_G2_H    
+    g2_close (gid->g2_id);
+#endif
+    if (gid == _sgp2_cwin)
+       _sgp2_cwin = NULL;
+
+    delete gid;
+}
+
+void
+sgp2_set_active_win (SGP_ID gid)
+{
+    _sgp2_cwin = gid;
+}
+
+SGP_ID
+sgp2_get_active_win (void)
+{
+    return (_sgp2_cwin);
+}
+
+
+/* NAME
+ *     sgp2_clear          Clear window
+ */
+
+void 
+sgp2_clear ()
+{
+#if HAVE_G2
+    if (_sgp_cwin != NULL)
+       g2_clear (gid->g2_id);
+#endif
+}
+
+/* NAME
+ *     sgp2_window             Set window in world coordinates
+ */
+
+void
+sgp2_window (double xmin, double ymin, double xmax, double ymax)
+{
+    if (_sgp2_cwin == NULL)
+       return;
+
+    if (xmin >= xmax || ymin >= ymax) {
+       sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_window]");
+       return;
+    }
+
+    _sgp2_cwin->xw_min = xmin;
+    _sgp2_cwin->yw_min = ymin;
+    _sgp2_cwin->xw_max = xmax;
+    _sgp2_cwin->yw_max = ymax;
+    calc_wc_to_ndc();
+}
+
+
+/* NAME
+ *     sgp2_viewport                   Set viewport in NDC
+ */
+
+void
+sgp2_viewport (double xmin, double ymin, double xmax, double ymax)
+{
+    if (_sgp2_cwin == NULL)
+       return;
+
+    if (xmin >= xmax || ymin >= ymax) {
+       sys_error (ERR_WARNING, "Minimum > Maximum [sgp2_viewport]");
+       return;
+    }
+    
+    _sgp2_cwin->xv_min = xmin;
+    _sgp2_cwin->yv_min = ymin;
+    _sgp2_cwin->xv_max = xmax;
+    _sgp2_cwin->yv_max = ymax;
+    calc_wc_to_ndc();
+    
+    _sgp2_cwin->view[0] = xmin;                        /* Array for clip_rect() */
+    _sgp2_cwin->view[1] = ymin;
+    _sgp2_cwin->view[2] = xmax;
+    _sgp2_cwin->view[3] = ymax;
+}
+
+
+/* NAME
+ *     sgp2_frame_vpt          draw box around viewport
+ */
+
+void
+sgp2_frame_vpt (void)
+{
+    if (_sgp2_cwin == NULL)
+       return;
+
+    _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_min, 0);
+    _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_max, _sgp2_cwin->yv_min, 1);
+    _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_max, _sgp2_cwin->yv_max, 1);
+    _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_max, 1);
+    _sgp2_stylus (_sgp2_cwin, _sgp2_cwin->xv_min, _sgp2_cwin->yv_min, 1);
+}
+
+
+/* NAME
+ *     calc_wc_to_ndc                  Calculate transform matrix
+ */
+
+void
+calc_wc_to_ndc (void)
+{
+    double sx, sy;
+    
+    if (_sgp2_cwin == NULL)
+       return;
+
+    sx = (_sgp2_cwin->xv_max - _sgp2_cwin->xv_min) / (_sgp2_cwin->xw_max - _sgp2_cwin->xw_min);
+    sy = (_sgp2_cwin->yv_max - _sgp2_cwin->yv_min) / (_sgp2_cwin->yw_max - _sgp2_cwin->yw_min);
+    
+    ident_gmtx_2 (_sgp2_cwin->wc_to_ndc_x);
+    _sgp2_cwin->wc_to_ndc_x[0][0] = sx;
+    _sgp2_cwin->wc_to_ndc_x[2][0] = _sgp2_cwin->xv_min - sx * _sgp2_cwin->xw_min;
+    _sgp2_cwin->wc_to_ndc_x[1][1] = sy;
+    _sgp2_cwin->wc_to_ndc_x[2][1] = _sgp2_cwin->yv_min - sy * _sgp2_cwin->yw_min;
+    
+    _sgp2_cwin->recalc_mc_to_ndc = TRUE;
+    _sgp2_cwin->recalc_ndc_to_mc = TRUE;
+}
+
+
+void 
+calc_ndc_to_mc (void)
+{
+    if (_sgp2_cwin == NULL)
+       return;
+
+    if (_sgp2_cwin->recalc_mc_to_ndc) {
+       mult_gmtx_2 (_sgp2_cwin->ctm_2_x, _sgp2_cwin->wc_to_ndc_x, _sgp2_cwin->mc_to_ndc_x);
+       _sgp2_cwin->recalc_mc_to_ndc = FALSE;
+    }
+    
+    invert_gmtx_2 (_sgp2_cwin->mc_to_ndc_x, _sgp2_cwin->ndc_to_mc_x);
+    _sgp2_cwin->recalc_ndc_to_mc = FALSE;
+}
+
+
+/* NAME
+ *     wc_to_ndc                       Map from world coordinates to NDC
+ */
+
+void 
+wc_to_ndc (double xw, double yw, double *xn, double *yn)
+{
+    if (_sgp2_cwin == NULL)
+       return;
+
+    if (_sgp2_cwin->recalc_mc_to_ndc) {
+       mult_gmtx_2 (_sgp2_cwin->ctm_2_x, _sgp2_cwin->wc_to_ndc_x, _sgp2_cwin->mc_to_ndc_x);
+       _sgp2_cwin->recalc_mc_to_ndc = FALSE;
+    }
+
+    *xn = xw * _sgp2_cwin->mc_to_ndc_x[0][0] + yw * _sgp2_cwin->mc_to_ndc_x[1][0] + _sgp2_cwin->mc_to_ndc_x[2][0];
+    *yn = xw * _sgp2_cwin->mc_to_ndc_x[0][1] + yw * _sgp2_cwin->mc_to_ndc_x[1][1] + _sgp2_cwin->mc_to_ndc_x[2][1];
+}
+
+
+/*==============================================================*/
+/* map from normalized device coords. to world coordinates     */
+/*==============================================================*/
+void
+ndc_to_wc (double xn, double yn, double *xw, double *yw)
+{
+    if (_sgp2_cwin == NULL)
+       return;
+
+    if (_sgp2_cwin->recalc_ndc_to_mc) {
+       calc_ndc_to_mc();
+       _sgp2_cwin->recalc_ndc_to_mc = FALSE;
+    }
+
+    *xw = xn * _sgp2_cwin->ndc_to_mc_x[0][0] + yn * _sgp2_cwin->ndc_to_mc_x[1][0] + _sgp2_cwin->ndc_to_mc_x[2][0];
+    *yw = xn * _sgp2_cwin->ndc_to_mc_x[0][1] + yn * _sgp2_cwin->ndc_to_mc_x[1][1] + _sgp2_cwin->ndc_to_mc_x[2][1];
+}
+
+
+/*==============================================================*/
+/* set the color                                               */
+/*==============================================================*/
+void 
+sgp2_color (int icol)
+{
+    setcolor(icol);
+}
+
+/*==============================================================*/
+/* set line style.  Pass 16 bit repeating pattern              */
+/*==============================================================*/
+void 
+sgp2_line_style (int style)
+{
+    setlinestyle(style);
+}
+
+/*==============================================================*/
+/* absolute draw to                                            */
+/*==============================================================*/
+void 
+sgp2_line_abs (double x, double y)
+{
+    double x1, y1, x2, y2;
+
+    if (_sgp2_cwin == NULL)
+       return;
+
+    wc_to_ndc (_sgp2_cwin->curx, _sgp2_cwin->cury, &x1, &y1);
+    wc_to_ndc (x, y, &x2, &y2);
+
+    if (clip_rect (x1, y1, x2, y2, _sgp2_cwin->view) == TRUE) { /* clip to viewport */
+       _sgp2_stylus (_sgp2_cwin, x1, y1, 0);           /* move to first point */
+       _sgp2_stylus (_sgp2_cwin, x2, y2, 1);           /* draw to second point */
+    }
+
+    _sgp2_cwin->curx = x;
+    _sgp2_cwin->cury = y;
+}
+
+/*==============================================================*/
+/* absolute move to                                            */
+/*==============================================================*/
+void 
+sgp2_move_abs (double x, double y)
+{
+    if (_sgp2_cwin == NULL)
+       return;
+
+    _sgp2_cwin->curx = x;
+    _sgp2_cwin->cury = y;                      /* moves are not clipped */
+}
+
+/*==============================================================*/
+/* vector draw                                                 */
+/*==============================================================*/
+void 
+sgp2_line_rel (double x, double y)
+{
+    if (_sgp2_cwin != NULL)
+       sgp2_line_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
+}
+
+/*==============================================================*/
+/* vector move                                                 */
+/*==============================================================*/
+void 
+sgp2_move_rel (double x, double y)
+{
+    if (_sgp2_cwin != NULL)
+       sgp2_move_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
+}
+
+/*==============================================================*/
+/* draw text                                                   */
+/*==============================================================*/
+void 
+sgp2_draw_text (char *message)
+{
+    double sx,sy;
+    if (_sgp2_cwin == NULL)
+       return;
+
+    wc_to_ndc (_sgp2_cwin->curx, _sgp2_cwin->cury, &sx, &sy);
+    _sgp2_stylus (_sgp2_cwin, sx, sy, 0);      /* move to location */
+    _sgp2_dev_text (_sgp2_cwin, message);
+}
+
+void
+charsize (double wid, double height)
+{
+    _sgp2_set_text (_sgp2_cwin, wid, height, cspec.textangle, cspec.font);
+}
+
+void
+textangle (double angle)
+{
+    _sgp2_set_text (_sgp2_cwin, cspec.width, cspec.height, angle, cspec.font);
+}
+
+void 
+sgp2_polyline_abs (double x[], double y[], int n)
+{
+    double x1, y1, x2, y2;
+    int i;
+    double xt, yt;
+
+    if (_sgp2_cwin == NULL || n < 2)
+       return;
+
+    wc_to_ndc (x[0], y[0], &x1, &y1);
+    wc_to_ndc (x[1], y[1], &x2, &y2);
+
+    xt = x2;           /* don't pass (x2,y2) to clip, we need them */
+    yt = y2;           /* as the beginning point of the next line */
+
+    if (clip_rect (x1, y1, xt, yt, _sgp2_cwin->view) == TRUE) {
+       _sgp2_stylus (_sgp2_cwin, x1, y1, 0);
+       _sgp2_stylus (_sgp2_cwin, xt, yt, 1);
+    }
+
+    for (i = 2; i < n; i++) {
+       x1 = x2;                        /* NDC endpoint of last line */
+       y1 = y2;
+       wc_to_ndc (x[i], y[i], &x2, &y2);
+       xt = x2;
+       yt = y2;
+       if (clip_rect (x1, y1, xt, yt, _sgp2_cwin->view) == TRUE) {
+           _sgp2_stylus (_sgp2_cwin, x1, y1, 0);
+           _sgp2_stylus (_sgp2_cwin, xt, yt, 1);
+       }
+    }
+}
+
+
+void 
+sgp2_mark_abs (double x, double y)
+{
+    double xndc, yndc;
+
+    if (_sgp2_cwin == NULL)
+       return;
+
+    wc_to_ndc (x, y, &xndc, &yndc);
+    markndc (_sgp2_cwin, xndc, yndc);
+    _sgp2_cwin->curx = x;
+    _sgp2_cwin->cury = y;
+}
+
+
+void 
+sgp2_mark_rel (double x, double y)
+{
+    sgp2_mark_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
+}
+
+
+void 
+sgp2_point_abs (double x, double y)
+{
+    double xndc, yndc;
+
+    if (_sgp2_cwin == NULL)
+       return;;
+
+    wc_to_ndc (x, y, &xndc, &yndc);
+    pntndc (_sgp2_cwin, xndc, yndc);
+    _sgp2_cwin->curx = x;
+    _sgp2_cwin->cury = y;
+}
+
+
+void 
+sgp2_point_rel (double x, double y)
+{
+    sgp2_point_abs (x + _sgp2_cwin->curx, y + _sgp2_cwin->cury);
+}
+
+
+/*----------------------------------------------------------------------*/
+/*                  Current Transformation Matrix Routine              */
+/*----------------------------------------------------------------------*/
+
+
+/* NAME
+ *     ctm_clr_2                       Clear current transformation matrix
+ *
+ * SYNOPSIS
+ *     ctm_clr_2()
+ */
+
+void 
+ctm_clr_2 (void)
+{
+    GRFMTX_2D m;
+
+    ident_gmtx_2 (m);
+    ctm_set_2 (m);
+}
+
+
+/* NAME
+ *     ctm_get_2                       Get ctm
+ *
+ * SYNOPSIS
+ *     ctm_get_2 (m)
+ * OUT GRFMTX_2D m                     Copy of ctm
+ */
+
+void 
+ctm_get_2 (GRFMTX_2D m)
+{
+    int x, y;
+
+    if (_sgp2_cwin == NULL)
+       return;
+
+    for (x = 0; x < 3; x++)
+       for (y = 0; y < 3; y++)
+           m[x][y] = _sgp2_cwin->ctm_2_x[x][y];
+}
+
+
+/* NAME
+ *     ctm_set_2                       Set ctm to a matrix
+ *
+ * SYNOPSIS
+ *     ctm_get_ctm_2 (m)
+ * IN  GRFMTX m                        New ctm
+ */
+
+void 
+ctm_set_2 (GRFMTX_2D m)
+{
+    int x, y;
+    if (_sgp2_cwin == NULL)
+       return;
+
+    for (x = 0; x < 3; x++)
+       for (y = 0; y < 3; y++)
+           _sgp2_cwin->ctm_2_x[x][y] = m[x][y];
+
+    _sgp2_cwin->recalc_ndc_to_mc = TRUE;
+    _sgp2_cwin->recalc_mc_to_ndc = TRUE;
+}
+
+
+void 
+ctm_pre_mult_2 (GRFMTX_2D m)
+{
+    GRFMTX_2D new_ctm;
+
+    mult_gmtx_2 (m, _sgp2_cwin->ctm_2_x, new_ctm);
+    ctm_set_2 (new_ctm);
+}
+
+
+void 
+ctm_post_mult_2 (GRFMTX_2D m)
+{
+    GRFMTX_2D new_ctm;
+
+    mult_gmtx_2 (_sgp2_cwin->ctm_2_x, m, new_ctm);
+    ctm_set_2 (new_ctm);
+}
diff --git a/libctgraphics/sgpdrive.cpp b/libctgraphics/sgpdrive.cpp
new file mode 100644 (file)
index 0000000..111fd3e
--- /dev/null
@@ -0,0 +1,562 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: sgpdrive.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**  $Log: sgpdrive.cpp,v $
+**  Revision 1.1  2000/06/19 18:05:03  kevin
+**  initial cvs import
+**
+**  Revision 1.2  2000/06/15 19:07:10  kevin
+**  *** empty log message ***
+**
+**  Revision 1.1  2000/06/13 16:20:31  kevin
+**  finished c++ conversions
+**
+**  Revision 1.7  2000/06/03 06:29:22  kevin
+**  Finished g2 conditional compilation
+**
+**  Revision 1.6  2000/05/24 22:49:01  kevin
+**  Updated SGP: first function X-windows version
+**
+**  Revision 1.5  2000/05/11 14:07:23  kevin
+**  Fixed compilation warnings
+**
+**  Revision 1.4  2000/05/08 20:08:15  kevin
+**  *** empty log message ***
+**
+**  Revision 1.3  2000/04/28 18:35:23  kevin
+**  removed unused files
+**
+**  Revision 1.2  2000/04/28 13:50:45  kevin
+**  Removed Makefile Makefile.in that are automatically generated by autoconf
+**
+**  Revision 1.1.1.1  2000/04/28 13:02:44  kevin
+**  Initial CVS import for first public release
+**
+**
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+/* Device Driver for IBM PC Kevin Rosenberg  March 84 */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "kstddef.h"
+#include "sgp.h"
+#include "kmath.h"
+#include "cio.h"
+
+static int init_prt(void);
+static void term_prt(void);
+
+/*===========================================================*/
+/* fundamental device drivers                                */
+/*===========================================================*/
+
+#define XCHARSIZ       (1.0 / 80.0)            /* size of standard characters */
+#define YCHARSIZ       (1.0 / 25.0)            /* on screen in NDC */
+
+#define CRTASPT            (0.75)                      /* for IBM ECD */
+
+/*-------------------*/
+/* print buffer data */
+/*-------------------*/
+#define PRTINIT            1
+#define PRTLIN     2
+#define PRTTERM     3
+
+#define PRTSIZE           200
+#define PRTMODE           1                    /* Epson 120 dot/in graphic mode */
+#define PRTASPT   (120.0 / 72.0)       /* dots/in vectical / horizontal */
+
+static DEVICE crt, prt;
+CHARSPEC cspec;
+static GRFSTATE state;
+
+
+
+/* NAME
+ *   gp_init           Initialize graphics package
+ *
+ * SYNOPSIS
+ *   gp_init()
+ */
+
+
+int
+_sgp2_init_dev (SGP_ID cwin)
+{
+#if 0
+    initdevice (CRTDEV, GM_ENHANCED, 0, 0);
+    initdevice (PRTDEV, PRTMODE, (int) (PRTSIZE * PRTASPT), PRTSIZE);
+    opendevice (CRTDEV);
+    setlinestyle (LS_SOLID);
+    setcolor (1);
+    _sgp2_set_text (XCHARSIZ, YCHARSIZ, 0.0, 0);
+    setbackg (0);
+    settextclr (1, 0);
+    gp_set_aspect (CRTDEV, CRTASPT);
+    gp_set_aspect (PRTDEV, 1.0);
+#endif
+
+    state.xndc = 10.;          /* to guarntee a move */
+    _sgp2_stylus (cwin, 0.0,0.0,0);            /* move to starting corner */
+
+    return (TRUE);
+}
+
+
+/* NAME
+ *   gp_initdev                Initializes graphic device
+ *
+ * SYNOPSIS
+ *   initdevice (dev, mode, xsize, ysize)
+ *   int dev           Device handle
+ *   int mode          Mode for device (device specific)
+ *   int xsize         Size of x buffer for PRTDEV
+ *   int ysize         Size of y buffer for PRTDEV
+ */
+
+int 
+initdevice (int dev, int mode, int xsize, int ysize)
+{
+    if (dev & CRTDEV)
+       {
+           //       crt.dotfunc = crt_wdot;
+           //      crt.linefunc = crt_line;
+           crt.xmin = 0;
+           crt.ymin = 0;
+           switch (crt.mode)
+               {
+#if 0
+               case 4:
+               case 5: 
+                   crt.xmax  = 319;
+                   crt.xsize = 320;
+                   crt.ymax  = 199;
+                   crt.ysize = 200;
+                   crt.colormax = 3;
+                   break;
+               case GM_640x200:
+                   crt.xmax  = 639;
+                   crt.xsize = 640;
+                   crt.ymax  = 199;
+                   crt.ysize = 200;
+                   crt.colormax = 1;
+                   break;
+               case GM_ENHANCED:
+               case GM_MONOGRF:
+                   crt.xmax  = 639;
+                   crt.xsize = 640;
+                   crt.ymax  = 349;
+                   crt.ysize = 350;
+                   crt.colormax = 15;
+                   break;
+               case GM_640x480x16:
+                   crt.xmax  = 639;
+                   crt.xsize = 640;
+                   crt.ymax  = 479;
+                   crt.ysize = 480;
+                   crt.colormax = 15;
+                   break;
+               case GM_640x480x256:
+                   crt.xmax  = 639;
+                   crt.xsize = 640;
+                   crt.ymax  = 479;
+                   crt.ysize = 480;
+                   crt.colormax = 255;
+                   break;
+               case GM_1024x768x16:
+                   crt.xmax  = 1023;
+                   crt.xsize = 1024;
+                   crt.ymax  = 767;
+                   crt.ysize = 768;
+                   crt.colormax = 15;
+                   break;
+               case GM_1024x768x256:
+                   crt.xmax  = 1023;
+                   crt.xsize = 1024;
+                   crt.ymax  = 767;
+                   crt.ysize = 768;
+                   crt.colormax = 255;
+                   break;
+#endif
+               default:
+                   return (FALSE);
+               }
+           //      crt_set_mode (crt.mode, TRUE);      /* Initialize device */
+       }
+
+    if (dev & PRTDEV) {
+       if (prt.open == TRUE)
+           closedevice (PRTDEV);
+       prt.buf = NULL;
+       if (mode < 0)
+           prt.mode = PRTMODE;
+       if (mode > 6)
+           prt.mode = PRTMODE;
+       else
+           prt.mode = mode;
+
+       if (xsize > 1 && ysize > 1) {
+           prt.xsize = xsize;
+           prt.ysize = ysize;
+           prt.xmin = 0;
+           prt.ymin = 0;
+           prt.xmax = prt.xsize - 1;
+           prt.ymax = prt.ysize - 1;
+       }
+
+       prt.colormax = 1;
+       //          prt.dotfunc = prtdot;
+       //          prt.linefunc = prtline;
+
+       init_prt ();            /* Initialize the device */
+    }
+
+    return (TRUE);
+}
+           
+
+/* NAME
+ *    gp_opendev               Open device for output
+ *
+ * SYNOPSIS
+ *    gp_opendev (dev)
+ *    int dev                  Device handle
+ *                             devices are number in powers of two
+ */
+
+int 
+opendevice (int dev)
+{
+    if (dev & CRTDEV)
+       crt.open = TRUE;
+
+    if (dev & PRTDEV)
+       prt.open = TRUE;
+
+    return(TRUE);
+}
+
+
+/* NAME
+ *   gp_closedev               Close device for output
+ *
+ * SYNOPSIS
+ *   gp_closedev (dev)
+ *   int dev                   Device handle
+ *
+ * DESCRIPTION
+ *    Temporarily suspends output from going to a device
+ */
+
+void
+closedevice (int dev)
+{
+    if (dev & CRTDEV)          /* close crt */
+       crt.open = FALSE;
+
+    if (dev & PRTDEV)
+       prt.open = FALSE;
+}
+
+
+void
+termdevice (int dev)
+{
+    if (dev & PRTDEV)
+       term_prt ();
+}
+
+static int init_prt(void)
+{
+    return(0);
+}
+
+
+static void term_prt(void)
+{
+}
+
+/*===========================================================*/
+/* stylus draws a line to the absolute point x,y in NDC's    */
+/*              t=0 for move, t=1 for draw                   */
+/*===========================================================*/
+void 
+_sgp2_stylus (SGP_ID cwin, double x, double y, int beam)
+{
+    int xp, yp;
+
+    if ((state.xndc == x) && (state.yndc == y) && (beam == 0))
+       return;         /* no need to move */
+
+    state.xndc = x;            /* save current beam location */
+    state.yndc = y;
+
+    if (cwin != NULL) {
+       xp = (int) (x * cwin->pw_xsize + 0.5);
+       yp = (int) (y * cwin->pw_ysize + 0.5);
+#if HAVE_G2_H
+       if (beam != 0)
+           g2_line (cwin->g2_id, (double) cwin->phys_curx, (double) cwin->phys_cury, (double) xp, (double) yp);
+#endif
+       cwin->phys_curx = xp;
+       cwin->phys_cury = yp;
+    }
+}
+
+void
+pntndc (SGP_ID cwin, double x, double y)
+{
+    _sgp2_stylus (cwin, x, y, 0);      /* move to point */
+    // if (crt.open == TRUE)
+    //     cpix_set (crt.icurx, crt.icury, crt.color);
+}
+       
+void
+markndc (SGP_ID cwin, double x, double y)
+{
+    _sgp2_stylus (cwin, x, y, 0);      /* move to point */
+
+    if (crt.open == TRUE)
+       wrtsymbol (state.marktype, crt.icurx, crt.icury, &crt);
+
+    if (prt.open == TRUE)
+       wrtsymbol (state.marktype, prt.icurx, prt.icury, &prt);
+}
+
+GRFSTATE *
+inqstate (void)
+{
+    return (&state);
+}
+
+void
+gp_set_aspect (int dev, double asp)
+{
+    if (asp > 0.0) {
+       if (dev & CRTDEV)
+           crt.asp = asp;
+       if (dev & PRTDEV)
+           prt.asp = asp;
+    }
+}
+
+void 
+setlinestyle (int style)
+{
+    if (style == state.linestyle)
+       return;
+
+    state.linestyle = style;
+
+    crt.style = style;
+    prt.style = style;
+
+    // crt_line_style (crt.style);
+}
+
+void
+setlinewidth (int wid)
+{
+    state.linewidth = wid;
+}
+
+DEVICE *
+inqdev (int dev)
+{
+    extern DEVICE prt, crt;
+
+    if (dev & CRTDEV)
+       return (&crt);
+    else if (dev & PRTDEV)
+       return (&prt);
+    else
+       return (NULL);
+}
+
+/*===========================================================*/
+/* set text size                                             */
+/*===========================================================*/
+void
+_sgp2_set_text ( SGP_ID cwin,
+        double width,
+        double height,                 /* size of character in NDC */
+        double textangle,                      /* text angle */
+        int font                               /* text font */
+        )
+{
+    double temp;
+
+#if HAVE_G2_H
+    g2_set_font_size(cwin->g2_id, (height * cwin->pw_ysize));
+#endif
+    height = clamp (height, 0.0, 1.0);
+    width = clamp (width, 0.0, 1.0);
+    /* textangle = textangle - (2 * PI * (int) (textangle / (2 * PI)));
+     */
+    cspec.width = width;
+    cspec.height = height;
+    cspec.textangle = textangle;
+    cspec.font = font;
+
+    if (textangle > - HALFPI / 2 && textangle < HALFPI / 2) {
+       cspec.updir = YPLUS;
+       cspec.textdir = XPLUS;
+    } else if (textangle > HALFPI / 2 && textangle < 3 * HALFPI / 2) {
+       cspec.updir = XMINUS;
+       cspec.textdir = YPLUS;
+    } else if (textangle > 3 * HALFPI / 2 && textangle < 5 * HALFPI / 2) {
+       cspec.updir = YMINUS;
+       cspec.textdir = XMINUS;
+    } else if (textangle > 5 * HALFPI / 2 && textangle < 7 * HALFPI / 2) {
+       cspec.updir = XPLUS;
+       cspec.textdir = YMINUS;
+    } else {
+       cspec.updir = YPLUS;
+       cspec.textdir = XPLUS;
+    }
+
+    if (cspec.updir == XMINUS || cspec.updir == XPLUS) {
+       temp = height;
+       height = width;
+       width = temp;
+    }
+
+    crt.icwidth = (int) (width * crt.xsize + 0.5);
+    crt.icheight = (int) (height * crt.ysize + 0.5);
+    crt.icwidth = clamp (crt.icwidth, 8, crt.xsize);
+    crt.icheight = clamp (crt.icheight, 8, crt.ysize);
+
+    prt.icwidth = (int) (width * prt.xsize + 0.5);
+    prt.icheight = (int) (height * prt.ysize + 0.5);
+    prt.icwidth = clamp (prt.icwidth, 8, prt.xsize);
+    prt.icheight = clamp (prt.icheight, 8, prt.ysize);
+}
+
+void
+settextclr (int fore, int back)
+{
+    cspec.fore = fore;
+    cspec.back = back;
+    crt.cfore = fore;
+    crt.cback = back;
+    prt.cfore = clamp (fore, 0, prt.colormax);
+    prt.cback = back;
+}
+
+void
+setcolor (int fore)
+{
+    int back;
+
+    state.foregnd = fore;
+    back = state.backgnd;
+    crtcolor (crt.mode, &fore, &back);         /* set colors on crt */
+    crt.color = fore;
+    prt.color = clamp (fore, 0, prt.colormax);
+}
+
+void
+setbackg (int back)
+{
+    int fore;
+
+    state.backgnd = back;
+    fore = state.foregnd;
+    crtcolor (crt.mode, &fore, &back);
+}
+
+/*
+ * INITMARKER (<SYMBOL>)
+ *
+ * Sets the current marker symbol (cross, square, diamond..)
+ */
+int 
+initmarker (int marker, int color)
+{
+    if (marker > NMARKERS || marker < 0)
+       return(-1);
+    else {
+       state.marktype = marker;
+       state.markcolor = color;
+    }
+    return(0);
+} /* end initmarker */
+
+/*
+ * SETCHARDIR ( <DIRECTION> )
+ *
+ * indicates in which direction a string should be printed, e.g.:
+ *  direction = YPLUS  -> print on the horizontal from left to right
+ *  direction = YMINUS -> print upside-down characters from right to left
+ *  direction = XMINUS -> print on the vertical from down to up
+ *  direction = XPLUS  -> print on the vertical from up to down
+ */
+int 
+settextdir (
+           int direction        /* direction flag */
+           )
+{
+
+    if (direction != XPLUS &&
+       direction != XMINUS &&
+       direction != YPLUS &&
+       direction != YMINUS ) {
+       printf("Error in character direction: %d\n", direction);
+       return(-1);
+    }
+    cspec.textdir = direction;
+    charsize (cspec.width, cspec.height);
+
+    return(0);
+}  /* end setchardir */
+
+
+void
+_sgp2_dev_text (SGP_ID cwin, char *message)
+{
+#if HAVE_G2_H
+    g2_string (cwin->g2_id, cwin->phys_curx, cwin->phys_cury, message);
+#endif
+}
+
+/*===========================================================*/
+/* terminate graphics to current device                      */
+/*     close any files, and output any buffers               */
+/*===========================================================*/
+void
+termgrf2 (void)
+{
+    if (prt.open == TRUE) {
+       flushdevice (PRTDEV);
+       closedevice (PRTDEV);
+       termdevice (PRTDEV);
+    }
+
+    if (crt.open == TRUE) {
+       closedevice (CRTDEV);
+    }  
+}
+
+
+void
+flushdevice (int dev)
+{
+    // if (dev & PRTDEV)
+    //     prtline (PRTTERM, 0, 0, 0, 0, 0, 0);   /*  print contents of printer buffer */
+}
diff --git a/libctgraphics/sgptext.cpp b/libctgraphics/sgptext.cpp
new file mode 100644 (file)
index 0000000..a4cb1a3
--- /dev/null
@@ -0,0 +1,116 @@
+/*****************************************************************************
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2000 Kevin Rosenberg
+**
+**  $Id: sgptext.cpp,v 1.1 2000/06/19 18:05:03 kevin Exp $
+**  $Log: sgptext.cpp,v $
+**  Revision 1.1  2000/06/19 18:05:03  kevin
+**  initial cvs import
+**
+**  Revision 1.1  2000/06/13 16:20:31  kevin
+**  finished c++ conversions
+**
+**  Revision 1.2  2000/04/28 18:35:23  kevin
+**  removed unused files
+**
+**  Revision 1.1.1.1  2000/04/28 13:02:44  kevin
+**  Initial CVS import for first public release
+**
+**
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License (version 2) as
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+/* FILE
+ *   sgptext.c                         Text routines for graphics package
+ */
+
+#include "kstddef.h"
+#include "sgp.h"
+#include <stdio.h>
+#include "cio.h"
+
+
+/* Pixel patterns of marker symbols (1x1 to 5x5 matrix) */
+char MARKER[NMARKERS][5] = {
+       { '\0', '\0', '\010', '\0', '\0'},              /* small dot */
+       { '\0', '\034', '\024', '\034', '\0'},          /* empty square */
+       { '\0', '\034', '\034', '\034', '\0'},          /* filled square */
+       { '\0', '\010', '\024', '\010', '\0'},          /* empty diamond */
+       { '\0', '\010', '\034', '\010', '\0'},          /* filled diamond */
+       { '\010', '\010', '\076', '\010', '\010'},      /* cross */
+       { '\0', '\024', '\010', '\024', '\0'},          /* x */
+       { '\034', '\042', '\042', '\042', '\034'},      /* open circle */
+       { '\034', '\076', '\076', '\076', '\034'},      /* filled circle */
+       { '\076', '\042', '\042', '\042', '\076'},      /* big open square */
+       { '\010', '\024', '\042', '\024', '\010'}};     /* big open diamond */
+
+/* WRTSYMBOL (sym, x, y, dev)
+ *
+ * puts marker symbols on the screen
+ * input in screen pixels
+ * Calls: dot()
+ */
+
+void 
+wrtsymbol (
+    int sym,
+    int x,
+    int y,           /* Coordinates in screen pixels */
+    DEVICE *dev
+)
+{
+} 
+
+/*
+ * WRTCHAR(<CH>, <X>, <Y>, cspec, dev)
+ *
+ * puts marker symbols on the screen
+ * input in screen pixels
+ * Calls: dot(), peek()
+ */
+
+void 
+wrtchar (
+    int ch,    /* Character to be put on the screen */
+    int x,
+    int y,     /* Coordinates in screen pixels of lower left corner*/
+    CHARSPEC *cspec,
+    DEVICE *dev
+)
+{
+} 
+
+/*
+ * WRTTEXT (<STRING>)
+ *
+ * prints a string starting from current position writing in the current
+ * printing direction (at right angle to the character direction)
+ * The pen is return to the original position.
+ */
+
+void
+wrttext (char txtstr[], int x, int y, CHARSPEC *cspec, DEVICE *dev)
+{
+} 
+
+
+/*
+ * SETCOLOR( <COLOR>)
+ *
+ * Set current color
+ */
+void 
+crtcolor (int mode, int *f, int *b)
+{
+}