Annotation of OpenXM_contrib/gnuplot/term/pstricks.trm, Revision 1.1.1.2
1.1 maekawa 1: /* Hey Emacs this is -*- C -*-
2: *
1.1.1.2 ! maekawa 3: * $Id: pstricks.trm,v 1.12.2.1 1999/08/19 14:15:55 lhecking Exp $
1.1 maekawa 4: */
5:
6: /* GNUPLOT - pstricks.trm */
7:
8: /*[
9: * Copyright 1990 - 1993, 1998
10: *
11: * Permission to use, copy, and distribute this software and its
12: * documentation for any purpose with or without fee is hereby granted,
13: * provided that the above copyright notice appear in all copies and
14: * that both that copyright notice and this permission notice appear
15: * in supporting documentation.
16: *
17: * Permission to modify the software is granted, but not the right to
18: * distribute the complete modified source code. Modifications are to
19: * be distributed as patches to the released version. Permission to
20: * distribute binaries produced by compiling modified sources is granted,
21: * provided you
22: * 1. distribute the corresponding source modifications from the
23: * released version in the form of a patch file along with the binaries,
24: * 2. add special version identification to distinguish your version
25: * in addition to the base release version number,
26: * 3. provide your name and address as the primary contact for the
27: * support of your modified version, and
28: * 4. retain our contact information in regard to use of the base
29: * software.
30: * Permission to distribute the released version of the source code along
31: * with corresponding source modifications in the form of a patch file is
32: * granted with same provisions 2 through 4 for binary distributions.
33: *
34: * This software is provided "as is" without express or implied warranty
35: * to the extent permitted by applicable law.
36: ]*/
37:
38: /*
39: * This file is included by ../term.c.
40: *
41: * This terminal driver supports:
42: * The PSTricks macros for LaTeX.
43: *
44: * AUTHORS
45: * David Kotz
46: *
47: * Raymond Toy toy@soho.crd.ge.com
48: * Modified the eepic.trm file to use PSTricks macros instead.
49: *
50: * 20 Mar 93:
51: * Utilized many suggestions from Gisli Ottarsson
52: * (gisli@liapunov.eecs.umich.edu) to create a new version.
53: * Should also work with TeX as well as LaTeX.
54: *
55: * If you have PSTricks version 0.91, #define OLD_PST to
56: * get the right dots.
57: *
58: * Added a really ugly hack (enabled by default) to print
59: * "nice" numbers for axis labels. This should really be at
60: * a higher level in the code, but I'm lazy right now.
61: *
62: * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
63: *
64: */
65:
66: /*
67: * This file contains the PSTricks terminal driver, intended for use with the
68: * pstricks.sty macro package for LaTeX. This is an alternative to the
69: * eepic and latex driver. You need pstricks.sty, and, of course, a printer
70: * that understands PostScript. Ghostscript understands Postscript too.
71: *
72: * PSTricks is available via anonymous ftp from the /pub directory
73: * at Princeton.EDU. This driver definitely does not come close to
74: * using the full capability of the PSTricks package.
75: */
76: /*
77: * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
78: */
79:
80: #include "driver.h"
81:
82: #ifdef TERM_REGISTER
83: register_term(pstricks)
84: #endif
85:
86: #ifdef TERM_PROTO
87: TERM_PUBLIC void PSTRICKS_options __PROTO((void));
88: TERM_PUBLIC void PSTRICKS_init __PROTO((void));
89: TERM_PUBLIC void PSTRICKS_graphics __PROTO((void));
90: TERM_PUBLIC void PSTRICKS_text __PROTO((void));
91: TERM_PUBLIC void PSTRICKS_linetype __PROTO((int linetype));
92: TERM_PUBLIC void PSTRICKS_move __PROTO((unsigned int x, unsigned int y));
93: TERM_PUBLIC void PSTRICKS_point __PROTO((unsigned int x, unsigned int y, int number));
94: TERM_PUBLIC void PSTRICKS_vector __PROTO((unsigned int ux, unsigned int uy));
95: TERM_PUBLIC void PSTRICKS_arrow __PROTO((unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, TBOOLEAN head));
96: TERM_PUBLIC void PSTRICKS_put_text __PROTO((unsigned int x, unsigned int y, char str[]));
97: TERM_PUBLIC int PSTRICKS_justify_text __PROTO((enum JUSTIFY mode));
98: TERM_PUBLIC int PSTRICKS_text_angle __PROTO((int ang));
99: TERM_PUBLIC void PSTRICKS_reset __PROTO((void));
100:
101: #define PSTRICKS_XMAX 10000.0
102: #define PSTRICKS_YMAX 10000.0
103:
104: #define PSTRICKS_HTIC 150
105: #define PSTRICKS_VTIC 200
106: #define PSTRICKS_HCHAR 160
107: #define PSTRICKS_VCHAR 420
108: #endif /* TERM_PROTO */
109:
110: #ifndef TERM_PROTO_ONLY
111: #ifdef TERM_BODY
112: static void PSTRICKS_endline __PROTO((void));
113: static char *PSTRICKS_hack_text __PROTO((char s[]));
114:
115: static float PSTRICKS_xscale = 1.0;
116: static float PSTRICKS_yscale = 1.0;
117: static float PSTRICKS_posx;
118: static float PSTRICKS_posy;
119: enum JUSTIFY PSTRICKS_justify = LEFT;
120: static int PSTRICKS_angle = 0;
121:
122: #define PSTRICKS_TINY_DOT 0.00025 /* A tiny dot */
123:
124: /* POINTS */
125: #define PSTRICKS_POINT_TYPES 12 /* we supply more point types */
126: static char *PSTRICKS_points[] =
127: {
128: "\\PST@Diamond",
129: "\\PST@Plus",
130: "\\PST@Square",
131: "\\PST@Cross",
132: "\\PST@Circle",
133: "\\PST@Triangle",
134: "\\PST@Pentagon",
135: "\\PST@Filldiamond",
136: "\\PST@Fillsquare",
137: "\\PST@Filltriangle",
138: "\\PST@Fillcircle",
139: "\\PST@Fillpentagon"
140: };
141:
142: /* LINES */
143: #define PSTRICKS_NUMLINES 6 /* number of linetypes below */
144: static char *PSTRICKS_lines[] =
145: {
146: "\\PST@Border",
147: "\\PST@Axes",
148: "\\PST@Solid",
149: "\\PST@Dashed",
150: "\\PST@Dotted",
151: "\\PST@LongDash"
152: };
153:
154: /* current line type */
155: static int PSTRICKS_type;
156:
157: /* are we in the middle of a line */
158: static TBOOLEAN PSTRICKS_inline = FALSE;
159:
160: /* terminate any line in progress */
161: static void PSTRICKS_endline __PROTO((void));
162:
163: /* number of points in line so far */
164: static int PSTRICKS_linecount = 0;
165:
166: /* max value for linecount */
167: #define PSTRICKS_LINEMAX 100
168:
169: /*
170: * Handle options
171: */
172:
173: static int PST_hack_text = TRUE; /* Hack text on */
174: static int PST_unit_plot = FALSE; /* Unit-sized plot off */
175:
176: TERM_PUBLIC void PSTRICKS_options()
177: {
178: if (!END_OF_COMMAND) {
179: if (almost_equals(c_token, "no$hacktext")) {
180: PST_hack_text = FALSE;
181: c_token++;
182: } else if (almost_equals(c_token, "u$nit")) {
183: PST_unit_plot = TRUE;
184: c_token++;
185: }
186: }
187: }
188:
189: TERM_PUBLIC void PSTRICKS_init()
190: {
191: PSTRICKS_posx = PSTRICKS_posy = 0;
192: PSTRICKS_linetype(-1);
193: fputs("% GNUPLOT: LaTeX picture using PSTRICKS macros\n", gpoutfile);
194: }
195:
196:
197: TERM_PUBLIC void PSTRICKS_graphics()
198: {
199: fputs("\
200: % Define new PST objects, if not already defined\n\
201: \\ifx\\PSTloaded\\undefined\n\
202: \\def\\PSTloaded{t}\n\
203: \\psset{arrowsize=.01 3.2 1.4 .3}\n\
204: \\psset{dotsize=.01}\n\
205: \\catcode`@=11\n\n", gpoutfile);
206:
207: /* Define line type objects */
208: fputs("\
209: \\newpsobject{PST@Border}{psline}{linewidth=.0015,linestyle=solid}\n\
210: \\newpsobject{PST@Axes}{psline}{linewidth=.0015,linestyle=dotted,dotsep=.004}\n\
211: \\newpsobject{PST@Solid}{psline}{linewidth=.0015,linestyle=solid}\n\
212: \\newpsobject{PST@Dashed}{psline}{linewidth=.0015,linestyle=dashed,dash=.01 .01}\n\
213: \\newpsobject{PST@Dotted}{psline}{linewidth=.0025,linestyle=dotted,dotsep=.008}\n\
214: \\newpsobject{PST@LongDash}{psline}{linewidth=.0015,linestyle=dashed,dash=.02 .01}\n", gpoutfile);
215:
216: /* Define point objects */
217:
218: #ifdef OLD_PST
219: /* PSTricks version 0.91 had x and diamond dot types */
220: fputs("\
221: \\newpsobject(PST@Diamond}{psdots}{linewidth=.001,linestyle=solid,dotstyle=diamond}\n\
222: \\newpsobject(PST@Filldiamond}{psdots}{linewidth=.001,linestyle=solid,dotstyle=diamond*}\n\
223: \\newpsobject{PST@Cross}{psdots}{linewidth=.001,linestyle=solid,dotstyle=x}\n", gpoutfile);
224: #else
225: /* Newer versions use rotated plus and square to get the x and diamond dots */
226: fputs("\
227: \\newpsobject{PST@Diamond}{psdots}{linewidth=.001,linestyle=solid,dotstyle=square,dotangle=45}\n\
228: \\newpsobject{PST@Filldiamond}{psdots}{linewidth=.001,linestyle=solid,dotstyle=square*,dotangle=45}\n\
229: \\newpsobject{PST@Cross}{psdots}{linewidth=.001,linestyle=solid,dotstyle=+,dotangle=45}\n", gpoutfile);
230: #endif
231:
232: fputs("\
233: \\newpsobject{PST@Plus}{psdots}{linewidth=.001,linestyle=solid,dotstyle=+}\n\
234: \\newpsobject{PST@Square}{psdots}{linewidth=.001,linestyle=solid,dotstyle=square}\n\
235: \\newpsobject{PST@Circle}{psdots}{linewidth=.001,linestyle=solid,dotstyle=o}\n\
236: \\newpsobject{PST@Triangle}{psdots}{linewidth=.001,linestyle=solid,dotstyle=triangle}\n\
237: \\newpsobject{PST@Pentagon}{psdots}{linewidth=.001,linestyle=solid,dotstyle=pentagon}\n\
238: \\newpsobject{PST@Fillsquare}{psdots}{linewidth=.001,linestyle=solid,dotstyle=square*}\n\
239: \\newpsobject{PST@Fillcircle}{psdots}{linewidth=.001,linestyle=solid,dotstyle=*}\n\
240: \\newpsobject{PST@Filltriangle}{psdots}{linewidth=.001,linestyle=solid,dotstyle=triangle*}\n\
241: \\newpsobject{PST@Fillpentagon}{psdots}{linewidth=.001,linestyle=solid,dotstyle=pentagon*}\n", gpoutfile);
242:
243: /* Define arrow object */
244: fputs("\
245: \\newpsobject{PST@Arrow}{psline}{linewidth=.001,linestyle=solid}\n\
246: \\catcode`@=12\n\n\
247: \\fi\n", gpoutfile);
248:
249: /* Set the scaled plot size, if it's not a unit plot */
250: if (!PST_unit_plot) {
251: fprintf(gpoutfile, "\\psset{unit=%fin,xunit=%fin,yunit=%fin}\n",
252: 5.0 * PSTRICKS_xscale,
253: 5.0 * PSTRICKS_xscale,
254: 3.0 * PSTRICKS_yscale);
255: }
256: fputs("\
257: \\pspicture(0,0)(1,1)\n\
258: \\ifx\\nofigs\\undefined\n\
259: \\catcode`@=11\n\n", gpoutfile);
260: }
261:
262:
263: TERM_PUBLIC void PSTRICKS_text()
264: {
265: PSTRICKS_endline();
266: fputs("\
267: \\catcode`@=12\n\
268: \\fi\n\
269: \\endpspicture\n", gpoutfile);
270: }
271:
272:
273: TERM_PUBLIC void PSTRICKS_linetype(linetype)
274: int linetype;
275: {
276: PSTRICKS_endline();
277:
278: if (linetype >= PSTRICKS_NUMLINES - 2)
279: linetype %= (PSTRICKS_NUMLINES - 2);
280:
281: PSTRICKS_type = linetype;
282: }
283:
284:
285:
286: TERM_PUBLIC void PSTRICKS_move(x, y)
287: unsigned int x;
288: unsigned int y;
289: {
290: PSTRICKS_endline();
291:
292: PSTRICKS_posx = x / PSTRICKS_XMAX;
293: PSTRICKS_posy = y / PSTRICKS_YMAX;
294: }
295:
296:
297: TERM_PUBLIC void PSTRICKS_point(x, y, number) /* version of line_and_point */
298: unsigned x;
299: unsigned y;
300: int number;
301: {
302: PSTRICKS_move(x, y);
303:
304: /* Print the character defined by 'number'; number < 0 means
305: to use a dot, otherwise one of the defined points. */
306:
307: if (number < 0) {
308: fprintf(gpoutfile, "\\qdisk(%.4f,%.4f){%.4f}\n",
309: x / PSTRICKS_XMAX,
310: y / PSTRICKS_YMAX,
311: PSTRICKS_TINY_DOT);
312: } else {
313: fprintf(gpoutfile, "%s(%.4f,%.4f)\n",
314: PSTRICKS_points[number % PSTRICKS_POINT_TYPES],
315: x / PSTRICKS_XMAX,
316: y / PSTRICKS_YMAX);
317: }
318: }
319:
320:
321: TERM_PUBLIC void PSTRICKS_vector(ux, uy)
322: unsigned ux;
323: unsigned uy;
324: {
325: if (!PSTRICKS_inline) {
326: PSTRICKS_inline = TRUE;
327:
328: /* Start a new line. This depends on line type */
329: fprintf(gpoutfile, "%s(%.4f,%.4f)\n", PSTRICKS_lines[PSTRICKS_type + 2],
330: PSTRICKS_posx, PSTRICKS_posy);
331: PSTRICKS_linecount = 1;
332: } else {
333: /*
334: * Even though we are in middle of a path,
335: * we may want to start a new path command.
336: * If they are too long then latex will choke.
337: */
338: if (PSTRICKS_linecount++ >= PSTRICKS_LINEMAX) {
339: /* fprintf(gpoutfile, "\n"); */
340: fprintf(gpoutfile, "%s(%.4f,%.4f)\n", PSTRICKS_lines[PSTRICKS_type + 2],
341: PSTRICKS_posx, PSTRICKS_posy);
342: PSTRICKS_linecount = 1;
343: }
344: }
345: PSTRICKS_posx = ux / PSTRICKS_XMAX;
346: PSTRICKS_posy = uy / PSTRICKS_YMAX;
347: fprintf(gpoutfile, "(%.4f,%.4f)\n", PSTRICKS_posx, PSTRICKS_posy);
348: }
349:
350: static void PSTRICKS_endline()
351: {
352: if (PSTRICKS_inline) {
353: putc('\n', gpoutfile);
354: PSTRICKS_inline = FALSE;
355: }
356: }
357:
358:
359: TERM_PUBLIC void PSTRICKS_arrow(sx, sy, ex, ey, head)
360: unsigned int sx;
361: unsigned int sy;
362: unsigned int ex;
363: unsigned int ey;
364: TBOOLEAN head;
365: {
366: fprintf(gpoutfile, "\\PST@Arrow%s(%.4f,%.4f)(%.4f,%.4f)\n",
367: head ? "{->}" : "",
368: sx / PSTRICKS_XMAX,
369: sy / PSTRICKS_YMAX,
370: ex / PSTRICKS_XMAX,
371: ey / PSTRICKS_YMAX);
372:
373: PSTRICKS_posx = ex / PSTRICKS_XMAX;
374: PSTRICKS_posy = ey / PSTRICKS_YMAX;
375: }
376:
377: /*
378: * A really ugly hack!!!
379: *
380: * This function takes an input string and hacks it up. If the
381: * input string starts with a number, it converts the number into a
382: * TeX style number including exponential notation. Thus, if
383: * the input is the string "3.14159e3 is a number", then
384: * the output is "$3.14159\cdot 10^{3}$ is a number", so that TeX
385: * will produce something nice.
386: *
387: * This is basically meant for producing axis labels that look nice.
388: *
389: * What a hack!
390: */
391:
392:
393: static char *PSTRICKS_hack_text(s)
394: char s[];
395: {
396: double value;
397: char *ends;
398: static char hack[BUFSIZ];
399:
400: /*
401: * Does the string start with a number?
402: */
403:
404: value = strtod(s, &ends);
405:
406: if (s == ends) {
407: /*
408: * This doesn't start a number, so just copy the string over
409: */
410:
411: strcpy(hack, s);
412: } else {
413: char *ptr;
414:
415: /*
416: * We have a number! Check to see if the number
417: * is in scientific notation
418: */
419:
1.1.1.2 ! maekawa 420: safe_strncpy(hack, s, ends - s + 1);
1.1 maekawa 421: /* hack[ends - s] = '\0'; */
422:
423: ptr = strchr(hack, 'e');
424: if (ptr == NULL) {
425: ptr = strchr(hack, 'E');
426: }
427: if (ptr != NULL) {
428: /*
429: * Exponential notation! Let's get the mantissa and exponent separately
430: */
431:
432: double man_val;
433: int expo_val;
434:
435: *ptr = NUL;
436:
437: man_val = atof(hack);
438: expo_val = atoi(ptr + 1);
439:
440: if (man_val == 0) {
441: sprintf(hack, "0");
442: } else if (man_val == 1) {
443: sprintf(hack, "$10^{%d}$", expo_val);
444: } else if (man_val == (int) man_val) {
445: if (expo_val == 1) {
446: sprintf(hack, "$%d$", (int) man_val);
447: } else {
448: sprintf(hack, "$%d \\times 10^{%d}$", (int) man_val, expo_val);
449: }
450: } else {
451: if (expo_val == 1) {
452: sprintf(hack, "$%f$", man_val);
453: } else {
454: sprintf(hack, "$%f \\times 10^{%d}$", man_val, expo_val);
455: }
456: }
457: }
458: /*
459: * Copy anything that's left of the string
460: */
461:
462: strcat(hack, ends);
463: }
464:
465: return hack;
466: }
467:
468: TERM_PUBLIC void PSTRICKS_put_text(x, y, str)
469: unsigned int x;
470: unsigned int y;
471: char str[];
472: {
473: PSTRICKS_endline();
474:
475: /* Skip this if the string is empty */
476:
477: if (strlen(str) > 0) {
478: fputs("\\rput", gpoutfile);
479:
480: /* Set justification */
481:
482: switch (PSTRICKS_justify) {
483: case LEFT:
484: fputs("[l]", gpoutfile);
485: break;
486: case CENTRE:
487: break;
488: case RIGHT:
489: fputs("[r]", gpoutfile);
490: break;
491: }
492:
493: /* Set text angle */
494:
495: switch (PSTRICKS_angle) {
496: case 0:
497: break;
498: case 1:
499: fputs("{L}", gpoutfile);
500: break;
501: }
502:
503: /* Set reference position and text */
504:
505: fprintf(gpoutfile, "(%.4f,%.4f)",
506: x / PSTRICKS_XMAX,
507: y / PSTRICKS_YMAX);
508: if (PST_hack_text) {
509: char *hack;
510:
511: /* Hack leading numbers to something nice for TeX */
512:
513: hack = PSTRICKS_hack_text(str);
514: fprintf(gpoutfile, "{%s}\n", hack);
515: } else {
516: fprintf(gpoutfile, "{%s}\n", str);
517: }
518: }
519: }
520:
521:
522:
523: TERM_PUBLIC int PSTRICKS_justify_text(mode)
524: enum JUSTIFY mode;
525: {
526: PSTRICKS_justify = mode;
527: return (TRUE);
528: }
529:
530: TERM_PUBLIC int PSTRICKS_text_angle(ang)
531: int ang;
532: {
533: PSTRICKS_angle = ang;
534: return (TRUE);
535: }
536:
537: TERM_PUBLIC void PSTRICKS_reset()
538: {
539: PSTRICKS_endline();
540: PSTRICKS_posx = PSTRICKS_posy = 0;
541: }
542:
543: #endif /* TERM_BODY */
544:
545: #ifdef TERM_TABLE
546:
547: TERM_TABLE_START(pstricks_driver)
548: "pstricks", "LaTeX picture environment with PSTricks macros",
549: PSTRICKS_XMAX, PSTRICKS_YMAX, PSTRICKS_VCHAR, PSTRICKS_HCHAR,
550: PSTRICKS_VTIC, PSTRICKS_HTIC, PSTRICKS_options, PSTRICKS_init, PSTRICKS_reset,
551: PSTRICKS_text, null_scale, PSTRICKS_graphics, PSTRICKS_move, PSTRICKS_vector,
552: PSTRICKS_linetype, PSTRICKS_put_text, PSTRICKS_text_angle,
553: PSTRICKS_justify_text, PSTRICKS_point, PSTRICKS_arrow, set_font_null
554: TERM_TABLE_END(pstricks_driver)
555:
556: #undef LAST_TERM
557: #define LAST_TERM pstricks_driver
558:
559: #endif /* TERM_TABLE */
560: #endif /* TERM_PROTO_ONLY */
561:
562: #ifdef TERM_HELP
563: START_HELP(pstricks)
564: "1 pstricks",
565: "?commands set terminal pstricks",
566: "?set terminal pstricks",
567: "?set term pstricks",
568: "?terminal pstricks",
569: "?term pstricks",
570: "?pstricks",
571: " The `pstricks` driver is intended for use with the \"pstricks.sty\" macro",
572: " package for LaTeX. It is an alternative to the `eepic` and `latex` drivers.",
573: " You need \"pstricks.sty\", and, of course, a printer that understands",
574: " PostScript, or a converter such as Ghostscript.",
575: "",
576: " PSTricks is available via anonymous ftp from the /pub directory at",
577: " Princeton.EDU. This driver definitely does not come close to using the full",
578: " capability of the PSTricks package.",
579: "",
580: " Syntax:",
581: " set terminal pstricks {hacktext | nohacktext} {unit | nounit}",
582: "",
583: " The first option invokes an ugly hack that gives nicer numbers; the second",
584: " has to do with plot scaling. The defaults are `hacktext` and `nounit`."
585: END_HELP(pstricks)
586: #endif /* TERM_HELP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>