Initial release of Maemo 5 port of gnuplot
[gnuplot] / term / tpic.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: tpic.trm,v 1.21 2006/07/21 02:35:48 sfeam Exp $
3  */
4
5 /* GNUPLOT - tpic.trm */
6
7 /*[
8  * Copyright 1990 - 1993, 1998, 2004
9  *
10  * Permission to use, copy, and distribute this software and its
11  * documentation for any purpose with or without fee is hereby granted,
12  * provided that the above copyright notice appear in all copies and
13  * that both that copyright notice and this permission notice appear
14  * in supporting documentation.
15  *
16  * Permission to modify the software is granted, but not the right to
17  * distribute the complete modified source code.  Modifications are to
18  * be distributed as patches to the released version.  Permission to
19  * distribute binaries produced by compiling modified sources is granted,
20  * provided you
21  *   1. distribute the corresponding source modifications from the
22  *    released version in the form of a patch file along with the binaries,
23  *   2. add special version identification to distinguish your version
24  *    in addition to the base release version number,
25  *   3. provide your name and address as the primary contact for the
26  *    support of your modified version, and
27  *   4. retain our contact information in regard to use of the base
28  *    software.
29  * Permission to distribute the released version of the source code along
30  * with corresponding source modifications in the form of a patch file is
31  * granted with same provisions 2 through 4 for binary distributions.
32  *
33  * This software is provided "as is" without express or implied warranty
34  * to the extent permitted by applicable law.
35 ]*/
36
37 /*
38  * This file is included by ../term.c.
39  *
40  * This terminal driver supports:
41  *   The tpic \specials (version 2.2) for LaTeX.
42  *
43  * AUTHORS
44  *   Oh-Yeah?   3 Sep. 1992 (closely following eepic.trm by David Kotz)
45  *   A. Woo     5 Oct. 1992 (removed ansi prototypes for braindead compilers)
46  *
47  * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
48  *
49  */
50 /*
51  *  This file contains the tpic terminal driver for use with LaTeX.
52  *  This is an alternative to the latex and eepic drivers. You need
53  *  a printer driver that supports the tpic \specials version 2.2.
54  *
55  * Comparison with the eepic driver (eepic.trm):
56  *  Merits
57  *    - More point and line types
58  *    - Options to change point size, linewidth, dot & dash intervals
59  *    - Dotted and dashed lines for high-sample-rate curves (but may
60  *      depend on tpic (da & dt) implementation of your dvi driver :-)
61  *    - Overlapped points made fancier by tpic shading facility
62  *    - Optional comments for trimming figure margins
63  *    - No need for epic and eepic macros
64  *  Drawback
65  *    - You cannot use eepicemu macro for non-tpic-support dvi drivers
66  *
67  * LATEX must also be defined.
68  */
69
70
71 /* These parameters can be modified as you like, through options.  Say
72    "set terminal tpic <pointsize> <linewidth> <interval>".  <pointsize>
73    and <linewidth> are integers in milli-inches; <interval> is a float
74    in inches.  If non-positive value is specified, the default (below)
75    is chosen.
76 */
77
78 /*
79  * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
80  */
81
82 #include "driver.h"
83
84 #ifdef TERM_REGISTER
85 register_term(tpic)
86 #endif
87
88 #ifdef TERM_PROTO
89 TERM_PUBLIC void TPIC_options __PROTO((void));          /* get size options */
90 TERM_PUBLIC void TPIC_init __PROTO((void));
91 TERM_PUBLIC void TPIC_reset __PROTO((void));
92 TERM_PUBLIC void TPIC_text __PROTO((void));
93 TERM_PUBLIC void TPIC_graphics __PROTO((void));
94 TERM_PUBLIC void TPIC_move __PROTO((unsigned int x, unsigned int y));
95 TERM_PUBLIC void TPIC_vector __PROTO((unsigned int ux, unsigned int uy));
96 TERM_PUBLIC void TPIC_linetype __PROTO((int linetype));
97 TERM_PUBLIC void TPIC_put_text __PROTO((unsigned int x, unsigned int y, const char *str));      /* ref point and text */
98 TERM_PUBLIC int TPIC_text_angle __PROTO((int ang));
99 TERM_PUBLIC int TPIC_justify_text __PROTO((enum JUSTIFY mode));
100 TERM_PUBLIC void TPIC_point __PROTO((unsigned int x, unsigned int y, int number));
101 TERM_PUBLIC void TPIC_arrow __PROTO((unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, int head));
102
103 /* tpic \specials unit in inches (1 milli-inch) */
104 #define TPIC_UNIT 0.001
105
106 /* 5 inches wide by 3 inches high (default) */
107 #define TPIC_XMAX (unsigned int) (5 / TPIC_UNIT)
108 #define TPIC_YMAX (unsigned int) (3 / TPIC_UNIT)
109 #define TPIC_PTS_PER_UNIT (72.27 * TPIC_UNIT)
110 #define TPIC_HTIC  (unsigned int) ( 5.0 / TPIC_PTS_PER_UNIT)    /* 5pt */
111 #define TPIC_VTIC  (unsigned int) ( 5.0 / TPIC_PTS_PER_UNIT)    /* 5pt */
112 #define TPIC_HCHAR (unsigned int) ( 5.3 / TPIC_PTS_PER_UNIT)    /* 5.3pt */
113 #define TPIC_VCHAR (unsigned int) (11.0 / TPIC_PTS_PER_UNIT)    /* 11pt */
114 #endif /* TERM_PROTO */
115
116 #ifndef TERM_PROTO_ONLY
117 #ifdef TERM_BODY
118 static int tpic_pointsize = 40; /* min point radius   (in milli-inches) */
119 static int tpic_linewidth = 6;  /* min line thickness (in milli-inches) */
120 static double tpic_interval = 0.1;      /* min dot & dash intervals (in inches) */
121
122 /* ARROWS: same code as for LATEX */
123 /* figure out the best arrow. in latex.trm */
124 static void best_latex_arrow __PROTO((int sx, int sy, int ex, int ey, int who, int head));
125
126 /* all prototypes ... */
127 static void tpic_startline __PROTO((void));
128 static void tpic_endline __PROTO((void));
129 static void tpic_pushpath __PROTO((unsigned int x, unsigned int y));
130 static void tpic_scanpath __PROTO((void));
131 static void tpic_diamond __PROTO((int size));
132 static void tpic_plus __PROTO((int size));
133 static void tpic_box __PROTO((int size));
134 static void tpic_times __PROTO((int size));
135 static void tpic_triangle __PROTO((int size));
136 static void tpic_star __PROTO((int size));
137 static void tpic_hexagon __PROTO((int size));
138 static void tpic_circle __PROTO((int size));
139 static void tpic_doublecircle __PROTO((int size));
140 static void tpic_vercircle __PROTO((int size)); /* circle with | */
141 static void tpic_horcircle __PROTO((int size)); /* circle with - */
142 static void tpic_pluscircle __PROTO((int size));        /* circle with + */
143 static void tpic_timescircle __PROTO((int size));       /* circle with times */
144 static void tpic_starcircle __PROTO((int size));        /* circle with star */
145 static void tpic_dotcircle __PROTO((int size)); /* circle with dot (black circle) */
146 static void tpic_diamondcircle __PROTO((int size)); /* circle with black diamond */
147 static void tpic_boxcircle __PROTO((int size)); /* circle with black box */
148 static void tpic_trianglecircle __PROTO((int size));    /* circle with black triangle */
149 static void tpic_hexagoncircle __PROTO((int size));     /* circle with black hexagon */
150 static void tpic_plustimescircle __PROTO((int size));   /* no more idea ... with plus & times */
151 static void tpic_abspath __PROTO((unsigned int x, unsigned int y));     /* absolute coord */
152 static void tpic_path __PROTO((int x, int y));
153 static void tpic_flush __PROTO((void));
154 static void tpic_arc __PROTO((int radius));     /* actually, draw a full circle */
155 static void tpic_shade __PROTO((double grayscale));
156 static void tpic_pen __PROTO((int thickness));
157 static void tpic_dottedflush __PROTO((double interval));
158 static void tpic_dashedflush __PROTO((double interval));
159
160 typedef enum {
161     tpic_none, tpic_white, tpic_gray, tpic_black
162 } tpic_shadestyle;
163 typedef enum {
164     tpic_nosize, tpic_small, tpic_medium, tpic_large
165 } tpic_size;
166 typedef void (*tpic_function) __PROTO((int size));
167
168 typedef struct {
169     tpic_shadestyle shadestyle;
170     tpic_size size;
171     tpic_function function;
172 } tpic_point_info;
173
174 /* POINTS */
175 static /*GPFAR */ tpic_point_info GPFAR tpic_point[] =
176 {
177     {tpic_white, tpic_medium, tpic_diamond},
178     {tpic_none, tpic_medium, tpic_plus},
179     {tpic_white, tpic_medium, tpic_box},
180     {tpic_none, tpic_medium, tpic_times},
181     {tpic_white, tpic_medium, tpic_triangle},
182     {tpic_none, tpic_medium, tpic_star},
183     {tpic_white, tpic_small, tpic_circle},
184     {tpic_white, tpic_medium, tpic_circle},
185     {tpic_white, tpic_large, tpic_circle},
186     {tpic_black, tpic_small, tpic_circle},
187     {tpic_black, tpic_medium, tpic_circle},
188     {tpic_black, tpic_large, tpic_circle},
189     {tpic_black, tpic_medium, tpic_diamond},
190     {tpic_black, tpic_medium, tpic_box},
191     {tpic_black, tpic_medium, tpic_triangle},
192     {tpic_white, tpic_medium, tpic_hexagon},
193     {tpic_black, tpic_medium, tpic_hexagon},
194     {tpic_white, tpic_medium, tpic_doublecircle},
195     {tpic_white, tpic_medium, tpic_vercircle},
196     {tpic_white, tpic_medium, tpic_horcircle},
197     {tpic_white, tpic_medium, tpic_pluscircle},
198     {tpic_white, tpic_medium, tpic_timescircle},
199     {tpic_white, tpic_medium, tpic_starcircle},
200     {tpic_black, tpic_medium, tpic_doublecircle},
201     {tpic_white, tpic_medium, tpic_dotcircle},
202     {tpic_white, tpic_medium, tpic_diamondcircle},
203     {tpic_white, tpic_medium, tpic_boxcircle},
204     {tpic_white, tpic_medium, tpic_trianglecircle},
205     {tpic_white, tpic_medium, tpic_hexagoncircle},
206     {tpic_white, tpic_medium, tpic_plustimescircle}
207 };
208
209 typedef enum {
210     tpic_solid, tpic_dotted, tpic_dashed,
211     tpic_dashed_sdot, tpic_dashed_ddot
212 } tpic_linestyle;
213 typedef struct {
214     tpic_size thickness, interval;
215     tpic_linestyle linestyle;
216 } tpic_line_info;
217
218 /* LINES */
219 static /*GPFAR */ tpic_line_info GPFAR tpic_line[] =
220 {
221     {tpic_medium, tpic_nosize, tpic_solid},     /* -2 border */
222     {tpic_small, tpic_small, tpic_dashed},      /* -1 axes */
223     {tpic_small, tpic_nosize, tpic_solid},
224     {tpic_medium, tpic_nosize, tpic_solid},
225     {tpic_large, tpic_nosize, tpic_solid},
226     {tpic_small, tpic_small, tpic_dotted},
227     {tpic_medium, tpic_small, tpic_dotted},
228     {tpic_large, tpic_small, tpic_dotted},
229     {tpic_small, tpic_small, tpic_dashed},
230     {tpic_medium, tpic_small, tpic_dashed},
231     {tpic_large, tpic_small, tpic_dashed},
232     {tpic_small, tpic_small, tpic_dashed_sdot},         /* dash with single dots */
233     {tpic_medium, tpic_small, tpic_dashed_sdot},
234     {tpic_large, tpic_small, tpic_dashed_sdot},
235     {tpic_small, tpic_small, tpic_dashed_ddot},         /* dash with double dots */
236     {tpic_medium, tpic_small, tpic_dashed_ddot},
237     {tpic_large, tpic_small, tpic_dashed_ddot},
238     {tpic_small, tpic_medium, tpic_dotted},
239     {tpic_medium, tpic_medium, tpic_dotted},
240     {tpic_large, tpic_medium, tpic_dotted},
241     {tpic_small, tpic_medium, tpic_dashed},
242     {tpic_medium, tpic_medium, tpic_dashed},
243     {tpic_large, tpic_medium, tpic_dashed},
244     {tpic_small, tpic_medium, tpic_dashed_sdot},
245     {tpic_medium, tpic_medium, tpic_dashed_sdot},
246     {tpic_large, tpic_medium, tpic_dashed_sdot},
247     {tpic_small, tpic_medium, tpic_dashed_ddot},
248     {tpic_medium, tpic_medium, tpic_dashed_ddot},
249     {tpic_large, tpic_medium, tpic_dashed_ddot},
250     {tpic_small, tpic_large, tpic_dotted},
251     {tpic_medium, tpic_large, tpic_dotted},
252     {tpic_large, tpic_large, tpic_dotted},
253     {tpic_small, tpic_large, tpic_dashed},
254     {tpic_medium, tpic_large, tpic_dashed},
255     {tpic_large, tpic_large, tpic_dashed},
256     {tpic_small, tpic_large, tpic_dashed_sdot},
257     {tpic_medium, tpic_large, tpic_dashed_sdot},
258     {tpic_large, tpic_large, tpic_dashed_sdot},
259     {tpic_small, tpic_large, tpic_dashed_ddot},
260     {tpic_medium, tpic_large, tpic_dashed_ddot},
261     {tpic_large, tpic_large, tpic_dashed_ddot}
262 };
263
264 TERM_PUBLIC void
265 TPIC_options()
266 {                               /* get size options */
267     struct value a;
268     int ptsize, linewidth;
269     double interval;
270
271     if (!END_OF_COMMAND) {
272         ptsize = (int) real(const_express(&a));
273         if (ptsize > 0)
274             tpic_pointsize = ptsize;
275     }
276     if (!END_OF_COMMAND) {
277         linewidth = (int) real(const_express(&a));
278         if (linewidth > 0)
279             tpic_linewidth = linewidth;
280     }
281     if (!END_OF_COMMAND) {
282         interval = (double) real(const_express(&a));
283         if (interval > 0)
284             tpic_interval = interval;
285     }
286     sprintf(term_options, "%d %d %f", tpic_pointsize, tpic_linewidth,
287             tpic_interval);
288 }
289
290 static unsigned int tpic_posx;  /* current position */
291 static unsigned int tpic_posy;
292 static int tpic_point_types;
293 static int tpic_numlines;
294
295 TERM_PUBLIC void
296 TPIC_init()
297 {
298     static char GPFAR tpic1[] = "\
299 %% GNUPLOT: LaTeX picture using tpic \\specials\n\
300 %%          with %d point types and %d line types\n\
301 %% Options: pointsize = %d, linewidth = %d, interval = %f\n\
302 %% To change above options, say:\n\
303 %% set terminal tpic pointsize_value linewidth_value interval_value\n\
304 %% (pointsize and linewidth - integers in milli-inches.\n\
305 %%  interval - a float in inches.  If zero is specified, \n\
306 %%  the default value is chosen.)\n\
307 \\setlength{\\unitlength}{%fin}%%\n";
308     tpic_point_types = sizeof(tpic_point) / sizeof(tpic_point[0]);
309     tpic_numlines = sizeof(tpic_line) / sizeof(tpic_line[0]);
310
311     tpic_posx = tpic_posy = 0;
312     TPIC_linetype(-1);
313     fprintf(gpoutfile, tpic1,
314             tpic_point_types, tpic_numlines - 2,
315             tpic_pointsize, tpic_linewidth, tpic_interval,
316             TPIC_UNIT);
317 }
318
319 TERM_PUBLIC void
320 TPIC_reset()
321 {
322     tpic_endline();
323     tpic_posx = tpic_posy = 0;
324 }
325
326 TERM_PUBLIC void
327 TPIC_text()
328 {
329     tpic_endline();
330     fputs("\\end{picture}\n", gpoutfile);
331 }
332
333 TERM_PUBLIC void
334 TPIC_graphics()
335 {
336     register struct termentry *t = term;
337     int left, right, top, bottom;       /* margins */
338     static char GPFAR begin[] = "%s\\begin{picture}(%d,%d)(%d,%d)%% %s\n";
339
340     fprintf(gpoutfile, begin, "", t->xmax, t->ymax, 0, 0, "");
341
342     /* the following is dependent on boundary() function in graphics.c */
343     left = TPIC_HCHAR * 12;
344     right = TPIC_HCHAR * 2 + TPIC_HTIC;
345     bottom = TPIC_VCHAR * 7 / 2 + 1;
346     top = TPIC_VCHAR * 5 / 2 - 1;
347     fprintf(gpoutfile, begin, "%% ", t->xmax - left, t->ymax, left, 0,
348             "trim left margin");
349     fprintf(gpoutfile, begin, "%% ", t->xmax - right, t->ymax, 0, 0,
350             "trim right margin");
351     fprintf(gpoutfile, begin, "%% ", t->xmax - left - right, t->ymax, left, 0,
352             "trim left & right margins");
353     fprintf(gpoutfile, begin, "%% ", t->xmax, t->ymax - top, 0, 0,
354             "trim top margin");
355     fprintf(gpoutfile, begin, "%% ", t->xmax, t->ymax - bottom, 0, bottom,
356             "trim bottom margin");
357     fprintf(gpoutfile, begin, "%% ", t->xmax, t->ymax - top - bottom, 0, bottom,
358             "trim top & bottom margins");
359
360     fputs("\\footnotesize%\n", gpoutfile);
361 }
362
363 TERM_PUBLIC void
364 TPIC_move(unsigned int x, unsigned int y)
365 {
366     tpic_endline();
367     tpic_posx = x;
368     tpic_posy = y;
369 }
370
371 #define TPIC_LINEMAX 100        /* max value for linecount */
372 static TBOOLEAN tpic_inline = FALSE;    /* are we in the middle of a line */
373 static int tpic_linecount = 0;  /* number of points in line so far */
374
375 TERM_PUBLIC void
376 TPIC_vector(unsigned int ux, unsigned int uy)
377 {
378     if (!tpic_inline) {
379         tpic_startline();
380     } else if (tpic_linecount >= TPIC_LINEMAX) {
381         /* Even though we are in middle of a path, we may start a new path
382            command once in a while; if they are too long, latex will choke. */
383         tpic_endline();
384         tpic_startline();
385     }
386     tpic_pushpath(ux, uy);
387     tpic_posx = ux;
388     tpic_posy = uy;
389 }
390
391 static int tpic_linetype;       /* current line type */
392
393 static void
394 tpic_startline()
395 {                               /* private */
396     int thickness = 1;
397
398     tpic_inline = TRUE;
399     switch (tpic_line[tpic_linetype + 2].thickness) {
400     case tpic_small:
401         thickness = tpic_linewidth;
402         break;
403     case tpic_medium:
404         thickness = (int) (tpic_linewidth * 3);
405         break;
406     case tpic_large:
407         thickness = (int) (tpic_linewidth * 5);
408         break;
409     default:
410         break;
411     }
412     tpic_pen(thickness);
413     tpic_linecount = 0;
414     tpic_pushpath(tpic_posx, tpic_posy);
415     return;
416 }
417
418 static void
419 tpic_endline()
420 {                               /* private */
421     double interval = 1;
422
423     if (tpic_inline) {
424         tpic_scanpath();        /* draw actually */
425         switch (tpic_line[tpic_linetype + 2].interval) {
426         case tpic_small:
427             interval = tpic_interval;
428             break;
429         case tpic_medium:
430             interval = tpic_interval * 2;
431             break;
432         case tpic_large:
433             interval = tpic_interval * 3;
434             break;
435         case tpic_nosize:
436             break;
437         }
438         switch (tpic_line[tpic_linetype + 2].linestyle) {
439         case tpic_solid:
440             tpic_flush();
441             break;
442         case tpic_dotted:
443             tpic_dottedflush(interval);
444             break;
445         case tpic_dashed:
446             tpic_dashedflush(interval);
447             break;
448         case tpic_dashed_sdot:  /* dashed with single dots in between */
449             tpic_dashedflush(interval);
450             tpic_scanpath();    /* draw again */
451             tpic_dottedflush(interval / 2);
452             break;
453         case tpic_dashed_ddot:  /* dashed with double dots in between */
454             tpic_dashedflush(interval);
455             tpic_scanpath();    /* draw again */
456             tpic_dottedflush(interval / 3);
457             break;
458         }
459         tpic_inline = FALSE;
460     }
461     return;
462 }
463
464 /* private: stack functions */
465 static unsigned int pathpoint[TPIC_LINEMAX][2];         /* point stack */
466
467 static void
468 tpic_pushpath(unsigned int x, unsigned int y)
469 {
470     if (tpic_linecount < TPIC_LINEMAX) {
471         pathpoint[tpic_linecount][0] = x;
472         pathpoint[tpic_linecount][1] = y;
473         tpic_linecount++;
474     }
475     return;
476 }
477
478 static void
479 tpic_scanpath()
480 {
481     int i;
482
483     for (i = 0; i < tpic_linecount; i++)
484         tpic_abspath(pathpoint[i][0], pathpoint[i][1]);
485     return;
486 }
487
488 TERM_PUBLIC void
489 TPIC_linetype(int linetype)
490 {
491     tpic_endline();
492     if (linetype < -2)
493         linetype = LT_BLACK;
494     if (linetype >= tpic_numlines - 2)
495         linetype %= (tpic_numlines - 2);
496     tpic_linetype = linetype;
497 }
498
499 static int tpic_angle = 0;      /* 0 = horizontal, 1 = vertical */
500 static enum JUSTIFY tpic_justify = LEFT;
501
502 TERM_PUBLIC void
503 TPIC_put_text(unsigned int x, unsigned int y, const char *str)
504 {
505     char *justify = NULL;
506
507     tpic_endline();
508     fprintf(gpoutfile, "\\put(%d,%d)", x, y);
509
510     if ((str[0] == '{') || (str[0] == '[')) {
511         fprintf(gpoutfile, "{\\makebox(0,0)%s}\n", str);
512     } else
513         switch (tpic_angle) {
514         case 0:         /* horizontal */
515             switch (tpic_justify) {
516             case LEFT:
517                 justify = "[l]";
518                 break;
519             case CENTRE:
520                 justify = "";
521                 break;
522             case RIGHT:
523                 justify = "[r]";
524                 break;
525             }
526             fprintf(gpoutfile, "{\\makebox(0,0)%s{%s}}\n", justify, str);
527             break;
528         case 1:         /* vertical */
529             /* we can't really write text vertically, but will put the ylabel
530                centred at the left of the plot, and then we'll make a \shortstack */
531             switch (tpic_justify) {
532             case LEFT:
533                 justify = "[lb]";
534                 break;
535             case CENTRE:
536                 justify = "[l]";
537                 break;
538             case RIGHT:
539                 justify = "[lt]";
540                 break;
541             }
542             fprintf(gpoutfile, "{\\makebox(0,0)%s{\\shortstack{%s}}}\n",
543                     justify, str);
544             break;
545         }
546 }
547
548 TERM_PUBLIC int
549 TPIC_text_angle(int ang)
550 {
551     tpic_angle = (ang ? 1 : 0);
552     return (TRUE);
553 }
554
555 TERM_PUBLIC int
556 TPIC_justify_text(enum JUSTIFY mode)
557 {
558     tpic_justify = mode;
559     return (TRUE);
560 }
561
562 TERM_PUBLIC void
563 TPIC_point(unsigned int x, unsigned int y, int number)
564 {
565     int size = 0;
566
567     TPIC_move(x, y);
568
569     /* Print the character defined by 'number'; number < 0 means
570        to use a dot, otherwise one of the defined points. */
571
572     fprintf(gpoutfile, "\\put(%d,%d){", x, y);  /* start putting */
573
574     if (number < 0) {
575         fputs("\\rule{.1pt}{.1pt}", gpoutfile); /* tiny dot */
576     } else {
577         number %= tpic_point_types;
578         switch (tpic_point[number].shadestyle) {
579         case tpic_white:
580             tpic_pen(tpic_linewidth);   /* set it thin */
581             tpic_shade(0.0);
582             break;
583         case tpic_gray:
584             tpic_pen(tpic_linewidth);
585             tpic_shade(0.5);
586             break;
587         case tpic_black:
588             tpic_pen(tpic_linewidth);
589             tpic_shade(1.0);
590             break;
591         case tpic_none:
592             tpic_pen(tpic_linewidth * 3);       /* set it thick */
593             break;
594         }
595         switch (tpic_point[number].size) {
596         case tpic_small:
597             size = tpic_pointsize;
598             break;
599         case tpic_medium:
600             size = (int) (tpic_pointsize * 1.4142);
601             break;
602         case tpic_large:
603             size = (int) (tpic_pointsize * 2.0);
604             break;
605         default:
606             break;
607         }
608         (tpic_point[number].function) (size);
609     }
610
611     fputs("}%%\n", gpoutfile);  /* end putting */
612 }
613
614 TERM_PUBLIC void
615 TPIC_arrow(
616     unsigned int sx, unsigned int sy,
617     unsigned int ex, unsigned int ey,
618     int head)
619 {
620     best_latex_arrow(sx, sy, ex, ey, 1, head);  /* call latex routine */
621     tpic_posx = ex;
622     tpic_posy = ey;
623 }
624
625 /* private: draw points with tpic commands */
626
627 static void
628 tpic_diamond(int size)
629 {
630     size = (int) (size * 1.4142);       /* spread by sqrt(2) */
631
632     tpic_path(0, size);
633     tpic_path(-size, 0);
634     tpic_path(0, -size);
635     tpic_path(size, 0);
636     tpic_path(0, size);
637     tpic_flush();
638     return;
639 }
640
641 static void
642 tpic_plus(int size)
643 {
644     tpic_path(0, size);
645     tpic_path(0, -size);
646     tpic_flush();
647     tpic_path(size, 0);
648     tpic_path(-size, 0);
649     tpic_flush();
650     return;
651 }
652
653 static void
654 tpic_box(int size)
655 {
656     tpic_path(size, size);
657     tpic_path(-size, size);
658     tpic_path(-size, -size);
659     tpic_path(size, -size);
660     tpic_path(size, size);
661     tpic_flush();
662     return;
663 }
664
665 static void
666 tpic_times(int size)
667 {
668     size = (int) (size / 1.4142);       /* reduce by sqrt(2) */
669
670     tpic_path(size, size);
671     tpic_path(-size, -size);
672     tpic_flush();
673     tpic_path(size, -size);
674     tpic_path(-size, size);
675     tpic_flush();
676     return;
677 }
678
679 static void
680 tpic_triangle(int size)
681 {
682     int x;
683
684     size = (int) (size / 1.6119);       /* reduce by sqrt(3 * sqrt(3) / 2) */
685     x = (int) (size * 1.7321);
686
687     tpic_path(0, -size * 2);
688     tpic_path(-x, size);
689     tpic_path(x, size);
690     tpic_path(0, -size * 2);
691     tpic_flush();
692     return;
693 }
694
695 static void
696 tpic_star(int size)
697 {
698     int x;
699
700     size = (int) (size / 2);    /* reduce by 2 */
701     x = (int) (size * 1.7321);
702
703     tpic_path(0, size * 2);
704     tpic_path(0, -size * 2);
705     tpic_flush();
706     tpic_path(x, size);
707     tpic_path(-x, -size);
708     tpic_flush();
709     tpic_path(x, -size);
710     tpic_path(-x, size);
711     tpic_flush();
712     return;
713 }
714
715 static void
716 tpic_hexagon(int size)
717 {
718     int x;
719
720     size = (int) (size / 2);    /* reduce by 2 */
721     x = (int) (size * 1.7321);
722
723     tpic_path(0, size * 2);
724     tpic_path(-x, size);
725     tpic_path(-x, -size);
726     tpic_path(0, -size * 2);
727     tpic_path(x, -size);
728     tpic_path(x, size);
729     tpic_path(0, size * 2);
730     tpic_flush();
731     return;
732 }
733
734 static void
735 tpic_circle(int size)
736 {
737     tpic_arc(size);
738     return;
739 }
740
741 static void
742 tpic_doublecircle(int size)
743 {
744     tpic_arc(size);
745     tpic_shade(0.0);
746     tpic_arc(size / 2);
747     return;
748 }
749
750 static void
751 tpic_vercircle(int size)                        /* circle with | */
752 {
753     tpic_arc(size);
754     tpic_path(0, size);
755     tpic_path(0, -size);
756     tpic_flush();
757     return;
758 }
759
760 static void
761 tpic_horcircle(int size)                        /* circle with - */
762 {
763     tpic_arc(size);
764     tpic_path(size, 0);
765     tpic_path(-size, 0);
766     tpic_flush();
767     return;
768 }
769
770 static void
771 tpic_pluscircle(int size)                       /* circle with + */
772 {
773     tpic_arc(size);
774     tpic_plus(size);
775     return;
776 }
777
778 static void
779 tpic_timescircle(int size)                      /* circle with times */
780 {
781     tpic_arc(size);
782     tpic_times(size);
783     return;
784 }
785
786 static void
787 tpic_starcircle(int size)                       /* circle with star */
788 {
789     tpic_arc(size);
790     tpic_star(size);
791     return;
792 }
793
794 static void
795 tpic_dotcircle(int size)                        /* circle with dot (black circle) */
796 {
797     tpic_arc(size);
798     tpic_shade(1.0);
799     tpic_arc(size / 2);
800     return;
801 }
802
803 static void
804 tpic_diamondcircle(int size)                    /* not enough? circle with black diamond */
805 {
806     tpic_arc(size);
807     tpic_shade(1.0);
808     tpic_diamond((int) (size / 1.5));
809     return;
810 }
811
812 static void
813 tpic_boxcircle(int size)                        /* need more? circle with black box */
814 {
815     tpic_arc(size);
816     tpic_shade(1.0);
817     tpic_box((int) (size / 1.5));
818     return;
819 }
820
821 static void
822 tpic_trianglecircle(int size)                   /* circle with black triangle */
823 {
824     tpic_arc(size);
825     tpic_shade(1.0);
826     tpic_triangle((int) (size / 1.5));
827     return;
828 }
829
830 static void
831 tpic_hexagoncircle(int size)                    /* how about circle with black hexagon? */
832 {
833     tpic_arc(size);
834     tpic_shade(1.0);
835     tpic_hexagon((int) (size / 1.2));
836     return;
837 }
838
839 static void
840 tpic_plustimescircle(int size)                  /* no more idea ... with plus & times */
841 {
842     tpic_arc(size);
843     tpic_plus(size);
844     tpic_times(size);
845     return;
846 }
847
848 /* private: draw lines */
849
850 static void
851 tpic_abspath(unsigned int x, unsigned int y)
852 {
853     tpic_path(x, -y);
854     fputs("%\n", gpoutfile);
855     return;
856 }
857
858 /* private: tpic primitive functions */
859
860 static void
861 tpic_path(int x, int y)
862 {
863     fprintf(gpoutfile, "\\special{pa %d %d}", x, y);
864     return;
865 }
866
867 static void
868 tpic_flush()
869 {
870     fputs("\\special{fp}%\n", gpoutfile);
871     return;
872 }
873
874 static void
875 tpic_arc(int radius)
876 {
877     /* actually, draw a full circle */
878     fprintf(gpoutfile, "\\special{ar 0 0 %d %d 0 7}", radius, radius);
879     return;
880 }
881
882 static void
883 tpic_shade(double grayscale)
884 {
885     fprintf(gpoutfile, "\\special{sh %f}", grayscale);
886     return;
887 }
888
889 static void
890 tpic_pen(int thickness)
891 {
892     fprintf(gpoutfile, "\\special{pn %d}", thickness);
893     return;
894 }
895
896 static void
897 tpic_dottedflush(double interval)
898 {
899     fprintf(gpoutfile, "\\special{dt %f}%%\n", interval);
900     return;
901 }
902
903 static void
904 tpic_dashedflush(double interval)
905 {
906     fprintf(gpoutfile, "\\special{da %f}%%\n", interval);
907     return;
908 }
909
910 #endif /* TERM_BODY */
911
912 #ifdef TERM_TABLE
913
914 TERM_TABLE_START(tpic_driver)
915     "tpic", "TPIC -- LaTeX picture environment with tpic \\specials",
916     TPIC_XMAX, TPIC_YMAX, TPIC_VCHAR, TPIC_HCHAR,
917     TPIC_VTIC, TPIC_HTIC, TPIC_options, TPIC_init, TPIC_reset,
918     TPIC_text, null_scale, TPIC_graphics, TPIC_move, TPIC_vector,
919     TPIC_linetype, TPIC_put_text, TPIC_text_angle,
920     TPIC_justify_text, TPIC_point, TPIC_arrow, set_font_null
921 TERM_TABLE_END(tpic_driver)
922
923 #undef LAST_TERM
924 #define LAST_TERM tpic_driver
925
926 #endif /* TERM_TABLE */
927 #endif /* TERM_PROTO_ONLY */
928
929 #ifdef TERM_HELP
930 START_HELP(tpic)
931 "1 tpic",
932 "?commands set terminal tpic",
933 "?set terminal tpic",
934 "?set term tpic",
935 "?terminal tpic",
936 "?term tpic",
937 "?tpic",
938 " The `tpic` terminal driver supports the LaTeX picture environment with tpic",
939 " \\specials.  It is an alternative to the `latex` and `eepic` terminal drivers.",
940 " Options are the point size, line width, and dot-dash interval.",
941 "",
942 " Syntax:",
943 "       set terminal tpic <pointsize> <linewidth> <interval>",
944 "",
945 " where `pointsize` and `linewidth` are integers in milli-inches and `interval`",
946 " is a float in inches.  If a non-positive value is specified, the default is",
947 " chosen: pointsize = 40, linewidth = 6, interval = 0.1.",
948 "",
949 " All drivers for LaTeX offer a special way of controlling text positioning:",
950 " If any text string begins with '{', you also need to include a '}' at the",
951 " end of the text, and the whole text will be centered both horizontally",
952 " and vertically by LaTeX. --- If the text string begins with '[', you need",
953 " to continue it with: a position specification (up to two out of t,b,l,r),",
954 " ']{', the text itself, and finally, '}'. The text itself may be anything",
955 " LaTeX can typeset as an LR-box. \\rule{}{}'s may help for best positioning.",
956 "",
957 " Examples:",
958 " About label positioning:",
959 " Use gnuplot defaults (mostly sensible, but sometimes not really best):",
960 "        set title '\\LaTeX\\ -- $ \\gamma $'",
961 " Force centering both horizontally and vertically:",
962 "        set label '{\\LaTeX\\ -- $ \\gamma $}' at 0,0",
963 " Specify own positioning (top here):",
964 "        set xlabel '[t]{\\LaTeX\\ -- $ \\gamma $}'",
965 " The other label -- account for long ticlabels:",
966 "        set ylabel '[r]{\\LaTeX\\ -- $ \\gamma $\\rule{7mm}{0pt}}'"
967 END_HELP(tpic)
968 #endif /* TERM_TABLE */