home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Copyright (C) 1988, 1989 by Juha Takala, jta@sah.vtt.fi
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 1.
-
- 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
- the file "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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
- */
-
-
- /* Description:
- * dr_lib.c provides interface between device level and my draw(1).
- * Supported devices are:
- * - hpgl output for hp7475 plotter
- * - gl_plot(3) calls for EGA or matrix printer output
- * - plot(3) interface
- *
- */
- static char *rcsid =
- "$Id: dr_lib.c,v 2.4 89/12/08 14:00:34 jta Exp Locker: jta $";
-
- /* define this, if your plotter connection is 'y-cable' (not direct) */
- /* #define YCABLE /* */
-
- /* definede this if you want to ask paper size from plotter */
- /* (should not be used, if you are going to use this package as */
- /* part of pipelines) */
- /* #define ASK /* */
-
- #include <stdio.h>
- #include <math.h>
- #ifdef MSDOS
- #include <bios.h>
- #endif
- #include "dr_lib.h"
-
- #define ESC 0x1b /* ascii <ESC> */
-
- static int xscale(), yscale();
- static void sends(), invdev();
-
- #ifdef ASK
- static void takes();
- #endif /* ASK */
-
- /*
- * internal global variable declarations
- *
- */
- /* coordinate transformations */
- static float xuserincr, yuserincr;
- static float xuserlow, yuserlow;
- static float xuserhigh, yuserhigh;
- static float xdevicelow, ydevicelow;
- static float xdevicehigh, ydevicehigh;
- static float xrelarea, yrelarea;
- static float xfactor, yfactor;
- static float shape_factor, size_factor; /* text 'fatness' and size factors */
- static int lastx=0, lasty=0; /* device coordinates for last point */
-
-
- static int device = INVDEV; /* what output device we are working for */
- static int old_linetype = -1; /* remember last used linetype */
- static int old_pen = -1; /* ...and pen */
-
- static int errcount, warncount, errfile;
- static char *errfilename = "draw.err";
-
- static FILE *errfilefp;
-
-
-
- /* ********************************************************** */
- /* */
- /* Following functions are ment to be subroutines to be */
- /* called from a user supplied main program */
- /* */
- /* ********************************************************** */
-
- /*
- * dr_set_cset() - select cset
- *
- */
- void dr_set_cset(n)
- int n;
- {
- char s[50];
-
- switch (device)
- {
- case HP7475:
- if (n < 0 || n == 5 || (n > 9 && n < 30) || n > 39) {
- (void)sprintf(s, "Invalid cset code %d, using 0", n);
- dr_errmsg(s);
- n = 0;
- }
- (void)sprintf(s, "CS%d;\n", n);
- sends(s);
- break;
- #ifdef GL_LIB
- case SCREEN:
- /* (void)sprintf(s, "cset not yet for SCREEN");
- dr_errmsg(s); /* */
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- /* (void)sprintf(s, "cset not valid for PLOT");
- dr_errmsg(s); /* */
- break;
- #endif
- default:
- invdev(); break;
- }
- }
-
- /*
- * dr_set_pen() - select pen
- *
- */
- void dr_set_pen(n)
- int n; /* pen number, 1..6, 0=='put it away' */
- {
- char s[50];
-
- switch (device)
- {
- case HP7475:
- if (n < 0 || n > 6) {
- (void)sprintf(s, "Invalid pen code %d, using 1", n);
- dr_errmsg(s);
- n = 1;
- }
- if (n != old_pen) { /* optimize for hpgl... */
- old_pen = n;
- (void)sprintf(s, "SP%d;", n);
- sends(s);
- }
- break;
- #ifdef GL_LIB
- case SCREEN:
- /* (void)sprintf(s, "dr_set_pen(colour) not yet for SCREEN\n");
- dr_errmsg(s); /* */
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- /* (void)sprintf(s, "dr_set_pen(colour) not valid for PLOT\n");
- dr_errmsg(s); /* */
- break;
- #endif
- default:
- invdev(); break;
- }
- }
-
- /*
- * dr_goto() - move pen to point x, y
- *
- */
- void dr_goto(x, y, penup)
- float x, y; /* where he wants to go */
- int penup; /* nonzero == lift pen before moving */
- {
- char s[60];
- lastx = xscale(x);
- lasty = yscale(y);
- switch (device)
- {
- case HP7475:
- if (penup) sends ("PU");
- else sends ("PA;PD");
-
- /* go to point, leave pen as told
- */
- (void)sprintf(s, "%d,%d;\n", lastx, lasty);
- sends(s);
- break;
- #ifdef GL_LIB
- case SCREEN:
- if (penup) n_movepen(lastx, lasty);
- else n_draw(lastx, lasty);
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- if (penup) move(lastx, lasty);
- else cont(lastx, lasty);
- break;
- #endif
- default:
- invdev(); break;
- }
- return;
- }
-
-
- /*
- * dr_draw_line() - draw line (x1,y1) .. (x2,y2)
- *
- * connect the two data points with line
- */
- void dr_draw_line(x1, y1, x2, y2)
- float x1, y1, x2, y2; /* data points */
- {
- char s[60];
-
- lastx = xscale(x2);
- lasty = yscale(y2);
- switch (device)
- {
- case HP7475:
- /* lift pen,
- * go to first point,
- * drop pen there,
- */
- (void)sprintf(s, "PA;PU%d,%d;PD;", xscale(x1), yscale(y1));
- sends(s);
-
- /* draw line segment, lift pen
- */
- (void)sprintf(s, "PD%d,%d;PU;\n", lastx, lasty);
- sends(s);
- break;
- #ifdef GL_LIB
- case SCREEN:
- n_line(xscale(x1), yscale(y1), lastx, lasty);
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- line(xscale(x1), yscale(y1), lastx, lasty);
- break;
- #endif
- default:
- invdev(); break;
- }
- return;
- }
-
-
- /*
- * dr_draw_array() - draw y = f(x)
- *
- * connect data points with line
- */
- void dr_draw_array(x, y, n)
- float x[], y[]; /* data points */
- int n; /* number of points in x[] and y[] */
- {
- int i;
- char s[60];
-
- /* if we really have something to draw
- */
- if (n < 1)
- return;
-
- switch (device)
- {
- case HP7475:
- /* lift pen,
- * go to first point,
- * drop pen there,
- */
- (void)sprintf(s, "PA;PU%d,%d;PD;", xscale(x[0]), yscale(y[0]));
- sends(s);
-
- /* draw line segments
- */
- for (i=1; i<n; i++) {
- if (i % 4 == 0) sends("\n");
- (void)sprintf(s, "PD%d,%d;", xscale(x[i]), yscale(y[i]));
- sends(s);
- }
-
- /* finally lift pen
- */
- sends("PU;\n");
- break;
- #ifdef GL_LIB
- case SCREEN:
- n_movepen(xscale(x[0]), yscale(y[0]));
- for (i=1; i<n; i++)
- n_draw(xscale(x[i]), yscale(y[i]));
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- move(xscale(x[0]), yscale(y[0]));
- for (i=1; i<n; i++)
- cont(xscale(x[i]), yscale(y[i]));
- break;
- #endif
- default:
- invdev(); break;
- }
- lastx = xscale(x[i-1]);
- lasty = yscale(y[i-1]);
- return;
- }
-
-
- /*
- * dr_put_mark() - make a mark at (x,y)
- *
- * put mark at data point
- */
- void dr_put_mark(x, y, mark)
- float x, y; /* data point */
- char mark;
- {
- char s[60];
-
- lastx = xscale(x);
- lasty = yscale(y);
- switch (device)
- {
- case HP7475:
- /* if we really have something to plot
- */
-
- /* lift pen,
- * set symbol mode,
- */
- (void)sprintf(s, "PA;PU;SM%c;", mark);
- sends(s);
-
- /* put symbol at all data points
- */
- (void)sprintf(s, "PU%d,%d;", lastx, lasty);
- sends(s);
-
- /* reset symbol mode
- */
- sends("SM;\n");
- break;
- #ifdef GL_LIB
- case SCREEN:
- n_movepen(lastx, lasty);
- n_grafchar(mark);
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- move(lastx, lasty);
- *s = mark;
- *(s+1) = '\0';
- label(s);
- break;
- #endif
- default:
- invdev(); break;
- }
- return;
- }
-
-
- void dr_set_shape(x)
- float x;
- {
- if (x > 0.0)
- shape_factor = x * xrelarea/yrelarea;
- return;
- }
-
-
- void dr_set_size(x)
- float x;
- {
- if (x > 0.0)
- size_factor = x;
- return;
- }
-
-
- /*
- * dr_put_text() - put some text
- * plot(3) only has one size and orientation, what can you do!
- *
- */
- void dr_put_text(x, y, xofs, yofs, angle, size, s)
- float x, y; /* where to put it */
- float xofs, yofs; /* offset of start position, measured in */
- /* character size units */
- float angle; /* radians, 0.0 == horizontal */
- float size; /* relative size of text */
- char *s; /* the text */
- {
- char ss[60];
- int senddir;
- char dir[30];
-
- if (size <= 0.0) {
- sprintf(ss, "invalid size: %f");
- dr_errmsg(ss);
- return;
- }
- size *= size_factor;
-
- switch (device)
- {
- case HP7475:
- senddir = (angle != 0.0);
- if (senddir) {
- if (angle == M_PI_2)
- sprintf(dir,"DI0,1");
- else if (angle == -M_PI_2)
- sprintf(dir,"DI0,-1");
- else
- sprintf(dir,"DI1,%f", tan(angle));
- }
-
- /* lift pen, go to specified position, set direction & size,
- */
-
- (void)sprintf(ss, "PA;PU%d,%d;%s;SR%4.2f,%4.2f;\n",
- xscale(x), yscale(y),
- (senddir ? dir : ""),
- size * 0.75 * shape_factor * xrelarea,
- size * 1.5 * yrelarea);
- sends(ss);
-
- /* go to offset,
- * put text,
- * restore 0 degree direction.
- */
- if ((xofs != 0.0) || (yofs != 0.0)) {
- (void)sprintf(ss, "CP%4.2f,%4.2f;\n", xofs, yofs);
- sends(ss);
- }
- sends("LB"); sends(s); sends("\03\n");
-
- /* correction for y-offset, if necessary, to leave pen on same */
- /* height but after the text */
- if (yofs != 0.0) {
- (void)sprintf(ss, "CP0,%4.2f;\n", -yofs);
- sends(ss);
- }
-
- if (senddir)
- sends("DI1,0;\n");
- /* lastx = ....;
- lasty = ....; /* hp7475 does not really need these, */
- /* it remembers the pen position */
-
- break;
- #ifdef GL_LIB
- case SCREEN:
- n_movepen(xscale(x), yscale(y));
-
- #define GL_MODE_255_HAS_BUG
- #ifdef GL_MODE_255_HAS_BUG
- /* DT Lewis!! Wake up! */
- /* For some reason gl_lib works strangely with GL_MODE == 255 */
- /* (the output is (almost) microscopic small and weird shape). */
- /* We can compensate that strangeness here by modifying size */
- /* and sape factors for g_fontctl()... The values 3.0 and 0.4 */
- /* are experimental results (by kekkonen@sah.vtt.fi). */
- if (strncmp(getenv("GLMODE"),"256",3)==0)
- g_fontctl(3.0*size*yrelarea, 0.4*shape_factor, 1.0, angle, 0.0);
- else
- #endif
- #undef GL_MODE_255_HAS_BUG
- g_fontctl(size*yrelarea, shape_factor, 1.0, angle, 0.0);
- yofs = -0.5 - yofs;
- n_ch_ofs(xofs, yofs);
- n_grafstr(s);
- n_ch_ofs(0.0, -yofs);
- g_fontctl(size, 1.0, 1.0, 0.0, 0.0);
- /* lastx = ....;
- lasty = ....; /* this does not really need these, */
- /* it remembers the pen position */
-
- break;
- #endif
- #ifdef PLOT
- #define PLOT_CH_XSIZE 70
- #define PLOT_CH_YSIZE 100
- case PLOTLIB:
- {
- int i;
- float xsize, ysize;
- float xbase, ybase;
- float xincr, yincr;
- float xofs1, yofs1;
-
- xsize = PLOT_CH_XSIZE * size * xrelarea;
- ysize = PLOT_CH_YSIZE * size * yrelarea;
-
- yofs += 0.4; /* middle --> botom */
- xofs1 = (xofs * xsize * cos(angle) * shape_factor -
- yofs * ysize * sin(angle));
- yofs1 = (xofs * xsize * sin(angle) * shape_factor +
- yofs * ysize * cos(angle));
- xbase = xscale(x) + xofs1;
- ybase = yscale(y) + yofs1;
-
- xincr = cos(angle) * xsize * shape_factor;
- yincr = sin(angle) * ysize;
-
- /* This is how we simulate different printing directions */
- /* and character sizes: by moving to the position of every */
- /* single character one at a time */
- *(ss+1) = '\0';
- for (i=0; *ss=*s; s++,i) {
- move((int) (0.5 + xbase + i * xincr),
- (int) (0.5 + ybase + i * yincr));
- label(ss);
- i++;
- }
-
- lastx = (int) (0.5 + xbase + i * xincr - xofs1);
- lasty = (int) (0.5 + ybase + i * yincr - yofs1);
- move(lastx, lasty);
- }
- break;
- #endif
- default:
- invdev(); break;
- }
- return;
- }
-
- /*
- * dr_small_circle() - draw small circle at current point.
- * This routine needs the help of lastx and lasty in case of plot(3) library.
- *
- */
- void dr_draw_circle()
- {
- switch (device)
- {
- case HP7475:
- sends("CI35;\n"); break;
- #ifdef GL_LIB
- case SCREEN:
- n_ellipse1(100, 100); break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- circle(lastx, lasty, 20); break;
- #endif
- default:
- invdev(); break;
- }
- }
-
-
- /*
- * dr_finish() - terminate the plotting
- *
- * This routine must be called after all plotting activity is done
- * to restore the Y-cable connection so that terminal gets control
- */
- int dr_finish(clean_scr)
- int clean_scr; /* != 0 if we have clear screen */
- {
- char s[20];
-
- switch (device)
- {
- case HP7475:
- /* deselct pen,
- * reset Y-cable connection
- * (<esc>.Z is ignored if not Y-cable connecton )
- */
- (void)sprintf(s, "SP;%c.Z\n", ESC);
- sends(s);
- break;
- #ifdef GL_LIB
- case SCREEN:
- if (clean_scr && (strncmp(getenv("GLMODE"), "256", 3) != 0)) {
- #ifdef UNIX
- FILE *fp = fopen("/dev/tty", "r");
- fgets(s, 2, fp); /* wait for user response */
- fclose(fp);
- #endif /* UNIX */
- #ifdef MSDOS
- _bios_keybrd(_KEYBRD_READ); /* wait for keybrd. input forever */
- #endif /* MSDOS */
- }
- {
- int status;
- status = g_finish(); /* do clean screen */
- if (status != 0)
- dr_errmsg("dr_lib(): problems with g_finish().");
- }
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- move(0,0);
- closepl();
- break;
- #endif
- default:
- break; /* call to invdev() --> recursion */
- }
-
- /* check errors, tell if any or remove error log file
- */
- if (errcount == 0 && warncount == 0)
- (void)unlink(errfilename);
- else {
- if (errcount)
- (void)fprintf(stderr, "%d error%s,",
- errcount, (errcount == 1 ? "" : "s"));
- if (warncount)
- (void)fprintf(stderr, "%d warning%s,",
- warncount, (warncount == 1 ? "" : "s"));
- (void)fprintf (stderr, " see file \"%s\".\n", errfilename);
- }
- /* return something useful
- */
- return (errcount);
- }
-
-
- /*
- * dr_start - init the plotting device
- *
- * This routine must be called before any plotting activity is done
- * to set up the Y-cable connction so that plotter starts processing
- * or in case of direct connection, open the device
- */
- void dr_start(xlow, ylow, xhigh, yhigh, dev)
- int dev; /* plotting device & paper size */
- float xlow, xhigh; /* drawing area, relative to.. */
- float ylow, yhigh; /* ..whole paper, that means: */
- /* 0.0, 0.5, 0.5, 1.0 will use */
- /* upper left quarter of paper */
- {
- int p1x, p1y, p2x, p2y;
- float t1, t2;
- char s[200];
-
- /* open error log file
- */
- errcount = 0;
- warncount = 0;
- if ((errfilefp = fopen(errfilename, "w")) == NULL) {
- (void)fprintf(stderr, "\nCan't open %s. Aborting.\n", errfilename);
- exit(1);
- }
- errfile = fileno(errfilefp);
- xrelarea = xhigh - xlow;
- yrelarea = yhigh - ylow;
- shape_factor = yrelarea/xrelarea; /* back to normal 'fatness' */
- size_factor = 1.0; /* actual size normalized to area */
-
- switch (device = (dev & DEVMASK))
- {
- case HP7475:
- /* set Y-cable connection,
- * (<esc>.Y is ignored if not Y-cable connecton )
- * init the plotter,
- * set handshake mode x-on/x-off,
- * select pen #1
- */
- (void)sprintf(s, "\n%c.Y;IN;", ESC); /* Y-connection, plotter on */
- sends(s);
- (void)sprintf(s, "%c.I80;;17:", ESC); /* enable x-on/x-off x-on=^q */
- sends(s);
- (void)sprintf(s, "%c.N;19:\n", ESC); /* x-off=^s */
- sends(s);
- #ifdef ASK
- /* ask picture area from plotter
- * set up limits (leave some room for axis labels etc.) */
- sends("OP;");
- takes(s);
- #else /* ASK */
- /* we would get one of this */
- switch (dev & SIZEMASK)
- {
- case SIZE_A:
- (void)sprintf (s, "250,596,10250,7796\n");
- sends("PS4;\n");
- break;
- case SIZE_A4:
- (void)sprintf (s, "603,521,10603,7721\n");
- sends("PS4;\n");
- break;
- case SIZE_B:
- (void)sprintf (s, "522,259,15722,10259\n");
- sends("PS3;\n");
- break;
- case SIZE_A3:
- (void)sprintf (s, "170,602,15370,10602\n");
- sends("PS3;\n");
- break;
- default:
- dr_errmsg("Invalid paper size. Aborting.");
- (void)dr_finish();
- exit(1);
- }
- #endif /* ASK */
- if ( sscanf(s, "%d,%d,%d,%d", &p1x, &p1y, &p2x, &p2y) == 4 ) {
- /* some room for labels */
- t1 = p1x + 0.05*(p2x-p1x); /* y-label */
- t2 = p2x - 0.001*(p2x-p1x); /* right margin */
- xdevicelow = t1 + xlow * (t2 - t1);
- xdevicehigh = t1 + xhigh * (t2 - t1);
- t1 = p1y + 0.05*(p2y-p1y); /* x-label */
- t2 = p2y - 0.07*(p2y-p1y); /* name */
- ydevicelow = t1 + ylow * (t2 - t1);
- ydevicehigh = t1 + yhigh * (t2 - t1);
- }
- else {
- dr_errmsg("Can't receive plotter dimensions. Aborting.");
- (void) dr_finish();
- exit(1);
- }
-
- dr_set_pen(1); /* select some pen */
- break;
- #ifdef GL_LIB
- case SCREEN:
- p1x = 0; p1y = 32767;
- p2x = 32767; p2y = 0;
- t1 = p1x + 0.06*(p2x-p1x); /* room y-axis label */
- t2 = p2x - 0.001*(p2x-p1x); /* no room at right margin */
- xdevicelow = t1 + xlow * (t2 - t1);
- xdevicehigh = t1 + xhigh * (t2 - t1);
- t1 = p1y + 0.10*(p2y-p1y); /* room for x-axis label */
- t2 = p2y - 0.05*(p2y-p1y); /* room fo picture's name */
- ydevicelow = t1 + ylow * (t2 - t1);
- ydevicehigh = t1 + yhigh * (t2 - t1);
-
- #define ENV_MODE 0 /* from gl.h; it means that g_init() will */
- /* look operating mode in environment */
- /* variable GLMODE */
- g_init(ENV_MODE);
- #undef ENV_MODE
- /* dr_set_pen(1); /* select some pen */
- break;
- #endif
-
- #ifdef PLOT
- case PLOTLIB:
- /* Y-cable for Tektornix? */
- p1x = 0; p1y = 0;
- p2x = 5450; p2y = 4095;
- /* 5% room for labels */
- t1 = p1x + 0.07*(p2x-p1x); /* y-label */
- t2 = p2x - 0.02*(p2x-p1x);; /* righ margin */
- xdevicelow = t1 + xlow * (t2 - t1);
- xdevicehigh = t1 + xhigh * (t2 - t1);
- t1 = p1y + 0.10*(p2y-p1y); /* x-label */
- t2 = p2y - 0.05*(p2y-p1y); /* name */
- ydevicelow = t1 + ylow * (t2 - t1);
- ydevicehigh = t1 + yhigh * (t2 - t1);
-
- openpl();
- space(0,0,4096,4096);
- erase();
- break;
- #endif
- default:
- invdev(); break;
- }
-
- /* check coordinate position legality
- */
- if (xlow < -0.0001 || xhigh > 1.0001 ||
- ylow < -0.0001 || yhigh > 1.0001) {
- dr_errmsg("Illegal x/y low/high position. Aborting.");
- (void)dr_finish();
- exit(1);
- }
- return;
- }
-
-
- /*
- * dr_xgrid - draw x grid
- *
- * Draw grid lines parallel to y-axis. When argument n == 0, makes
- * lines at every tic-mark, n == 1 makes one grid line between every
- * tic mark etc. To leave grid lines away, just don't call this.
- */
- void dr_xgrid(n)
- int n; /* number of grid lines */
- /* between tic-marks */
- {
- int i;
- int x, y1, y2; /* temps for grid line positions */
- int nlines; /* number of grid lines to draw */
- char s[200];
-
- /* check interval
- */
- if (n < 1) {
- dr_errmsg("Invalid x-grid interval, using 1");
- n = 1;
- }
-
- /* how many lines we have?
- */
- nlines = (int) (n*(xuserhigh-xuserlow)/xuserincr - 0.5);
-
- switch (device)
- {
- case HP7475:
- /* select absolute moving
- */
- sends("PA;\n");
- #ifdef SLOW
- if (slow) {
- }
- #endif
- /* draw desired number of lines, sawing up and down
- */
- y1 = yscale(yuserlow);
- y2 = yscale(yuserhigh);
- for (i=1; i<=nlines; i++) {
- /* go up */
- x = xscale(i*xuserincr/n+xuserlow);
- (void)sprintf(s, "PU%d,%d;PD%d,%d;", x, y1, x, y2);
- sends(s);
- /* go down */
- if (++i <= nlines) {
- x = xscale(i*xuserincr/n+xuserlow);
- (void)sprintf(s, "PU%d,%d;PD%d,%d;\n", x, y2, x, y1);
- sends(s);
- }
- }
-
- /* lift pen
- */
- sends("PU;\n");
- break;
- #ifdef GL_LIB
- case SCREEN:
- y1 = yscale(yuserlow);
- y2 = yscale(yuserhigh);
- for (i=1; i<=nlines; i++) {
- x = xscale(i*xuserincr/n+xuserlow);
- n_line(x,y1, x,y2);
- }
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- y1 = yscale(yuserlow);
- y2 = yscale(yuserhigh);
- for (i=1; i<=nlines; i++) {
- x = xscale(i*xuserincr/n+xuserlow);
- line(x,y1, x,y2);
- }
- break;
- #endif
- default:
- invdev(); break;
- }
- }
-
-
- /*
- * dr_ygrid - draw y grid
- *
- * See dr_xgrid().
- */
- void dr_ygrid(n)
- int n;
- {
- int i;
- int nlines; /* number of lines */
- char s[200];
- int x1, x2, y;
-
- /* check interval
- */
- if (n < 1) {
- dr_errmsg("Invalid y-grid interval, using 1");
- n = 1;
- }
-
- /* how many lines do we have?
- */
- nlines = (int) (n*(yuserhigh-yuserlow)/yuserincr - 0.5);
-
- switch (device)
- {
- case HP7475:
- /* select absolute moving
- */
- sends("PA;\n");
-
- /* draw desired number of lines, sawing right and left
- */
- x1 = xscale(xuserlow);
- x2 = xscale(xuserhigh);
- for (i=1; i<=nlines; i++) {
- /* go right */
- y = yscale(yuserlow+i*yuserincr/n);
- (void)sprintf(s, "PU%d,%d;PD%d,%d;", x1, y, x2, y);
- sends(s);
- /* go left */
- if (++i <= nlines) {
- y = yscale(yuserlow+i*yuserincr/n);
- (void)sprintf(s, "PU%d,%d;PD%d,%d;", x2, y, x1, y);
- sends(s);
- }
- sends("\n");
- }
-
- /* lift pen
- */
- sends("PU;\n");
- break;
- #ifdef GL_LIB
- case SCREEN:
- x1 = xscale(xuserlow);
- x2 = xscale(xuserhigh);
- for (i=1; i<=nlines; i++) {
- y = yscale(i*yuserincr/n+yuserlow);
- n_line(x1,y, x2,y);
- }
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- x1 = xscale(xuserlow);
- x2 = xscale(xuserhigh);
- for (i=1; i<=nlines; i++) {
- y = yscale(i*yuserincr/n+yuserlow);
- line(x1,y, x2,y);
- }
- break;
- #endif
- default:
- invdev(); break;
- }
- }
-
-
- /*
- * dr_area_def - establish x and y axis
- *
- * [xy]low lower left corner
- * [xy]high upper right corner
- * [xy]incr increment of tic-marks
- * no_axes flag, != 0 means don't draw axes
- *
- * Coordinate values will be printed at every tic-mark, so useful
- * values for incr is such that (high-low)/incr will be some small
- * integer. With functions dr_xgrid() and dr_ygrid() it is possible to
- * draw grid lines also in between these tic-marcs.
- */
- void dr_area_def(xlow, xincr, xhigh, ylow, yincr, yhigh, no_axes)
- float xlow, xincr, xhigh;
- float ylow, yincr, yhigh;
- int no_axes;
- {
- int i;
- char units[30]; /* place for units */
- char s[200];
- float x, y;
- int ix, iy, nx, ny;
-
- /* set the globals
- */
- xuserlow = xlow; xuserhigh = xhigh; xuserincr = xincr;
- yuserlow = ylow; yuserhigh = yhigh; yuserincr = yincr;
- xfactor = (xdevicehigh - xdevicelow) / (xuserhigh - xuserlow);
- yfactor = (ydevicehigh - ydevicelow) / (yuserhigh - yuserlow) ;
-
- /* check legality,
- * abort on error
- */
- if ((xincr == 0.0) ||
- (xuserlow == xuserhigh) ||
- ((xuserhigh-xuserlow)*xincr < 0.0)) {
- dr_errmsg("x-axis defined improperly. Aborting.");
- (void)dr_finish();
- exit(1);
- }
- if ((yincr == 0.0) ||
- (yuserlow == yuserhigh) ||
- ((yuserhigh-yuserlow)*yincr < 0.0)) {
- dr_errmsg("y-axis defined improperly. Aborting.");
- (void)dr_finish();
- exit(1);
- }
- if (no_axes)
- return;
-
- switch (device)
- {
- case HP7475:
-
- /* draw box
- * --------
- */
-
- /* select absolute plotting mode,
- * lift pen,
- * go to lower left corner
- */
- (void)sprintf(s,"PA;PU%d,%d;\n",
- xscale(xlow), yscale(ylow));
- sends(s);
-
- /* draw x-axis with x-tick marks
- */
-
- (void)sprintf(s, "TL%.1f,%.1f;\n", 0.5*xrelarea, 0.5*yrelarea);
- sends(s);
- for (nx=0, x = xlow;
- x < xhigh + xincr/100.0;
- x += xincr, nx++) {
- (void)sprintf(s, "PD%d,%d;XT;\n", xscale(x), yscale(ylow));
- sends(s);
- }
- (void)sprintf(s, "PD%d,%d;\n", xscale(xhigh), yscale(ylow));
- sends(s);
-
- /* draw y-axis with y-tick marks
- */
- (void)sprintf(s, "PU%d,%d;\n",
- xscale(xlow), yscale(ylow));
- sends(s);
- for (ny=0, y = ylow;
- y < yhigh + yincr/100.0;
- y += yincr, ny++) {
- (void)sprintf(s, "PD%d,%d;YT;\n", xscale(xlow), yscale(y));
- sends(s);
- }
- (void)sprintf(s, "PD%d,%d;\n", xscale(xlow), yscale(yhigh));
- sends(s);
-
- /* outer borders of the box
- */
- (void)sprintf(s, "PU%d,%d;PD%d,%d,%d,%d;PU\n",
- xscale(xlow), yscale(yhigh),
- xscale(xhigh), yscale(yhigh),
- xscale(xhigh), yscale(ylow));
- sends(s);
- break;
- #ifdef GL_LIB
- #define GL_TIC_SIZE 200
- case SCREEN:
- iy = yscale(ylow);
- n_movepen(xscale(xlow), iy);
-
- for (nx=0, x = xlow;
- x < xhigh + xincr/100.0;
- x += xincr, nx++) {
- ix = xscale(x);
- n_draw(ix, iy);
- n_line(ix, iy+GL_TIC_SIZE, ix, iy-GL_TIC_SIZE);
- n_movepen(ix, iy);
- }
- n_draw(xscale(xhigh), iy);
-
- /* draw y-axis with y-tick marks
- */
- ix = xscale(xlow);
- n_movepen(ix, yscale(ylow));
- for (ny=0, y = ylow;
- y < yhigh + yincr/100.0;
- y += yincr, ny++) {
- iy = yscale(y);
- n_draw(ix, iy);
- n_line(ix+GL_TIC_SIZE, iy, ix-GL_TIC_SIZE, iy);
- n_movepen(ix, iy);
- }
- n_draw(ix, yscale(yhigh));
-
- /* outer borders of the box
- */
- n_movepen(xscale(xlow), yscale(yhigh));
- n_draw(xscale(xhigh), yscale(yhigh));
- n_draw(xscale(xhigh), yscale(ylow));
- break;
- #endif
- #ifdef PLOT
- #define PLOT_TIC_SIZE 40
- case PLOTLIB:
- iy = yscale(ylow);
- move(xscale(xlow), iy);
-
- for (nx=0, x = xlow;
- x < xhigh + xincr/100.0;
- x += xincr, nx++) {
- ix = xscale(x);
- cont(ix, iy);
- line(ix, iy+PLOT_TIC_SIZE, ix, iy-PLOT_TIC_SIZE);
- move(ix, iy);
- }
- cont(xscale(xhigh), iy);
-
- /* draw y-axis with y-tick marks
- */
- ix = xscale(xlow);
- move(ix, yscale(ylow));
- for (ny=0, y = ylow;
- y < yhigh + yincr/100.0;
- y += yincr, ny++) {
- iy = yscale(y);
- cont(ix, iy);
- line(ix+PLOT_TIC_SIZE, iy, ix-PLOT_TIC_SIZE, iy);
- move(ix, iy);
- }
- cont(ix, yscale(yhigh));
-
- /* outer borders of the box
- */
- move(xscale(xlow), yscale(yhigh));
- cont(xscale(xhigh), yscale(yhigh));
- cont(xscale(xhigh), yscale(ylow));
- break;
- #endif
- default:
- invdev(); break;
- }
-
-
- /* put y-units
- */
- for (i=ny-1; i>=0; i--) {
- (void)sprintf(units, "%g", ylow + i * yincr);
- dr_put_text(xlow, ylow+i*yincr,
- -strlen(units)/2.0, -1.3, -M_PI_2, 1.0, units);
- }
-
- /* put x-units
- */
- for (i=0; i<nx; i++) {
- (void)sprintf(units, "%g", xlow + i * xincr);
- dr_put_text(xlow+i*xincr, ylow,
- -strlen(units)/2.0, -1.3, 0.0, 1.0, units);
- }
- return;
- }
-
- /*
- * linetypes
- *
- */
- #ifdef GL_LIB
- static long gl_line_types[] = { /* 76543210765432107654321076543210 */
- 0xf0000000L, /* ====............................ */
- 0xffff0000L, /* ================................ */
- 0xffffff00L, /* ========================........ */
- 0xffffff18L, /* ========================...==... */
- 0xfffff0f0L, /* ====================....====.... */
- 0xfffff39cL, /* ====================..===..===.. */
- 0xffffffffL, /* ================================ */
- 0x66666666L, /* ==..==..==..==..==..==..==..==.. */
- 0xf8f8f8f8L, /* =====...=====...=====...=====... */
- 0xffffff00L, /* ========================........ */
- 0xfc30fc30L }; /* ======....==....======....==.... */
- #define DEF_GL_TYPE 7 /* this will produce continous line */
- #endif /* GL_PLOT */
- #ifdef PLOT
- static char *plot_line_types[] = {
- "dotted", /* 1 */
- "longdashed", /* 2 */
- "shortdashed", /* 3 */
- "dotdashed", /* 4 */
- "solid", /* 5 */
- "solid", /* 6 */
- "solid" }; /* 7 */
- #define DEF_PLOT_TYPE 7 /* this will produce continous line */
- #endif /* PLOT */
-
- int dr_set_ltype(linetype)
- int linetype;
- {
- char s[40];
- int old_val = old_linetype;
-
- switch (device)
- {
- case HP7475:
- if (linetype < 0 || linetype > 6) {
- linetype = 7;
- sends("LT;");
- }
- else {
- (void)sprintf(s, "LT%d;", linetype);
- sends(s);
- }
- break;
- #ifdef GL_LIB
- case SCREEN:
- if (linetype < 1 ||
- linetype > (sizeof(gl_line_types) / sizeof(gl_line_types[0]))) {
- sprintf (s, "Invalid linetype: %d", linetype);
- dr_errmsg(s);
- linetype = DEF_GL_TYPE;
- }
- g_style(gl_line_types[linetype-1]);
- break;
- #endif
- #ifdef PLOT
- case PLOTLIB:
- if (linetype < 1 ||
- linetype > (sizeof(plot_line_types) /
- sizeof(plot_line_types[0]))) {
- sprintf (s, "Invalid linetype: %d", linetype);
- dr_errmsg(s);
- linetype = DEF_PLOT_TYPE;
- }
- linemod(plot_line_types[linetype-1]);
- break;
- #endif
- default:
- invdev(); break;
- }
- old_linetype = linetype;
- return old_val;
- }
-
- /*
- * xscale - scaling in horizontal directon
- *
- * convert user x-coordinate to physical device x-coordinate
- */
- static int xscale(x)
- float x;
- {
- int temp;
- char s[60];
-
- /* calculate it
- */
- temp = (int) ((x - xuserlow) * xfactor + xdevicelow + 0.5);
- /* check, if it is good
- */
- if ((temp >= -32768) && (temp <= 32767))
- return (temp);
-
- /* when not good make report,
- * return something
- */
- (void)sprintf(s, "x-value out of range: %f", x);
- dr_warnmsg(s);
- return (int) (xdevicelow + 0.5);
- }
-
-
- /*
- * yscale - scaling in vertical directon
- *
- * convert user y-coordinate to physical device y-coordinate
- */
- static int yscale(y)
- float y;
- {
- int temp;
- char s[60];
-
- /* calculate it
- */
- temp = (int) ((y - yuserlow) * yfactor + ydevicelow + 0.5);
-
- /* check, if it is good
- */
- if ((temp >= -32768) && (temp <= 32767))
- return (temp);
-
- /* when not good make report,
- * return something
- */
- (void)sprintf(s, "y-value out of range: %f", y);
- dr_warnmsg(s);
- return (int) (ydevicelow + 0.5);
- }
-
- static void invdev()
- {
- dr_errmsg("Invalid plotting device.");
- (void)dr_finish();
- exit(1);
- }
-
-
- /*
- * dr_errmsg - send a string to error output
- *
- */
- void dr_errmsg(s)
- char *s;
- {
- char *p = s + strlen(s);
- if (p != s) p--;
- while ((p != s) && (*p == '\n')) /* strip the newlines */
- *(p--) = '\0';
- fprintf(errfilefp, "dr_lib error: %s\n", s);
- errcount++;
- return;
- }
-
-
- /*
- * warnmsg - send a string to error output
- *
- */
- void dr_warnmsg(s)
- char *s;
- {
- char *p = s + strlen(s);
- if (p != s) p--;
- while ((p != s) && (*p == '\n')) *(p--) = '\0';
- fprintf(errfilefp, "Warning: %s\n", s);
- warncount++;
- return;
- }
-
-
- /*
- * sends - send something to plotting device
- *
- */
- static void sends(s)
- char *s;
- {
- (void)printf("%s", s);
- }
-
- #ifdef ASK
- /*
- * takes - take a string from plotter (to read plotter coordinates)
- *
- */
- #include <signal.h>
- #include <setjmp.h>
-
- jmp_buf sjbuf;
- int (*savAlrm)(); /* save incomming alarm function */
-
- static int timerh() /* timer interrupt handler */
- {
- longjmp(sjbuf, 1);
- }
-
- static void takes(s)
- char *s;
- {
- #ifdef YCABLE
- savAlrm = signal(SIGALRM,timerh);
- alarm(2); /* give time to wake up */
- if (setjmp(sjbuf)) {
- alarm(0);
- signal(SIGALRM,savAlrm); /* cancel timer */
- (void)dr_finish();
- (void)fprintf(stderr, "\n\7Timeout reading stdin. Aborting.\n");
- exit(1);
- }
- gets(s);
- alarm(0);
- signal(SIGALRM,savAlrm); /* cancel timer */
- #else
- /* do it yorself */
- #endif
- }
- #endif /* ASK */
-