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