--- /dev/null
+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
+
+
+
--- /dev/null
+# 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
--- /dev/null
+/* ; 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);
+}
+
--- /dev/null
+/*****************************************************************************
+** 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 */
+}
--- /dev/null
+/*****************************************************************************
+** 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]);
+}
+
--- /dev/null
+/*****************************************************************************
+** 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);
+}
--- /dev/null
+/*****************************************************************************
+** 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);
+}
+
+
--- /dev/null
+/*****************************************************************************
+** 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();
+}
--- /dev/null
+/*****************************************************************************
+** 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);
+}
--- /dev/null
+/*****************************************************************************
+** 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]");
+}
--- /dev/null
+/*****************************************************************************
+** 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);
+}
--- /dev/null
+/*****************************************************************************
+** 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);
+}
--- /dev/null
+/*****************************************************************************
+** 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 */
+}
--- /dev/null
+/*****************************************************************************
+** 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)
+{
+}