/* plctrl.c Misc. control routines, like begin, end, exit, change graphics/text mode, change color. Includes some spillage from plcore.c. If you don't know where it should go, put it here. */ #define DEBUG #define ifset(s) (s ? s : "") #define ifsetu(s) (s ? s : (unsigned char*) "") #include "plplotP.h" #ifdef __GO32__ /* dos386/djgpp */ #ifdef __unix #undef __unix #endif #endif #ifdef __unix #ifdef HAVE_UNISTD_H #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #include #endif #include #include #include #endif /* Static functions */ static void strcat_delim(char *dirspec); static int (*exit_handler) (char *errormsg); static void plcmap0_def(int imin, int imax); static void plcmap1_def(void); /* An additional hardwired location for lib files. */ /* I have no plans to change these again, ever. */ #if defined(AMIGA) #ifndef PLLIBDEV #define PLLIBDEV "plplot:lib" #endif #elif defined(GNU386) #ifndef PLLIBDEV #define PLLIBDEV "c:/plplot/lib" #endif #elif defined(MSDOS) #ifndef PLLIBDEV #define PLLIBDEV "c:\\plplot\\lib" #endif #else /* Anything else is assumed to be Unix */ #ifndef PLLIBDEV #define PLLIBDEV "/usr/local/plplot/lib" #endif #endif /*--------------------------------------------------------------------------*\ * pldebug() * * Included into every plplot source file to control debugging output. To * enable printing of debugging output, you must #define DEBUG before * including plplotP.h or specify -DDEBUG in the compile line. When running * the program you must in addition specify -debug. This allows debugging * output to be available when asked for. * * Syntax: * pldebug(function_name, format, arg1, arg2...); \*--------------------------------------------------------------------------*/ static void pldebug( const char *fname, ... ) { #ifdef DEBUG va_list args; if (plsc->debug) { c_pltext(); va_start(args, fname); /* print out name of caller and source file */ (void) fprintf(stderr, "%s (%s): ", fname, __FILE__); /* print out remainder of message */ (void) vfprintf(stderr, (char *) va_arg(args, char *), args); va_end(args); c_plgra(); } #endif } /*--------------------------------------------------------------------------*\ * Routines that deal with colors & color maps. \*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*\ * plcol0() * * Set color, map 0. Argument is integer between 0 and plsc->ncol0. \*--------------------------------------------------------------------------*/ void c_plcol0(PLINT icol0) { if (plsc->level < 1) { plabort("plcol0: Please call plinit first"); return; } if (icol0 < 0 || icol0 >= plsc->ncol0) { plabort("plcol0: Invalid color."); return; } plsc->icol0 = icol0; plsc->curcolor.r = plsc->cmap0[icol0].r; plsc->curcolor.g = plsc->cmap0[icol0].g; plsc->curcolor.b = plsc->cmap0[icol0].b; plsc->curcmap = 0; plP_state(PLSTATE_COLOR0); } /*--------------------------------------------------------------------------*\ * plcol1() * * Set color, map 1. Argument is a float between 0. and 1. \*--------------------------------------------------------------------------*/ void c_plcol1(PLFLT col1) { PLINT icol1; if (plsc->level < 1) { plabort("plcol1: Please call plinit first"); return; } if (col1 < 0 || col1 > 1) { plabort("plcol1: Invalid color."); return; } icol1 = col1 * plsc->ncol1; icol1 = MIN(icol1, plsc->ncol1-1); plsc->icol1 = icol1; plsc->curcolor.r = plsc->cmap1[plsc->icol1].r; plsc->curcolor.g = plsc->cmap1[plsc->icol1].g; plsc->curcolor.b = plsc->cmap1[plsc->icol1].b; plsc->curcmap = 1; plP_state(PLSTATE_COLOR1); } /*--------------------------------------------------------------------------*\ * plscolbg() * * Set the background color (cmap0[0]) by 8 bit RGB value \*--------------------------------------------------------------------------*/ void c_plscolbg(PLINT r, PLINT g, PLINT b) { plscol0(0, r, g, b); } /*--------------------------------------------------------------------------*\ * plgcolbg() * * Returns the background color (cmap0[0]) by 8 bit RGB value \*--------------------------------------------------------------------------*/ void c_plgcolbg(PLINT *r, PLINT *g, PLINT *b) { plgcol0(0, r, g, b); } /*--------------------------------------------------------------------------*\ * plscol0() * * Set a given color from color map 0 by 8 bit RGB value * Does not result in any additional cells to be allocated. \*--------------------------------------------------------------------------*/ void c_plscol0(PLINT icol0, PLINT r, PLINT g, PLINT b) { if (plsc->cmap0 == NULL) plscmap0n(0); if (icol0 < 0 || icol0 >= plsc->ncol0) { plabort("plscol0: Illegal color table value"); return; } if ((r < 0 || r > 255) || (g < 0 || g > 255) || (b < 0 || b > 255)) { plabort("plscol0: Invalid color"); return; } plsc->cmap0[icol0].r = r; plsc->cmap0[icol0].g = g; plsc->cmap0[icol0].b = b; if (plsc->level > 0) plP_state(PLSTATE_CMAP0); } /*--------------------------------------------------------------------------*\ * plgcol0() * * Returns 8 bit RGB values for given color from color map 0 * Values are negative if an invalid color id is given \*--------------------------------------------------------------------------*/ void c_plgcol0(PLINT icol0, PLINT *r, PLINT *g, PLINT *b) { if (plsc->cmap0 == NULL) plscmap0n(0); *r = -1; *g = -1; *b = -1; if (icol0 < 0 || icol0 > plsc->ncol0) { plabort("plgcol0: Invalid color index"); return; } *r = plsc->cmap0[icol0].r; *g = plsc->cmap0[icol0].g; *b = plsc->cmap0[icol0].b; return; } /*--------------------------------------------------------------------------*\ * plscmap0() * * Set color map 0 colors by 8 bit RGB values. This sets the entire color * map -- only as many colors as specified will be allocated. \*--------------------------------------------------------------------------*/ void c_plscmap0(PLINT *r, PLINT *g, PLINT *b, PLINT ncol0) { int i; plscmap0n(ncol0); for (i = 0; i < plsc->ncol0; i++) { if ((r[i] < 0 || r[i] > 255) || (g[i] < 0 || g[i] > 255) || (b[i] < 0 || b[i] > 255)) { (void) fprintf(stderr, "plscmap0: Invalid RGB color: %d, %d, %d\n", (int) r[i], (int) g[i], (int) b[i]); plabort("plscmap0: Invalid color"); return; } plsc->cmap0[i].r = r[i]; plsc->cmap0[i].g = g[i]; plsc->cmap0[i].b = b[i]; } if (plsc->level > 0) plP_state(PLSTATE_CMAP0); } /*--------------------------------------------------------------------------*\ * plscmap1() * * Set color map 1 colors by 8 bit RGB values * This also sets the number of colors. \*--------------------------------------------------------------------------*/ void c_plscmap1(PLINT *r, PLINT *g, PLINT *b, PLINT ncol1) { int i; plscmap1n(ncol1); for (i = 0; i < plsc->ncol1; i++) { if ((r[i] < 0 || r[i] > 255) || (g[i] < 0 || g[i] > 255) || (b[i] < 0 || b[i] > 255)) { (void) fprintf(stderr, "plscmap1: Invalid RGB color: %d, %d, %d\n", (int) r[i], (int) g[i], (int) b[i]); plabort("plscmap1: Invalid color"); return; } plsc->cmap1[i].r = r[i]; plsc->cmap1[i].g = g[i]; plsc->cmap1[i].b = b[i]; } if (plsc->level > 0) plP_state(PLSTATE_CMAP1); } /*--------------------------------------------------------------------------*\ * plscmap1l() * * Set color map 1 colors using a piece-wise linear relationship between * position in the color map (from 0 to 1) and position in HLS or RGB color * space. May be called at any time. * * The idea here is to specify a number of control points that specify the * mapping between HLS (or RGB or CMY) and palette 1 value. Between these * points, linear interpolation is used. By mapping position in the color * map to function value, this gives a smooth variation of color with * intensity. Any number of control points may be specified, located at * arbitrary positions (intensities), although typically 2 - 4 are enough. * Another way of stating this is that we are traversing a given number of * lines through HLS (or RGB) space as we move through cmap 1 entries. The * control points at the minimum and maximum intensity (0 and 1) must * always be specified. By adding more control points you can get more * variation. One good technique for plotting functions that vary about * some expected average is to use an additional 2 control points in the * center (intensity ~= 0.5) that are the same color as the background * (typically white for paper output, black for crt), and same hue as the * boundary control points. This allows the highs and lows to be very * easily distinguished. * * Each control point must specify the position in cmap 1 as well as three * coordinates in HLS or RGB space. The first point MUST correspond to * position = 0, and the last to position = 1. * * The hue is interpolated around the "front" of the color wheel * (red<->green<->blue<->red) unless the "rev" flag is set, in which case * interpolation proceeds around the back (reverse) side. Specifying * rev=NULL is equivalent to setting rev[]=0 for every control point. * * Bounds on RGB coordinates: * R,G,B [0, 1] magnitude * * Bounds on HLS coordinates: * hue [0, 360] degrees * lightness [0, 1] magnitude * saturation [0, 1] magnitude * * The inputs are: * itype 0: HLS, 1: RGB * npts number of control points * pos[] position for each control point * coord1[] first coordinate for each control point * coord2[] second coordinate for each control point * coord3[] third coordinate for each control point * rev[] reverse flag for each control point \*--------------------------------------------------------------------------*/ void c_plscmap1l(PLINT itype, PLINT npts, PLFLT *pos, PLFLT *coord1, PLFLT *coord2, PLFLT *coord3, PLINT *rev) { int n; PLFLT h, l, s, r, g, b; if (npts < 2) { plabort("plscmap1l: Must specify at least two control points"); return; } if ( (pos[0] != 0) || (pos[npts-1] != 1)) { plabort("plscmap1l: First, last control points must lie on boundary"); return; } if ( npts > 32 ) { plabort("plscmap1l: Maximum of 32 control points allowed"); return; } /* Allocate if not done yet */ if (plsc->cmap1 == NULL) plscmap1n(0); /* Save control points */ plsc->ncp1 = npts; for (n = 0; n < npts; n++) { if (itype == 0) { h = coord1[n]; l = coord2[n]; s = coord3[n]; } else { r = coord1[n]; g = coord2[n]; b = coord3[n]; plRGB_HLS(r, g, b, &h, &l, &s); } plsc->cmap1cp[n].h = h; plsc->cmap1cp[n].l = l; plsc->cmap1cp[n].s = s; plsc->cmap1cp[n].p = pos[n]; if (rev == NULL) plsc->cmap1cp[n].rev = 0; else plsc->cmap1cp[n].rev = rev[n]; } /* Calculate and set color map */ plcmap1_calc(); } /*--------------------------------------------------------------------------*\ * plcmap1_calc() * * Bin up cmap 1 space and assign colors to make inverse mapping easy. * Always do interpolation in HLS space. \*--------------------------------------------------------------------------*/ void plcmap1_calc(void) { int i, n; PLFLT delta, dp, dh, dl, ds; PLFLT h, l, s, p, r, g, b; /* Loop over all control point pairs */ for (n = 0; n < plsc->ncp1-1; n++) { if ( plsc->cmap1cp[n].p == plsc->cmap1cp[n+1].p ) continue; /* Differences in p, h, l, s between ctrl pts */ dp = plsc->cmap1cp[n+1].p - plsc->cmap1cp[n].p; dh = plsc->cmap1cp[n+1].h - plsc->cmap1cp[n].h; dl = plsc->cmap1cp[n+1].l - plsc->cmap1cp[n].l; ds = plsc->cmap1cp[n+1].s - plsc->cmap1cp[n].s; /* Adjust dh if we are to go around "the back side" */ if (plsc->cmap1cp[n].rev) dh = (dh > 0) ? dh-360 : dh+360; /* Loop over all color cells. Only interested in cells located (in */ /* cmap1 space) between n_th and n+1_th control points */ for (i = 0; i < plsc->ncol1; i++) { p = (double) i / (plsc->ncol1 - 1.0); if ( (p < plsc->cmap1cp[n].p) || (p > plsc->cmap1cp[n+1].p) ) continue; /* Interpolate based on position of color cell in cmap1 space */ delta = (p - plsc->cmap1cp[n].p) / dp; /* Linearly interpolate to get color cell h, l, s values */ h = plsc->cmap1cp[n].h + dh * delta; l = plsc->cmap1cp[n].l + dl * delta; s = plsc->cmap1cp[n].s + ds * delta; while (h >= 360.) h -= 360.; while (h < 0.) h += 360.; plHLS_RGB(h, l, s, &r, &g, &b); plsc->cmap1[i].r = MAX(0, MIN(255, (int) (256. * r))); plsc->cmap1[i].g = MAX(0, MIN(255, (int) (256. * g))); plsc->cmap1[i].b = MAX(0, MIN(255, (int) (256. * b))); } } if (plsc->level > 0) plP_state(PLSTATE_CMAP1); } /*--------------------------------------------------------------------------*\ * plscmap0n() * * Set number of colors in cmap 0, (re-)allocate cmap 0, and fill with * default values for those colors not previously allocated (and less * than index 15, after that you just get grey). * * The driver is not guaranteed to support all of these. \*--------------------------------------------------------------------------*/ void c_plscmap0n(PLINT ncol0) { int ncol, size, imin, imax; /* No change */ if (ncol0 > 0 && plsc->ncol0 == ncol0) return; /* Handle all possible startup conditions */ if (plsc->ncol0 <= 0 && ncol0 <= 0) ncol = 16; else if (ncol0 <= 0) ncol = plsc->ncol0; else ncol = ncol0; imax = ncol-1; size = ncol * sizeof(PLColor); /* Allocate the space */ if (plsc->cmap0 == NULL) { plsc->cmap0 = (PLColor *) calloc(1, size); imin = 0; } else { plsc->cmap0 = (PLColor *) realloc(plsc->cmap0, size); imin = plsc->ncol0; } /* Fill in default entries */ plsc->ncol0 = ncol; plcmap0_def(imin, imax); } /*--------------------------------------------------------------------------*\ * plscmap1n() * * Set number of colors in cmap 1, (re-)allocate cmap 1, and set default * values if this is the first allocation. * * Note that the driver is allowed to disregard this number. * In particular, most use fewer than we use internally. \*--------------------------------------------------------------------------*/ void c_plscmap1n(PLINT ncol1) { int ncol, size; /* No change */ if (ncol1 > 0 && plsc->ncol1 == ncol1) return; /* Handle all possible startup conditions */ if (plsc->ncol1 <= 0 && ncol1 <= 0) ncol = 128; else if (ncol1 <= 0) ncol = plsc->ncol1; else ncol = ncol1; size = ncol * sizeof(PLColor); /* Allocate the space */ if (plsc->ncol1 > 0) plsc->cmap1 = (PLColor *) realloc(plsc->cmap1, size); else plsc->cmap1 = (PLColor *) calloc(ncol, sizeof(PLColor)); /* Fill in default entries */ plsc->ncol1 = ncol; if (plsc->ncp1 == 0) plcmap1_def(); else plcmap1_calc(); } /*--------------------------------------------------------------------------*\ * color_set() * * Initializes color table entry by RGB values. \*--------------------------------------------------------------------------*/ static void color_set(PLINT i, U_CHAR r, U_CHAR g, U_CHAR b) { plsc->cmap0[i].r = r; plsc->cmap0[i].g = g; plsc->cmap0[i].b = b; } /*--------------------------------------------------------------------------*\ * plcmap0_def() * * Initializes specified color map 0 color entry to its default. * * Initial RGB values for color map 0 taken from HPUX 8.07 X-windows * rgb.txt file, and may not accurately represent the described colors on * all systems. \*--------------------------------------------------------------------------*/ #define color_def(i, r, g, b) \ if (i >= imin && i <= imax) color_set(i, r, g, b); static void plcmap0_def(int imin, int imax) { int i; color_def(0, 0, 0, 0); /* black */ color_def(1, 255, 0, 0); /* red */ color_def(2, 255, 255, 0); /* yellow */ color_def(3, 0, 255, 0); /* green */ color_def(4, 50, 191, 193); /* aquamarine */ color_def(5, 255, 181, 197); /* pink */ color_def(6, 245, 222, 179); /* wheat */ color_def(7, 126, 126, 126); /* grey */ color_def(8, 165, 42, 42); /* brown */ color_def(9, 0, 0, 255); /* blue */ color_def(10, 138, 43, 226); /* Blue Violet */ color_def(11, 0, 255, 255); /* cyan */ color_def(12, 25, 204, 223); /* turquoise */ color_def(13, 255, 0, 255); /* magenta */ color_def(14, 233, 150, 122); /* salmon */ color_def(15, 255, 255, 255); /* white */ /* Any others are just arbitrarily set */ for (i = 16; i <= imax; i++) color_def(i, 255, 0, 0); /* red */ } /*--------------------------------------------------------------------------*\ * plcmap1_def() * * Initializes color map 1. * * The default initialization uses 4 control points in HLS space, the two * inner ones being very close to one of the vertices of the HLS double * cone. The vertex used (black or white) is chosen to be the closer to * the background color. If you don't like these settings you can always * initialize it yourself. \*--------------------------------------------------------------------------*/ static void plcmap1_def(void) { PLFLT i[4], h[4], l[4], s[4], vertex = 0.; /* Positions of control points */ i[0] = 0; /* left boundary */ i[1] = 0.45; /* just before center */ i[2] = 0.55; /* just after center */ i[3] = 1; /* right boundary */ /* For center control points, pick black or white, whichever is closer to bg */ /* Be carefult to pick just short of top or bottom else hue info is lost */ if (plsc->cmap0 != NULL) vertex = ((float) plsc->cmap0[0].r + (float) plsc->cmap0[0].g + (float) plsc->cmap0[0].b) / 3. / 255.; if (vertex < 0.5) vertex = 0.01; else vertex = 0.99; /* Set hue */ h[0] = 260; /* low: blue-violet */ h[1] = 260; /* only change as we go over vertex */ h[2] = 0; /* high: red */ h[3] = 0; /* keep fixed */ /* Set lightness */ l[0] = 0.5; /* low */ l[1] = vertex; /* bg */ l[2] = vertex; /* bg */ l[3] = 0.5; /* high */ /* Set saturation -- keep at maximum */ s[0] = 1; s[1] = 1; s[2] = 1; s[3] = 1; c_plscmap1l(0, 4, i, h, l, s, NULL); } /*--------------------------------------------------------------------------*\ * plscolor() * * Used to globally turn color output on/off \*--------------------------------------------------------------------------*/ void c_plscolor(PLINT color) { plsc->colorset = 1; plsc->color = color; } /*--------------------------------------------------------------------------*\ * plrgb() * * Set line color by red, green, blue from 0. to 1. * Do NOT use this. Only retained for backward compatibility \*--------------------------------------------------------------------------*/ void c_plrgb(PLFLT r, PLFLT g, PLFLT b) { if (plsc->level < 1) { plabort("plrgb: Please call plinit first"); return; } plsc->icol0 = PL_RGB_COLOR; plsc->curcolor.r = MAX(0, MIN(255, (int) (256. * r))); plsc->curcolor.g = MAX(0, MIN(255, (int) (256. * g))); plsc->curcolor.b = MAX(0, MIN(255, (int) (256. * b))); plsc->curcmap = 0; plP_state(PLSTATE_COLOR0); } /*--------------------------------------------------------------------------*\ * plrgb1() * * Set line color by 8 bit RGB values. * Do NOT use this. Only retained for backward compatibility \*--------------------------------------------------------------------------*/ void c_plrgb1(PLINT r, PLINT g, PLINT b) { if (plsc->level < 1) { plabort("plrgb1: Please call plinit first"); return; } if ((r < 0 || r > 255) || (g < 0 || g > 255) || (b < 0 || b > 255)) { plabort("plrgb1: Invalid color"); return; } plsc->icol0 = PL_RGB_COLOR; plsc->curcolor.r = r; plsc->curcolor.g = g; plsc->curcolor.b = b; plsc->curcmap = 0; plP_state(PLSTATE_COLOR0); } /*--------------------------------------------------------------------------*\ * void plhls() * * Set current color by hue, lightness, and saturation. * Convert hls color coordinates to rgb, then call plrgb. * Do NOT use this. Only retained for backward compatibility \*--------------------------------------------------------------------------*/ void c_plhls(PLFLT h, PLFLT l, PLFLT s) { PLFLT r, g, b; plHLS_RGB(h, l, s, &r, &g, &b); plrgb(r, g, b); } /*--------------------------------------------------------------------------*\ * void value() * * Auxiliary function used by plHLS_RGB(). \*--------------------------------------------------------------------------*/ static float value(double n1, double n2, double hue) { float val; while (hue >= 360.) hue -= 360.; while (hue < 0.) hue += 360.; if (hue < 60.) val = n1 + (n2 - n1) * hue / 60.; else if (hue < 180.) val = n2; else if (hue < 240.) val = n1 + (n2 - n1) * (240. - hue) / 60.; else val = n1; return (val); } /*--------------------------------------------------------------------------*\ * void plHLS_RGB() * * Convert HLS color to RGB color. * Bounds on HLS (input): * hue [0., 360.] degrees * lightness [0., 1.] magnitude * saturation [0., 1.] magnitude * * Hue is always mapped onto the interval [0., 360.] regardless of input. * Bounds on RGB (output) is always [0., 1.]. Convert to RGB color values * by multiplying by 2**nbits (nbits typically 8). \*--------------------------------------------------------------------------*/ void plHLS_RGB(PLFLT h, PLFLT l, PLFLT s, PLFLT *p_r, PLFLT *p_g, PLFLT *p_b) { float m1, m2; if (l <= .5) m2 = l * (s + 1.); else m2 = l + s - l * s; m1 = 2 * l - m2; *p_r = value(m1, m2, h + 120.); *p_g = value(m1, m2, h); *p_b = value(m1, m2, h - 120.); } /*--------------------------------------------------------------------------*\ * void plRGB_HLS() * * Convert RGB color to HLS color. * Bounds on RGB (input) is always [0., 1.]. * Bounds on HLS (output): * hue [0., 360.] degrees * lightness [0., 1.] magnitude * saturation [0., 1.] magnitude \*--------------------------------------------------------------------------*/ void plRGB_HLS(PLFLT r, PLFLT g, PLFLT b, PLFLT *p_h, PLFLT *p_l, PLFLT *p_s) { PLFLT h, l, s, d, rc, gc, bc, rgb_min, rgb_max; rgb_min = MIN( r, MIN( g, b )); rgb_max = MAX( r, MAX( g, b )); l = (rgb_min+rgb_max) / 2.0; if (rgb_min == rgb_max) { s = 0; h = 0; } else { d = rgb_max - rgb_min; if (l < 0.5) s = 0.5 * d / l; else s = 0.5* d / (1.-l); rc = (rgb_max-r) / d; gc = (rgb_max-g) / d; bc = (rgb_max-b) / d; if (r == rgb_max) h = bc-gc; else if (g == rgb_max) h = rc-bc+2; else h = gc-rc-2; h = h*60; if (h < 0) h = h+360; else if (h >= 360) h = h-360; } *p_h = h; *p_l = l; *p_s = s; } /*--------------------------------------------------------------------------*\ * A grab-bag of various control routines. \*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*\ * void plwarn() * * A handy way to issue warnings, if need be. \*--------------------------------------------------------------------------*/ void plwarn(char *errormsg) { int was_gfx = 0; if (plsc->graphx == 1) { was_gfx = 1; pltext(); } (void) fprintf(stderr, "\n*** PLPLOT WARNING ***\n"); if (*errormsg != '\0') (void) fprintf(stderr, "%s\n", errormsg); if (was_gfx == 1) plgra(); } /*--------------------------------------------------------------------------*\ * void plabort() * * Much the same as plwarn(), but appends ", aborting operation" to the * error message. Helps to keep source code uncluttered and provides a * convention for error aborts. \*--------------------------------------------------------------------------*/ void plabort(char *errormsg) { if (plsc->errcode != NULL) *(plsc->errcode) = 1; if (plsc->errmsg != NULL) { (void) sprintf(plsc->errmsg, "\n*** PLPLOT ERROR ***\n"); if (*errormsg != '\0') (void) sprintf(plsc->errmsg, "%s, aborting operation\n", errormsg); } else { int was_gfx = 0; if (plsc->graphx == 1) { was_gfx = 1; pltext(); } (void) fprintf(stderr, "\n*** PLPLOT ERROR ***\n"); if (*errormsg != '\0') (void) fprintf(stderr, "%s, aborting operation\n", errormsg); if (was_gfx == 1) plgra(); } } /*--------------------------------------------------------------------------*\ * void plexit() * * In case of an abort this routine is called. It just prints out an error * message and tries to clean up as much as possible. It's best to turn * off pause and then restore previous setting before returning. * * If cleanup needs to be done in the main program, the user should write * his/her own exit handler and pass it in via plsexit(). This function * should should either call plend() before exiting, or simply return. \*--------------------------------------------------------------------------*/ void plexit(char *errormsg) { int status = 1; if (exit_handler != NULL) status = (*exit_handler)(errormsg); plsc->nopause = 1; plend(); if (*errormsg != '\0') { (void) fprintf(stderr, "\n*** PLPLOT ERROR ***\n"); (void) fprintf(stderr, "%s\n", errormsg); } (void) fprintf(stderr, "Program aborted\n"); exit(status); } /*--------------------------------------------------------------------------*\ * void plsexit() * * Sets an optional user exit handler. \*--------------------------------------------------------------------------*/ void plsexit(int (*handler) (char *)) { exit_handler = handler; } /*--------------------------------------------------------------------------*\ * void plgra() * * Switches to graphics screen. * * Here and in pltext() it's a good idea to return silently if plinit() * hasn't yet been called, since plwarn() calls pltext() and plgra(), and * plwarn() may be called at any time. \*--------------------------------------------------------------------------*/ void c_plgra(void) { if (plsc->level > 0) plP_esc(PLESC_GRAPH, NULL); } /*--------------------------------------------------------------------------*\ * void pltext() * * Switches to text screen. \*--------------------------------------------------------------------------*/ void c_pltext(void) { if (plsc->level > 0) plP_esc(PLESC_TEXT, NULL); } /*--------------------------------------------------------------------------*\ * void pl_cmd() * * Front-end to driver escape function. * In principle this can be used to pass just about anything directly * to the driver. \*--------------------------------------------------------------------------*/ void pl_cmd(PLINT op, void *ptr) { plP_esc(op, ptr); } /*--------------------------------------------------------------------------*\ * char *plFindCommand * * Looks for the specified executable file. Search path: * PLPLOT_BIN_ENV = $(PLPLOT_BIN) * current directory * PLPLOT_HOME_ENV/bin = $(PLPLOT_HOME)/bin * BIN_DIR * * The caller must free the returned pointer (points to malloc'ed memory) * when finished with it. \*--------------------------------------------------------------------------*/ char * plFindCommand(char *fn) { char *fs = NULL, *dn; /* PLPLOT_BIN_ENV = $(PLPLOT_BIN) */ #if defined(PLPLOT_BIN_ENV) if ((dn = getenv(PLPLOT_BIN_ENV)) != NULL) { plGetName(dn, "", fn, &fs); if ( ! plFindName(fs)) return fs; /* what IS set? */ (void) fprintf(stderr, PLPLOT_BIN_ENV"=\"%s\"\n", dn); } #endif /* PLPLOT_BIN_ENV */ /* Current directory */ plGetName(".", "", fn, &fs); if ( ! plFindName(fs)) return fs; /* PLPLOT_HOME_ENV/bin = $(PLPLOT_HOME)/bin */ #if defined(PLPLOT_HOME_ENV) if ((dn = getenv(PLPLOT_HOME_ENV)) != NULL) { plGetName(dn, "bin", fn, &fs); if ( ! plFindName(fs)) return fs; (void) fprintf(stderr, PLPLOT_HOME_ENV"=\"%s\"\n",dn); /* what IS set? */ } #endif /* PLPLOT_HOME_ENV */ /* BIN_DIR */ #if defined (BIN_DIR) plGetName(BIN_DIR, "", fn, &fs); if ( ! plFindName(fs)) return fs; #endif /* Crapped out */ free_mem(fs); (void) fprintf(stderr, "plFindCommand: cannot locate command: %s\n", fn); #if defined (BIN_DIR) (void) fprintf(stderr, "bin dir=\"" BIN_DIR "\"\n" ); /* what WAS set? */ #endif /* BIN_DIR */ return NULL; } /*--------------------------------------------------------------------------*\ * FILE *plLibOpen(fn) * * Return file pointer to lib file. * Locations checked: * PLPLOT_LIB_ENV = $(PLPLOT_LIB) * current directory * PLPLOT_HOME_ENV/lib = $(PLPLOT_HOME)/lib * LIB_DIR * PLLIBDEV \*--------------------------------------------------------------------------*/ FILE * plLibOpen(char *fn) { FILE *file; char *fs = NULL, *dn = NULL; /* EMBOSS additions to avoid need for PLPLOT_LIB */ static char *prefix = PREFIX; static char *top = EMBOSS_TOP; if(!strcmp(prefix,"/usr/local")) { plGetName(prefix, "share/EMBOSS", fn, &fs); if ((file = fopen(fs, "rb")) != NULL) goto done; plGetName(top, "plplot/lib", fn, &fs); if ((file = fopen(fs, "rb")) != NULL) goto done; } else { plGetName(prefix, "share/EMBOSS", fn, &fs); if ((file = fopen(fs, "rb")) != NULL) goto done; } /* End of EMBOSS additions */ /**** search PLPLOT_LIB_ENV = $(PLPLOT_LIB) ****/ #if defined(PLPLOT_LIB_ENV) if ((dn = getenv(PLPLOT_LIB_ENV)) != NULL) { plGetName(dn, "", fn, &fs); if ((file = fopen(fs, "rb")) != NULL) goto done; (void) fprintf(stderr, PLPLOT_LIB_ENV"=\"%s\"\n", dn); /* what IS set? */ } #endif /* PLPLOT_LIB_ENV */ /**** search current directory ****/ if ((file = fopen(fn, "rb")) != NULL) goto done; /**** search PLPLOT_HOME_ENV/lib = $(PLPLOT_HOME)/lib ****/ #if defined (PLPLOT_HOME_ENV) if ((dn = getenv(PLPLOT_HOME_ENV)) != NULL) { plGetName(dn, "lib", fn, &fs); if ((file = fopen(fs, "rb")) != NULL) goto done; (void) fprintf(stderr, PLPLOT_HOME_ENV"=\"%s\"\n",dn); /* what IS set? */ } #endif /* PLPLOT_HOME_ENV/lib */ /**** search installed location ****/ #if defined (LIB_DIR) plGetName(LIB_DIR, "", fn, &fs); if ((file = fopen(fs, "rb")) != NULL) goto done; #endif /* LIB_DIR */ /**** search hardwired location ****/ #ifdef PLLIBDEV plGetName(PLLIBDEV, "", fn, &fs); if ((file = fopen(fs, "rb")) != NULL) goto done; #endif /* PLLIBDEV */ /**** not found, give up ****/ pltext(); (void) fprintf(stderr, "\nCannot open library file: %s\n", fn); /*#if defined (LIB_DIR)*/ /*fprintf(stderr, "lib dir=\"" LIB_DIR "\"\n" ); */ /* what WAS set? */ /*#endif*/ /* LIB_DIR */ (void) fprintf(stderr, "\nPlease set PLPLOT_LIB to the plplot/lib directory under emboss\n"); plgra(); return NULL; done: free_mem(fs); return (file); } /*--------------------------------------------------------------------------*\ * int plFindName * * Authors: Paul Dubois (LLNL), others? * This function is in the public domain. * * Given a pathname, determine if it is a symbolic link. If so, continue * searching to the ultimate terminus - there may be more than one link. * Use the error value to determine when the terminus is reached, and to * determine if the pathname really exists. Then stat it to determine * whether it's executable. Return 0 for an executable, errno otherwise. * Note that 'p' _must_ have at least one '/' character - it does by * construction in this program. The contents of the array pointed to by * 'p' are changed to the actual pathname if findname is successful. * * This function is only defined under Unix for now. \*--------------------------------------------------------------------------*/ #ifdef __unix int plFindName(char *p) { int n; char buf[1024], *cp; extern int errno; struct stat sbuf; pldebug("plFindName", "Trying to find %s\n", p); while ((n = readlink(p, buf, 1024)) > 0) { pldebug("plFindName", "Readlink read %d chars at: %s\n", n, p); if (buf[0] == '/') { /* Link is an absolute path */ (void) strncpy(p, buf, n); p[n] = '\0'; pldebug("plFindName", "Link is absolute: %s\n", p); } else { /* Link is relative to its directory; make it absolute */ cp = 1 + strrchr(p, '/'); (void) strncpy(cp, buf, n); cp[n] = '\0'; pldebug("plFindName", "Link is relative: %s\n\tTotal path:%s\n", cp, p); } } /* This macro not defined on the NEC SX-3 */ #ifdef SX #define S_ISREG(mode) (mode & S_IFREG) #endif /* SGI machines return ENXIO instead of EINVAL Dubois 11/92 */ if (errno == EINVAL || errno == ENXIO) { pldebug("plFindName", "%s may be the one...\n", p); if ((stat(p, &sbuf) == 0) && S_ISREG(sbuf.st_mode)) { pldebug("plFindName", "%s is a regular file\n", p); return (access(p, X_OK)); } } pldebug("plFindName", "%s found but is not executable\n", p); return (errno ? errno : -1); } #else int plFindName(char *p) { return 1; } #endif /*--------------------------------------------------------------------------*\ * void plGetName() * * Gets search name for file by concatenating the dir, subdir, and file * name, allocating memory as needed. The appropriate delimiter is added * after the dir specification as necessary. The caller is responsible * for freeing the malloc'ed memory. \*--------------------------------------------------------------------------*/ void plGetName(char *dir, char *subdir, char *filename, char **filespec) { int lfilespec; /* Malloc space for filespec */ free_mem(*filespec); lfilespec = 10; lfilespec = strlen(dir) + strlen(subdir) + strlen(filename) + 10; *filespec = (char *) malloc(lfilespec); strcpy(*filespec, dir); if (*subdir != '\0') { strcat_delim(*filespec); (void) strcat(*filespec, subdir); } if (*filename != '\0') { strcat_delim(*filespec); (void) strcat(*filespec, filename); } } /*--------------------------------------------------------------------------*\ * void strcat_delim() * * Append path name deliminator if necessary (does not add one if one's * there already, or if dealing with a colon-terminated device name as * used on the Amiga). \*--------------------------------------------------------------------------*/ static void strcat_delim(char *dirspec) { int ldirspec = strlen(dirspec); #if defined (MSDOS) if (dirspec[ldirspec-1] != '\\') (void) strcat(dirspec, "\\"); #elif defined (AMIGA) if (dirspec[ldirspec-1] != '/' && dirspec[ldirspec-1] != ':') strcat(dirspec, "/"); #elif defined (VMS) #else /* unix is the default */ if (dirspec[ldirspec-1] != '/') (void) strcat(dirspec, "/"); #endif } /*--------------------------------------------------------------------------*\ * plcol_interp() * * Initializes device cmap 1 entry by interpolation from pls->cmap1 * entries. Returned PLColor is supposed to represent the i_th color * out of a total of ncol colors in the current color scheme. \*--------------------------------------------------------------------------*/ void plcol_interp(PLStream *pls, PLColor *newcolor, int i, int ncol) { float x, delta; int il, ir; x = (double) (i * (pls->ncol1-1)) / (double) (ncol-1); il = x; ir = il + 1; delta = x - il; if (ir > pls->ncol1 || il < 0) (void) fprintf(stderr, "Invalid color\n"); else if (ir == pls->ncol1 || (delta == 0.)) { newcolor->r = pls->cmap1[il].r; newcolor->g = pls->cmap1[il].g; newcolor->b = pls->cmap1[il].b; } else { newcolor->r = (1.-delta) * pls->cmap1[il].r + delta * pls->cmap1[ir].r; newcolor->g = (1.-delta) * pls->cmap1[il].g + delta * pls->cmap1[ir].g; newcolor->b = (1.-delta) * pls->cmap1[il].b + delta * pls->cmap1[ir].b; } } /*--------------------------------------------------------------------------*\ * plOpenFile() * * Opens file for output, prompting if not set. * Prints extra newline at end to make output look better in batch runs. * A file name of "-" indicates output to stdout. \*--------------------------------------------------------------------------*/ #define MAX_NUM_TRIES 10 void plOpenFile(PLStream *pls) { int i = 0, count = 0; size_t len; char line[256]; while (pls->OutFile == NULL) { /* Setting pls->FileName = NULL forces creation of a new family member */ /* You should also free the memory associated with it if you do this */ if (pls->family && pls->BaseName != NULL) plP_getmember(pls); /* Prompt if filename still not known */ if (pls->FileName == NULL) { do { (void) fprintf(stderr, "Enter graphics output file name: "); (void) fgets(line, sizeof(line), stdin); len = strlen(line); if (len) len--; line[len] = '\0'; /* strip new-line */ count++; /* count zero entries */ } while (!len && count < MAX_NUM_TRIES); plP_sfnam(pls, line); } /* If name is "-", send to stdout */ if ( ! strcmp(pls->FileName, "-")) { pls->OutFile = stdout; pls->output_type = 1; break; } /* Need this here again, for prompted family initialization */ if (pls->family && pls->BaseName != NULL) plP_getmember(pls); if (i++ > 10) plexit("Too many tries."); if ((pls->OutFile = fopen(pls->FileName, "wb+")) == NULL) (void) fprintf(stderr, "Can't open %s.\n", pls->FileName); /* silence this message - Peter Rice, 5-Apr-2002 */ /* // else // (void) fprintf(stdout, "Created %s\n", pls->FileName); */ } } /*--------------------------------------------------------------------------*\ * plP_getmember() * * Sets up next file member name (in pls->FileName), but does not open it. \*--------------------------------------------------------------------------*/ void plP_getmember(PLStream *pls) { char tmp[256]; if (pls->FileName == NULL) pls->FileName = (char *) malloc(10 + strlen(pls->BaseName) + strlen(pls->Ext)); (void) sprintf(tmp, "%s.%%0%1ii%s", pls->BaseName, (int) pls->fflen,pls->Ext); (void) sprintf(pls->FileName, tmp, pls->member); } /*--------------------------------------------------------------------------*\ * plP_sfnam() * * Sets up file name & family stem name. * Reserve some extra space (5 chars) to hold an optional member number. \*--------------------------------------------------------------------------*/ void plP_sfnam(PLStream *pls, const char *fnam) { pls->OutFile = NULL; if (pls->FileName != NULL) free((void *) pls->FileName); pls->FileName = (char *) malloc(10 + strlen(fnam)); (void) strcpy(pls->FileName, fnam); if (pls->BaseName != NULL) free((void *) pls->BaseName); pls->BaseName = (char *) malloc(10 + strlen(fnam)); (void) strcpy(pls->BaseName, fnam); } /*--------------------------------------------------------------------------*\ * plFamInit() * * Initializes family file parameters. \*--------------------------------------------------------------------------*/ void plFamInit(PLStream *pls) { if (pls->family) { pls->bytecnt = 0; if ( ! pls->member) pls->member = 1; if ( ! pls->finc) pls->finc = 1; if ( ! pls->fflen) pls->fflen = 1; if ( ! pls->bytemax) pls->bytemax = PL_FILESIZE_KB * 1000; } } /*--------------------------------------------------------------------------*\ * plGetFam() * * Starts new member file of family file set if necessary. * * Note each member file is a complete graphics file (can be printed * individually), although 'plrender' will treat a family as a single * logical file if given the family name instead of the member name. \*--------------------------------------------------------------------------*/ void plGetFam(PLStream *pls) { if (pls->family) { if (pls->bytecnt > pls->bytemax || pls->famadv) { plP_tidy(); pls->member += pls->finc; pls->famadv = 0; plP_init(); return; } } } /*--------------------------------------------------------------------------*\ * plRotPhy() * * Rotates physical coordinates if necessary for given orientation. * Each time orient is incremented, the plot is rotated 90 deg clockwise. * Note: this is now used only to rotate by 90 degrees for devices that * expect portrait mode. \*--------------------------------------------------------------------------*/ void plRotPhy(PLINT orient, PLINT xmin, PLINT ymin, PLINT xmax, PLINT ymax, int *px, int *py) { int x, y; x = *px; y = *py; switch (orient%4) { case 1: *px = xmin + (y - ymin); *py = ymin + (xmax - x); break; case 2: *px = xmin + (xmax - x); *py = ymin + (ymax - y); break; case 3: *px = xmin + (ymax - y); *py = ymin + (x - xmin); break; default: break; /* do nothing */ } } /*--------------------------------------------------------------------------*\ * plAllocDev() * * Allocates a standard PLDev structure for device-specific data, stores * the address in pls->dev, and returns the address as well. \*--------------------------------------------------------------------------*/ PLDev * plAllocDev(PLStream *pls) { if (pls->dev != NULL) free((void *) pls->dev); pls->dev = calloc(1, (size_t) sizeof(PLDev)); if (pls->dev == NULL) plexit("plAllocDev: cannot allocate memory\n"); return (PLDev *) pls->dev; } /*--------------------------------------------------------------------------*\ * plGinInit() * * Just fills in the PLGraphicsIn with appropriate initial values. \*--------------------------------------------------------------------------*/ void plGinInit(PLGraphicsIn *gin) { gin->type = 0; gin->state = 0; gin->keysym = 0; gin->button = 0; gin->string[0] = '\0'; gin->pX = gin->pY = -1; gin->dX = gin->dY = 0.; gin->wX = gin->wY = 0.; } /*--------------------------------------------------------------------------*\ * plGetInt() * * Prompts human to input an integer in response to given message. \*--------------------------------------------------------------------------*/ PLINT plGetInt(char *s) { int m; int i = 0; char line[256]; while (i++ < 10) { (void) fprintf(stderr, s); (void) fgets(line, sizeof(line), stdin); #ifdef MSDOS m = atoi(line); return (m); #else if (sscanf(line, "%d", &m) == 1) return (m); (void) fprintf(stderr, "No value or value out of range; please try again\n"); #endif } plexit("Too many tries."); return (0); } /*--------------------------------------------------------------------------*\ * plGetFlt() * * Prompts human to input a float in response to given message. \*--------------------------------------------------------------------------*/ PLFLT plGetFlt(char *s) { PLFLT m; int i = 0; char line[256]; while (i++ < 10) { (void) fprintf(stderr, s); (void) fgets(line, sizeof(line), stdin); #ifdef MSDOS m = atof(line); return (m); #else if (sscanf(line, "%f", &m) == 1) return (m); (void) fprintf(stderr, "No value or value out of range; please try again\n"); #endif } plexit("Too many tries."); return (0.); } void plPX_sfnam (PLStream* pls, const char* fnam, const char* ext) { pls->OutFile = NULL; if (pls->FileName != NULL) free((void *) pls->FileName); pls->FileName = (char *) malloc(10 + strlen(fnam) + strlen(ext)); (void) strcpy(pls->FileName, fnam); (void) strcpy(&pls->FileName[strlen(fnam)], ext); if (pls->BaseName != NULL) free((void *) pls->BaseName); pls->BaseName = (char *) malloc(10 + strlen(fnam)); (void) strcpy(pls->BaseName, fnam); if (pls->Ext != NULL) free((void *) pls->Ext); pls->Ext = (char *) malloc(10 + strlen(ext)); (void) strcpy(pls->Ext, ext); } void plPX_swin (PLStream* pls, const char* window) { if (pls->plwindow != NULL) free((void *) pls->plwindow); pls->plwindow = (char *) malloc(1 + strlen(window)); (void) strcpy(pls->plwindow, window); } void plPX_trace (PLStream *pls, FILE* outf) { int i; fprintf (outf, "\nPLPLOT INTERNALS TRACE\n"); fprintf (outf, "\nMisc control information\n"); fprintf (outf, "ipls %d > %s\n", pls->ipls, "Stream number"); fprintf (outf, "level %d > %s\n", pls->level, "Initialization level"); fprintf (outf, "verbose %d > %s\n", pls->verbose, "Be more verbose than usual"); fprintf (outf, "debug %d > %s\n", pls->debug, "Generate debugging output"); fprintf (outf, "initialized %d > %s\n", pls->initialized, "Set if the stream has been initialized"); fprintf (outf, "program '%s' > %s\n", ifset(pls->program), "Program name"); fprintf (outf, "\nColormaps\n"); fprintf (outf, "icol0 %3d > %s\n", pls->icol0, "Color map 0 entry, current color (0 <= icol0 <= ncol0)"); fprintf (outf, "ncol0 %3d > %s\n", pls->ncol0, "Number of colors allocated in color map 0."); fprintf (outf, "icol1 %3d > %s\n", pls->icol1, "Color map 1 entry, current color (0 <= icol1 <= ncol1)"); fprintf (outf, "ncol1 %3d > %s\n", pls->ncol1, "Number of colors allocated in color map 1."); fprintf (outf, "ncp1 %3d > %s\n", pls->ncp1, "Number of control points in cmap1 allocation (max 32)"); fprintf (outf, "curcmap %3d > %s\n", pls->curcmap, "Current color map"); fprintf (outf, "curcolor (%3d %3d %3d) RGB > %s\n", (int)pls->curcolor.r, (int)pls->curcolor.g, (int)pls->curcolor.b, "Current color"); fprintf (outf, "cmap0 %p > %s\n", pls->cmap0, "Color map 0: maximum of ncol0 RGB 8-bit values"); if (pls->cmap0) fprintf (outf, "cmap0 (%3d %3d %3d) RGB\n", (int) pls->cmap0->r, (int) pls->cmap0->g, (int) pls->cmap0->b); fprintf (outf, "cmap1 %p > %s\n", pls->cmap1, "Color map 1: maximum of ncol0 RGB 8-bit values"); if (pls->cmap1) fprintf (outf, "cmap1 (%3d %3d %3d) RGB\n", (int) pls->cmap1->r, (int) pls->cmap1->g, (int) pls->cmap1->b); for (i=0; i<32; i++) fprintf (outf, "cmap1cp[%d] hue %3f light %f sat %f pos %f rev %d\n", i, pls->cmap1cp[i].h, pls->cmap1cp[i].l, pls->cmap1cp[i].s, pls->cmap1cp[i].p, pls->cmap1cp[i].rev ); fprintf (outf, "\nVariables governing pen width\n"); fprintf (outf, "width %3d > %s\n", pls->width, "Current pen width"); fprintf (outf, "widthset %3d > %s\n", pls->widthset, "Set if pen width was specified"); fprintf (outf, "widthlock %3d > %s\n", pls->widthlock, "Set if pen width is locked"); fprintf (outf, "\nVariables used for interacting with or by device driver\n"); fprintf (outf, "plbuf_read %d > %s\n", pls->plbuf_read, "Set during a plot buffer redraw"); fprintf (outf, "plbuf_write %d > %s\n", pls->plbuf_write, "Set if driver needs to use the plot buffer"); fprintf (outf, "device %d > %s\n", pls->device, "Graphics device id number"); fprintf (outf, "dev_minor %d > %s\n", pls->dev_minor, "Minor device id (for variations on one type)"); fprintf (outf, "termin %d > %s\n", pls->termin, "Set for interactive devices"); fprintf (outf, "graphx %d > %s\n", pls->graphx, "Set if currently in graphics mode"); fprintf (outf, "nopause %d > %s\n", pls->nopause, "Set if we are skipping the pause between frames"); fprintf (outf, "family %d > %s\n", pls->family, "Set if familying is enabled"); fprintf (outf, "member %d > %s\n", pls->member, "Number of current family member file open"); fprintf (outf, "finc %d > %s\n", pls->finc, "Number to increment between member files"); fprintf (outf, "fflen %d > %s\n", pls->fflen, "Minimum field length to use in member file number"); fprintf (outf, "bytemax %d > %s\n", pls->bytemax, "Number of bytes maximum per member file"); fprintf (outf, "famadv %d > %s\n", pls->famadv, "Set to advance to the next family member"); fprintf (outf, "dev_fill0 %d > %s\n", pls->dev_fill0, "Set if driver can do solid area fills"); fprintf (outf, "dev_fill1 %d > %s\n", pls->dev_fill1, "Set if driver can do pattern area fills"); fprintf (outf, "dev_di %d > %s\n", pls->dev_di, "Set if driver wants to handle DI commands"); fprintf (outf, "dev_flush %d > %s\n", pls->dev_flush, "Set if driver wants to handle flushes itself"); fprintf (outf, "dev_swin %d > %s\n", pls->dev_swin, "Set if driver wants to handle 'set window' commands"); fprintf (outf, "DevName '%s' > %s\n", ifset(pls->DevName), "Device name"); fprintf (outf, "OutFile %p > %s\n", pls->OutFile, "Output file pointer"); fprintf (outf, "BaseName '%s' > %s\n", ifset(pls->BaseName), "Output base name (i.e. family)"); fprintf (outf, "FileName '%s' > %s\n", ifset(pls->FileName), "Output file name"); fprintf (outf, "Ext '%s' > %s\n", ifset(pls->Ext), "Output file extension"); fprintf (outf, "output_type %d > %s\n", pls->output_type, "0 for file, 1 for stream"); fprintf (outf, "bytecnt %d > %s\n", pls->bytecnt, "Byte count for output stream"); fprintf (outf, "page %d > %s\n", pls->page, "Page count for output stream"); fprintf (outf, "linepos %d > %s\n", pls->linepos, "Line count for output stream"); fprintf (outf, "pdfs %p > %s\n", pls->pdfs, "PDF stream pointer"); if (pls->pdfs) { fprintf (outf, "pdfs file %p bp %ld bufmax %ld\n", pls->pdfs->file, pls->pdfs->bp, pls->pdfs->bufmax); fprintf (outf, ".... buffer '%s'\n", ifsetu(pls->pdfs->buffer)); } fprintf (outf, "dev_npts %d > %s\n", pls->dev_npts, "Number of points we are plotting"); fprintf (outf, "dev_x %p > %s\n", pls->dev_x, "Pointer to array of x values"); fprintf (outf, "dev_y %p > %s\n", pls->dev_y, "Pointer to array of x values"); if (pls->dev_x && pls->dev_y && pls->dev_npts) { for (i=0; i< pls->dev_npts; i++) fprintf (outf, "dev_x[%d] %6hd dev_y[%d] %6hd\n", i, pls->dev_x[i], i, pls->dev_y[i]); } fprintf (outf, "dev %p > %s\n", pls->dev, "pointer to device-specific data (malloc'ed)"); fprintf (outf, "KeyEH %p > %s\n", pls->KeyEH, "Keyboard event handler"); fprintf (outf, "KeyEH_data %p > %s\n", pls->KeyEH_data, "Pointer to client data to pass"); fprintf (outf, "ButtonEH %p > %s\n", pls->ButtonEH, "(Mouse) Button event handler"); fprintf (outf, "LocateEH %p > %s\n", pls->LocateEH, "Locate event handler"); fprintf (outf, "LocateEH_data %p > %s\n", pls->LocateEH_data, "Pointer to client data to pass"); fprintf (outf, "xdpi %f > %s\n", pls->xdpi, "Device DPI settings in x and y"); fprintf (outf, "ydpi %f > %s\n", pls->ydpi, "..."); fprintf (outf, "xlength %5d > %s\n", pls->xlength, "Device output lengths in x and y"); fprintf (outf, "ylength %5d > %s\n", pls->ylength, "..."); fprintf (outf, "xoffset %d > %s\n", pls->xoffset, "Device offsets from upper left hand corner"); fprintf (outf, "yoffset %d > %s\n", pls->yoffset, "..."); fprintf (outf, "pageset %d > %s\n", pls->pageset, "Set if page dimensions were specified"); fprintf (outf, "hack %d > %s\n", pls->hack, "Enables driver-specific hack(s) if set"); fprintf (outf, "\nPer stream tidy function.\n"); fprintf (outf, "tidy %p > %s\n", pls->tidy, "pointer to cleanup routine"); fprintf (outf, "tidy_data %p > %s\n", pls->tidy_data, "pointer to client data to pass"); fprintf (outf, "\nError info\n"); fprintf (outf, "errcode %p > %s\n", pls->errcode, "pointer to variable to assign error code"); if (pls->errcode) fprintf (outf, " *errcode %d\n", *pls->errcode); fprintf (outf, "errmsg '%s' > %s\n", ifset(pls->errmsg), "pointer to error message buffer (must be >= 160 bytes)"); fprintf (outf, "\nStuff used by Xlib driver\n"); fprintf (outf, "geometry '%s' > %s\n", ifset(pls->geometry), "Window geometry (malloc'ed)"); fprintf (outf, "window_id %ld > %s\n", pls->window_id, "X-window window ID"); fprintf (outf, "nopixmap %d > %s\n", pls->nopixmap, "Set if you want to forbid allocation of pixmaps"); fprintf (outf, "db %d > %s\n", pls->db, "Set if you want to double buffer output"); fprintf (outf, "\nStuff used by TK, DP drivers\n"); fprintf (outf, "server_name '%s' > %s\n", ifset(pls->server_name), "Main window name of server"); fprintf (outf, "server_host '%s' > %s\n", ifset(pls->server_host), "Name of host to run server on"); fprintf (outf, "server_port '%s' > %s\n", ifset(pls->server_port), "Port to talk to server on"); fprintf (outf, "user '%s' > %s\n", ifset(pls->user), "Your user name on remote host (for remsh command)"); fprintf (outf, "plserver '%s' > %s\n", ifset(pls->plserver), "Name of server"); fprintf (outf, "plwindow '%s' > %s\n", ifset(pls->plwindow), "Name of reference server window (malloc'ed)"); fprintf (outf, "tcl_cmd '%s' > %s\n", ifset(pls->tcl_cmd), "TCL command(s) to eval on startup"); fprintf (outf, "auto_path '%s' > %s\n", ifset(pls->auto_path), "Additional directories to autoload"); fprintf (outf, "bufmax %d > %s\n", pls->bufmax, "Number of bytes sent before output buffer is flushed"); fprintf (outf, "dp %d > %s\n", pls->dp, "Use Tcl-DP for communication, if set"); fprintf (outf, "server_nokill %d > %s\n", pls->server_nokill, "Don't kill plserver on a ^C if set"); fprintf (outf, "\nPlot buffer settings\n"); fprintf (outf, "plbufFile %p > %s\n", pls->plbufFile, "Plot buffer file pointer"); fprintf (outf, "plbufOwner %d > %s\n", pls->plbufOwner, "Typically set; only zero if current stream is cloned."); fprintf (outf, "\nDriver interface (DI)\n"); fprintf (outf, "difilt %d > %s\n", pls->difilt, "Driver interface filter flag"); fprintf (outf, "diclpxmi %d > %s\n", pls->diclpxmi, "Device clip limits"); fprintf (outf, "diclpxma %d > %s\n", pls->diclpxma, "..."); fprintf (outf, "diclpymi %d > %s\n", pls->diclpymi, "..."); fprintf (outf, "diclpyma %d > %s\n", pls->diclpyma, "..."); fprintf (outf, "dipxmin %f > %s\n", pls->dipxmin, "Min, max relative plot coordinates"); fprintf (outf, "dipymin %f > %s\n", pls->dipymin, "..."); fprintf (outf, "dipxmax %f > %s\n", pls->dipxmax, "..."); fprintf (outf, "dipymax %f > %s\n", pls->dipymax, "..."); fprintf (outf, "dipxax %f > %s\n", pls->dipxax, "Plot window transformation:"); fprintf (outf, "dipxb %f > %s\n", pls->dipxb, " x' = dipxax * x + dipxb"); fprintf (outf, "dipyay %f > %s\n", pls->dipyay, "and"); fprintf (outf, "dipyb %f > %s\n", pls->dipyb, " y' = dipyay * y + dipyb"); fprintf (outf, "aspdev %f > %s\n", pls->aspdev, "Original device aspect ratio"); fprintf (outf, "aspect %f > %s\n", pls->aspect, "Page aspect ratio"); fprintf (outf, "aspori %f > %s\n", pls->aspori, "Rotation-induced aspect ratio"); fprintf (outf, "mar %f > %s\n", pls->mar, "Page margin (minimum)"); fprintf (outf, "jx %f > %s\n", pls->jx, "Page justification in x"); fprintf (outf, "jy %f > %s\n", pls->jy, "Page justification in y"); fprintf (outf, "didxax %f > %s\n", pls->didxax, "Device window transformation:"); fprintf (outf, "didxb %f > %s\n", pls->didxb, " x' = didxax * x + didxb"); fprintf (outf, "didyay %f > %s\n", pls->didyay, "and"); fprintf (outf, "didyb %f > %s\n", pls->didyb, " y' = didyay * y + didyb"); fprintf (outf, "diorot %f > %s\n", pls->diorot, "Rotation angle (in units of pi/2)"); fprintf (outf, "dioxax %f > %s\n", pls->dioxax, "Orientation transformation:"); fprintf (outf, "dioxay %f > %s\n", pls->dioxay, " x' = dioxax * x + dioxay * y + dioxb"); fprintf (outf, "dioxb %f > %s\n", pls->dioxb, "."); fprintf (outf, "dioyax %f > %s\n", pls->dioyax, "and"); fprintf (outf, "dioyay %f > %s\n", pls->dioyay, " y' = dioyax * x + dioyay * y + dioyb"); fprintf (outf, "dioyb %f > %s\n", pls->dioyb, "."); fprintf (outf, "dimxax %f > %s\n", pls->dimxax, "Map meta to physical coordinates:"); fprintf (outf, "dimxb %f > %s\n", pls->dimxb, " x' = dimxax * x + dimxb"); fprintf (outf, "dimyay %f > %s\n", pls->dimyay, "and"); fprintf (outf, "dimyb %f > %s\n", pls->dimyb, " y' = dimyay * y + dimyb"); fprintf (outf, "dimxmin %f > %s\n", pls->dimxmin, "Target coordinate system parameters."); fprintf (outf, "dimymin %f > %s\n", pls->dimymin, "..."); fprintf (outf, "dimxmax %f > %s\n", pls->dimxmax, "..."); fprintf (outf, "dimymax %f > %s\n", pls->dimymax, "..."); fprintf (outf, "dimxpmm %f > %s\n", pls->dimxpmm, "... pixels per mm"); fprintf (outf, "dimypmm %f > %s\n", pls->dimypmm, "... pixels per mm"); fprintf (outf, "page_status %d > %s\n", pls->page_status, "Flag to indicate current action"); fprintf (outf, "freeaspect %d > %s\n", pls->freeaspect, "Do not preserve aspect ratio on orientation swaps"); fprintf (outf, "\nFill pattern info\n"); fprintf (outf, "patt %d > %s\n", pls->patt, "Fill pattern number 0: Hardware > 0: Software"); fprintf (outf, "inclin %5d %5d > %s\n", pls->inclin[0], pls->inclin[1], "Array of inclinations in tenths of degree for fill lines"); fprintf (outf, "delta %5d %5d > %s\n", pls->delta[0], pls->delta[1], "Array of spacings in micrometers between fill lines"); fprintf (outf, "nps %d > %s\n", pls->nps, "Number of distinct line styles for fills"); fprintf (outf, "\nVariables used in line drawing\n"); fprintf (outf, "currx %6d > %s\n", pls->currx, "Physical x-coordinate of current point"); fprintf (outf, "curry %6d > %s\n", pls->curry, "Physical y-coordinate of current point"); fprintf (outf, "Mark: Array of mark lengths in micrometers for broken lines\n"); fprintf (outf, "Space: Array of space lengths in micrometers for broken lines\n"); for (i=0; i<10; i++) fprintf (outf, "mark[%d] %d space[%d] %d\n", i, pls->mark[i], i, pls->space[i]); fprintf (outf, "nms %d > %s\n", pls->nms, "Number of elements for current broken line style"); fprintf (outf, "timecnt %d > %s\n", pls->timecnt, "Timer for broken lines"); fprintf (outf, "alarm %d > %s\n", pls->alarm, "Alarm indicating change of broken line status"); fprintf (outf, "pendn %d > %s\n", pls->pendn, "Flag indicating if pen is up or down"); fprintf (outf, "curel %d > %s\n", pls->curel, "Current element within broken line"); fprintf (outf, "\nVariables governing character strings\n"); fprintf (outf, "esc %d ASCII %x hex > %s\n", (int) pls->esc, (int) pls->esc, "Text string escape character"); fprintf (outf, "\nScale factors for characters, symbols, and tick marks.\n"); fprintf (outf, "scale %f > %s\n", pls->scale, "Scaling factor for chr, sym, maj, min."); fprintf (outf, "chrdef %f > %s\n", pls->chrdef, "Character default height"); fprintf (outf, "chrht %f > %s\n", pls->chrht, "Character current (scaled) height"); fprintf (outf, "symdef %f > %s\n", pls->symdef, "Symbol default height"); fprintf (outf, "symht %f > %s\n", pls->symht, "Symbol current (scaled) height"); fprintf (outf, "majdef %f > %s\n", pls->majdef, "Major tick default height"); fprintf (outf, "majht %f > %s\n", pls->majht, "Major tick current (scaled) height"); fprintf (outf, "mindef %f > %s\n", pls->mindef, "Minor tick default height"); fprintf (outf, "minht %f > %s\n", pls->minht, "Minor tick current (scaled) height"); fprintf (outf, "\nVariables governing numeric axis label appearance\n"); fprintf (outf, "setpre %d > %s\n", pls->setpre, "Non-zero to set precision using 'prec'"); fprintf (outf, "precis %d > %s\n", pls->precis, "User-specified precision"); fprintf (outf, "xdigmax %d > %s\n", pls->xdigmax, "Allowed #digits in axes labels"); fprintf (outf, "ydigmax %d > %s\n", pls->ydigmax, "Allowed #digits in axes labels"); fprintf (outf, "zdigmax %d > %s\n", pls->zdigmax, "Allowed #digits in axes labels"); fprintf (outf, "xdigits %d > %s\n", pls->xdigits, "Actual field widths (returned)"); fprintf (outf, "ydigits %d > %s\n", pls->ydigits, "Actual field widths (returned)"); fprintf (outf, "zdigits %d > %s\n", pls->zdigits, "Actual field widths (returned)"); fprintf (outf, "\nVariables governing physical coordinate system\n"); fprintf (outf, "vppxmi %6d > %s\n", pls->vppxmi, "Viewport boundaries in physical coordinates"); fprintf (outf, "vppxma %6d > %s\n", pls->vppxma, "..."); fprintf (outf, "vppymi %6d > %s\n", pls->vppymi, "..."); fprintf (outf, "vppyma %6d > %s\n", pls->vppyma, "..."); fprintf (outf, "sppxmi %6d > %s\n", pls->sppxmi, "Subpage boundaries in physical coordinates"); fprintf (outf, "sppxma %6d > %s\n", pls->sppxma, "..."); fprintf (outf, "sppymi %6d > %s\n", pls->sppymi, "..."); fprintf (outf, "sppyma %6d > %s\n", pls->sppyma, "..."); fprintf (outf, "clpxmi %6d > %s\n", pls->clpxmi, "Clip boundaries in physical coordinates"); fprintf (outf, "clpxma %6d > %s\n", pls->clpxma, "..."); fprintf (outf, "clpymi %6d > %s\n", pls->clpymi, "..."); fprintf (outf, "clpyma %6d > %s\n", pls->clpyma, "..."); fprintf (outf, "phyxmi %6d > %s\n", pls->phyxmi, "Physical device limits in physical coordinates"); fprintf (outf, "phyxma %6d > %s\n", pls->phyxma, "..."); fprintf (outf, "phyxlen %6d > %s\n", pls->phyxlen, "..."); fprintf (outf, "phyymi %6d > %s\n", pls->phyymi, "..."); fprintf (outf, "phyyma %6d > %s\n", pls->phyyma, "..."); fprintf (outf, "phyylen %6d > %s\n", pls->phyylen, "..."); fprintf (outf, "umx %6d > %s\n", pls->umx, "Number of micrometers in a pixel"); fprintf (outf, "umy %6d > %s\n", pls->umy, "..."); fprintf (outf, "xpmm %5f > %s\n", pls->xpmm, "Number of pixels to a millimeter"); fprintf (outf, "ypmm %5f > %s\n", pls->ypmm, "..."); fprintf (outf, "\nState variables for 3d plots\n"); fprintf (outf, "base3x %f > %s\n", pls->base3x, "World coordinate size of base for 3-d plot"); fprintf (outf, "base3y %f > %s\n", pls->base3y, "..."); fprintf (outf, "basecx %f > %s\n", pls->basecx, "Position of centre of base for 3-d plot"); fprintf (outf, "basecy %f > %s\n", pls->basecy, "..."); fprintf (outf, "domxmi %f > %s\n", pls->domxmi, "Minimum and maximum values for domain"); fprintf (outf, "domxma %f > %s\n", pls->domxma, "..."); fprintf (outf, "domymi %f > %s\n", pls->domymi, "..."); fprintf (outf, "domyma %f > %s\n", pls->domyma, "..."); fprintf (outf, "zzscl %f > %s\n", pls->zzscl, "Vertical (z) scale for 3-d plot"); fprintf (outf, "ranmi %f > %s\n", pls->ranmi, "Minimum and maximum z values for 3-d plot"); fprintf (outf, "ranma %f > %s\n", pls->ranma, "..."); fprintf (outf, "cxx %f > %s\n", pls->cxx, "Coordinate transformation from 3-d to 2-d"); fprintf (outf, "cxy %f > %s\n", pls->cxy, "..."); fprintf (outf, "cyx %f > %s\n", pls->cyx, "..."); fprintf (outf, "cyy %f > %s\n", pls->cyy, "..."); fprintf (outf, "cyz %f > %s\n", pls->cyz, "..."); fprintf (outf, "\nVariables for keeping track of windows on a page.\n"); fprintf (outf, "nplwin %d > %s\n", pls->nplwin, "Number of coordinate windows on current page"); fprintf (outf, "Array of plCWindows for current page\n"); for (i=0; i< pls->nplwin; i++) { fprintf (outf, " plwin[%d].dxmi %3f\n", i, pls->plwin[i].dxmi); fprintf (outf, " plwin[%d].dxma %3f\n", i, pls->plwin[i].dxma); fprintf (outf, " plwin[%d].dymi %3f\n", i, pls->plwin[i].dymi); fprintf (outf, " plwin[%d].dyma %3f\n", i, pls->plwin[i].dyma); fprintf (outf, " plwin[%d].wxmi %3f\n", i, pls->plwin[i].wxmi); fprintf (outf, " plwin[%d].wxma %3f\n", i, pls->plwin[i].wxma); fprintf (outf, " plwin[%d].wymi %3f\n", i, pls->plwin[i].wymi); fprintf (outf, " plwin[%d].wyma %3f\n.\n", i, pls->plwin[i].wyma); } fprintf (outf, "\nVariables governing subpages and viewports.\n"); fprintf (outf, "nsubx %d > %s\n", pls->nsubx, "Number of subpages on physical device"); fprintf (outf, "nsuby %d > %s\n", pls->nsuby, "..."); fprintf (outf, "cursub %d > %s\n", pls->cursub, "Current subpage"); fprintf (outf, "spdxmi %f > %s\n", pls->spdxmi, "Subpage boundaries in normalized device coordinates"); fprintf (outf, "spdxma %f > %s\n", pls->spdxma, "..."); fprintf (outf, "spdymi %f > %s\n", pls->spdymi, "..."); fprintf (outf, "spdyma %f > %s\n", pls->spdyma, "..."); fprintf (outf, "vpdxmi %f > %s\n", pls->vpdxmi, "Viewport boundaries in normalized device coordinates"); fprintf (outf, "vpdxma %f > %s\n", pls->vpdxma, "..."); fprintf (outf, "vpdymi %f > %s\n", pls->vpdymi, "..."); fprintf (outf, "vpdyma %f > %s\n", pls->vpdyma, "..."); fprintf (outf, "vpwxmi %f > %s\n", pls->vpwxmi, "Viewport boundaries in world coordinates"); fprintf (outf, "vpwxma %f > %s\n", pls->vpwxma, "..."); fprintf (outf, "vpwymi %f > %s\n", pls->vpwymi, "..."); fprintf (outf, "vpwyma %f > %s\n", pls->vpwyma, "..."); fprintf (outf, "\nTransformation variables\n"); fprintf (outf, "wpxscl %5f > %s\n", pls->wpxscl, "Transformation variables for world to physical conversion"); fprintf (outf, "wpxoff %5f > %s\n", pls->wpxoff, "..."); fprintf (outf, "wpyscl %5f > %s\n", pls->wpyscl, "..."); fprintf (outf, "wpyoff %5f > %s\n", pls->wpyoff, "..."); fprintf (outf, "wmxscl %5f > %s\n", pls->wmxscl, "Transformation variables for world coordinates to mm"); fprintf (outf, "wmxoff %5f > %s\n", pls->wmxoff, "..."); fprintf (outf, "wmyscl %5f > %s\n", pls->wmyscl, "..."); fprintf (outf, "wmyoff %5f > %s\n", pls->wmyoff, "..."); } int plFileInfo (PLStream *pls, char* tmp) { if (pls->family && pls->BaseName != NULL) { /* family names*/ (void) sprintf(tmp, "%s.%%0%1dd%s", pls->BaseName, (int) pls->fflen,pls->Ext); return pls->member; } if (pls->FileName == NULL) { *tmp='\0'; return 0; } /* simple filenames */ (void) sprintf(tmp, pls->FileName); return -1; }