--- /dev/null
+/* Hello, Emacs, this is -*-C-*-
+ * $Id: tpic.trm,v 1.21 2006/07/21 02:35:48 sfeam Exp $
+ */
+
+/* GNUPLOT - tpic.trm */
+
+/*[
+ * Copyright 1990 - 1993, 1998, 2004
+ *
+ * Permission to use, copy, and distribute this software and its
+ * documentation for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.
+ *
+ * Permission to modify the software is granted, but not the right to
+ * distribute the complete modified source code. Modifications are to
+ * be distributed as patches to the released version. Permission to
+ * distribute binaries produced by compiling modified sources is granted,
+ * provided you
+ * 1. distribute the corresponding source modifications from the
+ * released version in the form of a patch file along with the binaries,
+ * 2. add special version identification to distinguish your version
+ * in addition to the base release version number,
+ * 3. provide your name and address as the primary contact for the
+ * support of your modified version, and
+ * 4. retain our contact information in regard to use of the base
+ * software.
+ * Permission to distribute the released version of the source code along
+ * with corresponding source modifications in the form of a patch file is
+ * granted with same provisions 2 through 4 for binary distributions.
+ *
+ * This software is provided "as is" without express or implied warranty
+ * to the extent permitted by applicable law.
+]*/
+
+/*
+ * This file is included by ../term.c.
+ *
+ * This terminal driver supports:
+ * The tpic \specials (version 2.2) for LaTeX.
+ *
+ * AUTHORS
+ * Oh-Yeah? 3 Sep. 1992 (closely following eepic.trm by David Kotz)
+ * A. Woo 5 Oct. 1992 (removed ansi prototypes for braindead compilers)
+ *
+ * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
+ *
+ */
+/*
+ * This file contains the tpic terminal driver for use with LaTeX.
+ * This is an alternative to the latex and eepic drivers. You need
+ * a printer driver that supports the tpic \specials version 2.2.
+ *
+ * Comparison with the eepic driver (eepic.trm):
+ * Merits
+ * - More point and line types
+ * - Options to change point size, linewidth, dot & dash intervals
+ * - Dotted and dashed lines for high-sample-rate curves (but may
+ * depend on tpic (da & dt) implementation of your dvi driver :-)
+ * - Overlapped points made fancier by tpic shading facility
+ * - Optional comments for trimming figure margins
+ * - No need for epic and eepic macros
+ * Drawback
+ * - You cannot use eepicemu macro for non-tpic-support dvi drivers
+ *
+ * LATEX must also be defined.
+ */
+
+
+/* These parameters can be modified as you like, through options. Say
+ "set terminal tpic <pointsize> <linewidth> <interval>". <pointsize>
+ and <linewidth> are integers in milli-inches; <interval> is a float
+ in inches. If non-positive value is specified, the default (below)
+ is chosen.
+*/
+
+/*
+ * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
+ */
+
+#include "driver.h"
+
+#ifdef TERM_REGISTER
+register_term(tpic)
+#endif
+
+#ifdef TERM_PROTO
+TERM_PUBLIC void TPIC_options __PROTO((void)); /* get size options */
+TERM_PUBLIC void TPIC_init __PROTO((void));
+TERM_PUBLIC void TPIC_reset __PROTO((void));
+TERM_PUBLIC void TPIC_text __PROTO((void));
+TERM_PUBLIC void TPIC_graphics __PROTO((void));
+TERM_PUBLIC void TPIC_move __PROTO((unsigned int x, unsigned int y));
+TERM_PUBLIC void TPIC_vector __PROTO((unsigned int ux, unsigned int uy));
+TERM_PUBLIC void TPIC_linetype __PROTO((int linetype));
+TERM_PUBLIC void TPIC_put_text __PROTO((unsigned int x, unsigned int y, const char *str)); /* ref point and text */
+TERM_PUBLIC int TPIC_text_angle __PROTO((int ang));
+TERM_PUBLIC int TPIC_justify_text __PROTO((enum JUSTIFY mode));
+TERM_PUBLIC void TPIC_point __PROTO((unsigned int x, unsigned int y, int number));
+TERM_PUBLIC void TPIC_arrow __PROTO((unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, int head));
+
+/* tpic \specials unit in inches (1 milli-inch) */
+#define TPIC_UNIT 0.001
+
+/* 5 inches wide by 3 inches high (default) */
+#define TPIC_XMAX (unsigned int) (5 / TPIC_UNIT)
+#define TPIC_YMAX (unsigned int) (3 / TPIC_UNIT)
+#define TPIC_PTS_PER_UNIT (72.27 * TPIC_UNIT)
+#define TPIC_HTIC (unsigned int) ( 5.0 / TPIC_PTS_PER_UNIT) /* 5pt */
+#define TPIC_VTIC (unsigned int) ( 5.0 / TPIC_PTS_PER_UNIT) /* 5pt */
+#define TPIC_HCHAR (unsigned int) ( 5.3 / TPIC_PTS_PER_UNIT) /* 5.3pt */
+#define TPIC_VCHAR (unsigned int) (11.0 / TPIC_PTS_PER_UNIT) /* 11pt */
+#endif /* TERM_PROTO */
+
+#ifndef TERM_PROTO_ONLY
+#ifdef TERM_BODY
+static int tpic_pointsize = 40; /* min point radius (in milli-inches) */
+static int tpic_linewidth = 6; /* min line thickness (in milli-inches) */
+static double tpic_interval = 0.1; /* min dot & dash intervals (in inches) */
+
+/* ARROWS: same code as for LATEX */
+/* figure out the best arrow. in latex.trm */
+static void best_latex_arrow __PROTO((int sx, int sy, int ex, int ey, int who, int head));
+
+/* all prototypes ... */
+static void tpic_startline __PROTO((void));
+static void tpic_endline __PROTO((void));
+static void tpic_pushpath __PROTO((unsigned int x, unsigned int y));
+static void tpic_scanpath __PROTO((void));
+static void tpic_diamond __PROTO((int size));
+static void tpic_plus __PROTO((int size));
+static void tpic_box __PROTO((int size));
+static void tpic_times __PROTO((int size));
+static void tpic_triangle __PROTO((int size));
+static void tpic_star __PROTO((int size));
+static void tpic_hexagon __PROTO((int size));
+static void tpic_circle __PROTO((int size));
+static void tpic_doublecircle __PROTO((int size));
+static void tpic_vercircle __PROTO((int size)); /* circle with | */
+static void tpic_horcircle __PROTO((int size)); /* circle with - */
+static void tpic_pluscircle __PROTO((int size)); /* circle with + */
+static void tpic_timescircle __PROTO((int size)); /* circle with times */
+static void tpic_starcircle __PROTO((int size)); /* circle with star */
+static void tpic_dotcircle __PROTO((int size)); /* circle with dot (black circle) */
+static void tpic_diamondcircle __PROTO((int size)); /* circle with black diamond */
+static void tpic_boxcircle __PROTO((int size)); /* circle with black box */
+static void tpic_trianglecircle __PROTO((int size)); /* circle with black triangle */
+static void tpic_hexagoncircle __PROTO((int size)); /* circle with black hexagon */
+static void tpic_plustimescircle __PROTO((int size)); /* no more idea ... with plus & times */
+static void tpic_abspath __PROTO((unsigned int x, unsigned int y)); /* absolute coord */
+static void tpic_path __PROTO((int x, int y));
+static void tpic_flush __PROTO((void));
+static void tpic_arc __PROTO((int radius)); /* actually, draw a full circle */
+static void tpic_shade __PROTO((double grayscale));
+static void tpic_pen __PROTO((int thickness));
+static void tpic_dottedflush __PROTO((double interval));
+static void tpic_dashedflush __PROTO((double interval));
+
+typedef enum {
+ tpic_none, tpic_white, tpic_gray, tpic_black
+} tpic_shadestyle;
+typedef enum {
+ tpic_nosize, tpic_small, tpic_medium, tpic_large
+} tpic_size;
+typedef void (*tpic_function) __PROTO((int size));
+
+typedef struct {
+ tpic_shadestyle shadestyle;
+ tpic_size size;
+ tpic_function function;
+} tpic_point_info;
+
+/* POINTS */
+static /*GPFAR */ tpic_point_info GPFAR tpic_point[] =
+{
+ {tpic_white, tpic_medium, tpic_diamond},
+ {tpic_none, tpic_medium, tpic_plus},
+ {tpic_white, tpic_medium, tpic_box},
+ {tpic_none, tpic_medium, tpic_times},
+ {tpic_white, tpic_medium, tpic_triangle},
+ {tpic_none, tpic_medium, tpic_star},
+ {tpic_white, tpic_small, tpic_circle},
+ {tpic_white, tpic_medium, tpic_circle},
+ {tpic_white, tpic_large, tpic_circle},
+ {tpic_black, tpic_small, tpic_circle},
+ {tpic_black, tpic_medium, tpic_circle},
+ {tpic_black, tpic_large, tpic_circle},
+ {tpic_black, tpic_medium, tpic_diamond},
+ {tpic_black, tpic_medium, tpic_box},
+ {tpic_black, tpic_medium, tpic_triangle},
+ {tpic_white, tpic_medium, tpic_hexagon},
+ {tpic_black, tpic_medium, tpic_hexagon},
+ {tpic_white, tpic_medium, tpic_doublecircle},
+ {tpic_white, tpic_medium, tpic_vercircle},
+ {tpic_white, tpic_medium, tpic_horcircle},
+ {tpic_white, tpic_medium, tpic_pluscircle},
+ {tpic_white, tpic_medium, tpic_timescircle},
+ {tpic_white, tpic_medium, tpic_starcircle},
+ {tpic_black, tpic_medium, tpic_doublecircle},
+ {tpic_white, tpic_medium, tpic_dotcircle},
+ {tpic_white, tpic_medium, tpic_diamondcircle},
+ {tpic_white, tpic_medium, tpic_boxcircle},
+ {tpic_white, tpic_medium, tpic_trianglecircle},
+ {tpic_white, tpic_medium, tpic_hexagoncircle},
+ {tpic_white, tpic_medium, tpic_plustimescircle}
+};
+
+typedef enum {
+ tpic_solid, tpic_dotted, tpic_dashed,
+ tpic_dashed_sdot, tpic_dashed_ddot
+} tpic_linestyle;
+typedef struct {
+ tpic_size thickness, interval;
+ tpic_linestyle linestyle;
+} tpic_line_info;
+
+/* LINES */
+static /*GPFAR */ tpic_line_info GPFAR tpic_line[] =
+{
+ {tpic_medium, tpic_nosize, tpic_solid}, /* -2 border */
+ {tpic_small, tpic_small, tpic_dashed}, /* -1 axes */
+ {tpic_small, tpic_nosize, tpic_solid},
+ {tpic_medium, tpic_nosize, tpic_solid},
+ {tpic_large, tpic_nosize, tpic_solid},
+ {tpic_small, tpic_small, tpic_dotted},
+ {tpic_medium, tpic_small, tpic_dotted},
+ {tpic_large, tpic_small, tpic_dotted},
+ {tpic_small, tpic_small, tpic_dashed},
+ {tpic_medium, tpic_small, tpic_dashed},
+ {tpic_large, tpic_small, tpic_dashed},
+ {tpic_small, tpic_small, tpic_dashed_sdot}, /* dash with single dots */
+ {tpic_medium, tpic_small, tpic_dashed_sdot},
+ {tpic_large, tpic_small, tpic_dashed_sdot},
+ {tpic_small, tpic_small, tpic_dashed_ddot}, /* dash with double dots */
+ {tpic_medium, tpic_small, tpic_dashed_ddot},
+ {tpic_large, tpic_small, tpic_dashed_ddot},
+ {tpic_small, tpic_medium, tpic_dotted},
+ {tpic_medium, tpic_medium, tpic_dotted},
+ {tpic_large, tpic_medium, tpic_dotted},
+ {tpic_small, tpic_medium, tpic_dashed},
+ {tpic_medium, tpic_medium, tpic_dashed},
+ {tpic_large, tpic_medium, tpic_dashed},
+ {tpic_small, tpic_medium, tpic_dashed_sdot},
+ {tpic_medium, tpic_medium, tpic_dashed_sdot},
+ {tpic_large, tpic_medium, tpic_dashed_sdot},
+ {tpic_small, tpic_medium, tpic_dashed_ddot},
+ {tpic_medium, tpic_medium, tpic_dashed_ddot},
+ {tpic_large, tpic_medium, tpic_dashed_ddot},
+ {tpic_small, tpic_large, tpic_dotted},
+ {tpic_medium, tpic_large, tpic_dotted},
+ {tpic_large, tpic_large, tpic_dotted},
+ {tpic_small, tpic_large, tpic_dashed},
+ {tpic_medium, tpic_large, tpic_dashed},
+ {tpic_large, tpic_large, tpic_dashed},
+ {tpic_small, tpic_large, tpic_dashed_sdot},
+ {tpic_medium, tpic_large, tpic_dashed_sdot},
+ {tpic_large, tpic_large, tpic_dashed_sdot},
+ {tpic_small, tpic_large, tpic_dashed_ddot},
+ {tpic_medium, tpic_large, tpic_dashed_ddot},
+ {tpic_large, tpic_large, tpic_dashed_ddot}
+};
+
+TERM_PUBLIC void
+TPIC_options()
+{ /* get size options */
+ struct value a;
+ int ptsize, linewidth;
+ double interval;
+
+ if (!END_OF_COMMAND) {
+ ptsize = (int) real(const_express(&a));
+ if (ptsize > 0)
+ tpic_pointsize = ptsize;
+ }
+ if (!END_OF_COMMAND) {
+ linewidth = (int) real(const_express(&a));
+ if (linewidth > 0)
+ tpic_linewidth = linewidth;
+ }
+ if (!END_OF_COMMAND) {
+ interval = (double) real(const_express(&a));
+ if (interval > 0)
+ tpic_interval = interval;
+ }
+ sprintf(term_options, "%d %d %f", tpic_pointsize, tpic_linewidth,
+ tpic_interval);
+}
+
+static unsigned int tpic_posx; /* current position */
+static unsigned int tpic_posy;
+static int tpic_point_types;
+static int tpic_numlines;
+
+TERM_PUBLIC void
+TPIC_init()
+{
+ static char GPFAR tpic1[] = "\
+%% GNUPLOT: LaTeX picture using tpic \\specials\n\
+%% with %d point types and %d line types\n\
+%% Options: pointsize = %d, linewidth = %d, interval = %f\n\
+%% To change above options, say:\n\
+%% set terminal tpic pointsize_value linewidth_value interval_value\n\
+%% (pointsize and linewidth - integers in milli-inches.\n\
+%% interval - a float in inches. If zero is specified, \n\
+%% the default value is chosen.)\n\
+\\setlength{\\unitlength}{%fin}%%\n";
+ tpic_point_types = sizeof(tpic_point) / sizeof(tpic_point[0]);
+ tpic_numlines = sizeof(tpic_line) / sizeof(tpic_line[0]);
+
+ tpic_posx = tpic_posy = 0;
+ TPIC_linetype(-1);
+ fprintf(gpoutfile, tpic1,
+ tpic_point_types, tpic_numlines - 2,
+ tpic_pointsize, tpic_linewidth, tpic_interval,
+ TPIC_UNIT);
+}
+
+TERM_PUBLIC void
+TPIC_reset()
+{
+ tpic_endline();
+ tpic_posx = tpic_posy = 0;
+}
+
+TERM_PUBLIC void
+TPIC_text()
+{
+ tpic_endline();
+ fputs("\\end{picture}\n", gpoutfile);
+}
+
+TERM_PUBLIC void
+TPIC_graphics()
+{
+ register struct termentry *t = term;
+ int left, right, top, bottom; /* margins */
+ static char GPFAR begin[] = "%s\\begin{picture}(%d,%d)(%d,%d)%% %s\n";
+
+ fprintf(gpoutfile, begin, "", t->xmax, t->ymax, 0, 0, "");
+
+ /* the following is dependent on boundary() function in graphics.c */
+ left = TPIC_HCHAR * 12;
+ right = TPIC_HCHAR * 2 + TPIC_HTIC;
+ bottom = TPIC_VCHAR * 7 / 2 + 1;
+ top = TPIC_VCHAR * 5 / 2 - 1;
+ fprintf(gpoutfile, begin, "%% ", t->xmax - left, t->ymax, left, 0,
+ "trim left margin");
+ fprintf(gpoutfile, begin, "%% ", t->xmax - right, t->ymax, 0, 0,
+ "trim right margin");
+ fprintf(gpoutfile, begin, "%% ", t->xmax - left - right, t->ymax, left, 0,
+ "trim left & right margins");
+ fprintf(gpoutfile, begin, "%% ", t->xmax, t->ymax - top, 0, 0,
+ "trim top margin");
+ fprintf(gpoutfile, begin, "%% ", t->xmax, t->ymax - bottom, 0, bottom,
+ "trim bottom margin");
+ fprintf(gpoutfile, begin, "%% ", t->xmax, t->ymax - top - bottom, 0, bottom,
+ "trim top & bottom margins");
+
+ fputs("\\footnotesize%\n", gpoutfile);
+}
+
+TERM_PUBLIC void
+TPIC_move(unsigned int x, unsigned int y)
+{
+ tpic_endline();
+ tpic_posx = x;
+ tpic_posy = y;
+}
+
+#define TPIC_LINEMAX 100 /* max value for linecount */
+static TBOOLEAN tpic_inline = FALSE; /* are we in the middle of a line */
+static int tpic_linecount = 0; /* number of points in line so far */
+
+TERM_PUBLIC void
+TPIC_vector(unsigned int ux, unsigned int uy)
+{
+ if (!tpic_inline) {
+ tpic_startline();
+ } else if (tpic_linecount >= TPIC_LINEMAX) {
+ /* Even though we are in middle of a path, we may start a new path
+ command once in a while; if they are too long, latex will choke. */
+ tpic_endline();
+ tpic_startline();
+ }
+ tpic_pushpath(ux, uy);
+ tpic_posx = ux;
+ tpic_posy = uy;
+}
+
+static int tpic_linetype; /* current line type */
+
+static void
+tpic_startline()
+{ /* private */
+ int thickness = 1;
+
+ tpic_inline = TRUE;
+ switch (tpic_line[tpic_linetype + 2].thickness) {
+ case tpic_small:
+ thickness = tpic_linewidth;
+ break;
+ case tpic_medium:
+ thickness = (int) (tpic_linewidth * 3);
+ break;
+ case tpic_large:
+ thickness = (int) (tpic_linewidth * 5);
+ break;
+ default:
+ break;
+ }
+ tpic_pen(thickness);
+ tpic_linecount = 0;
+ tpic_pushpath(tpic_posx, tpic_posy);
+ return;
+}
+
+static void
+tpic_endline()
+{ /* private */
+ double interval = 1;
+
+ if (tpic_inline) {
+ tpic_scanpath(); /* draw actually */
+ switch (tpic_line[tpic_linetype + 2].interval) {
+ case tpic_small:
+ interval = tpic_interval;
+ break;
+ case tpic_medium:
+ interval = tpic_interval * 2;
+ break;
+ case tpic_large:
+ interval = tpic_interval * 3;
+ break;
+ case tpic_nosize:
+ break;
+ }
+ switch (tpic_line[tpic_linetype + 2].linestyle) {
+ case tpic_solid:
+ tpic_flush();
+ break;
+ case tpic_dotted:
+ tpic_dottedflush(interval);
+ break;
+ case tpic_dashed:
+ tpic_dashedflush(interval);
+ break;
+ case tpic_dashed_sdot: /* dashed with single dots in between */
+ tpic_dashedflush(interval);
+ tpic_scanpath(); /* draw again */
+ tpic_dottedflush(interval / 2);
+ break;
+ case tpic_dashed_ddot: /* dashed with double dots in between */
+ tpic_dashedflush(interval);
+ tpic_scanpath(); /* draw again */
+ tpic_dottedflush(interval / 3);
+ break;
+ }
+ tpic_inline = FALSE;
+ }
+ return;
+}
+
+/* private: stack functions */
+static unsigned int pathpoint[TPIC_LINEMAX][2]; /* point stack */
+
+static void
+tpic_pushpath(unsigned int x, unsigned int y)
+{
+ if (tpic_linecount < TPIC_LINEMAX) {
+ pathpoint[tpic_linecount][0] = x;
+ pathpoint[tpic_linecount][1] = y;
+ tpic_linecount++;
+ }
+ return;
+}
+
+static void
+tpic_scanpath()
+{
+ int i;
+
+ for (i = 0; i < tpic_linecount; i++)
+ tpic_abspath(pathpoint[i][0], pathpoint[i][1]);
+ return;
+}
+
+TERM_PUBLIC void
+TPIC_linetype(int linetype)
+{
+ tpic_endline();
+ if (linetype < -2)
+ linetype = LT_BLACK;
+ if (linetype >= tpic_numlines - 2)
+ linetype %= (tpic_numlines - 2);
+ tpic_linetype = linetype;
+}
+
+static int tpic_angle = 0; /* 0 = horizontal, 1 = vertical */
+static enum JUSTIFY tpic_justify = LEFT;
+
+TERM_PUBLIC void
+TPIC_put_text(unsigned int x, unsigned int y, const char *str)
+{
+ char *justify = NULL;
+
+ tpic_endline();
+ fprintf(gpoutfile, "\\put(%d,%d)", x, y);
+
+ if ((str[0] == '{') || (str[0] == '[')) {
+ fprintf(gpoutfile, "{\\makebox(0,0)%s}\n", str);
+ } else
+ switch (tpic_angle) {
+ case 0: /* horizontal */
+ switch (tpic_justify) {
+ case LEFT:
+ justify = "[l]";
+ break;
+ case CENTRE:
+ justify = "";
+ break;
+ case RIGHT:
+ justify = "[r]";
+ break;
+ }
+ fprintf(gpoutfile, "{\\makebox(0,0)%s{%s}}\n", justify, str);
+ break;
+ case 1: /* vertical */
+ /* we can't really write text vertically, but will put the ylabel
+ centred at the left of the plot, and then we'll make a \shortstack */
+ switch (tpic_justify) {
+ case LEFT:
+ justify = "[lb]";
+ break;
+ case CENTRE:
+ justify = "[l]";
+ break;
+ case RIGHT:
+ justify = "[lt]";
+ break;
+ }
+ fprintf(gpoutfile, "{\\makebox(0,0)%s{\\shortstack{%s}}}\n",
+ justify, str);
+ break;
+ }
+}
+
+TERM_PUBLIC int
+TPIC_text_angle(int ang)
+{
+ tpic_angle = (ang ? 1 : 0);
+ return (TRUE);
+}
+
+TERM_PUBLIC int
+TPIC_justify_text(enum JUSTIFY mode)
+{
+ tpic_justify = mode;
+ return (TRUE);
+}
+
+TERM_PUBLIC void
+TPIC_point(unsigned int x, unsigned int y, int number)
+{
+ int size = 0;
+
+ TPIC_move(x, y);
+
+ /* Print the character defined by 'number'; number < 0 means
+ to use a dot, otherwise one of the defined points. */
+
+ fprintf(gpoutfile, "\\put(%d,%d){", x, y); /* start putting */
+
+ if (number < 0) {
+ fputs("\\rule{.1pt}{.1pt}", gpoutfile); /* tiny dot */
+ } else {
+ number %= tpic_point_types;
+ switch (tpic_point[number].shadestyle) {
+ case tpic_white:
+ tpic_pen(tpic_linewidth); /* set it thin */
+ tpic_shade(0.0);
+ break;
+ case tpic_gray:
+ tpic_pen(tpic_linewidth);
+ tpic_shade(0.5);
+ break;
+ case tpic_black:
+ tpic_pen(tpic_linewidth);
+ tpic_shade(1.0);
+ break;
+ case tpic_none:
+ tpic_pen(tpic_linewidth * 3); /* set it thick */
+ break;
+ }
+ switch (tpic_point[number].size) {
+ case tpic_small:
+ size = tpic_pointsize;
+ break;
+ case tpic_medium:
+ size = (int) (tpic_pointsize * 1.4142);
+ break;
+ case tpic_large:
+ size = (int) (tpic_pointsize * 2.0);
+ break;
+ default:
+ break;
+ }
+ (tpic_point[number].function) (size);
+ }
+
+ fputs("}%%\n", gpoutfile); /* end putting */
+}
+
+TERM_PUBLIC void
+TPIC_arrow(
+ unsigned int sx, unsigned int sy,
+ unsigned int ex, unsigned int ey,
+ int head)
+{
+ best_latex_arrow(sx, sy, ex, ey, 1, head); /* call latex routine */
+ tpic_posx = ex;
+ tpic_posy = ey;
+}
+
+/* private: draw points with tpic commands */
+
+static void
+tpic_diamond(int size)
+{
+ size = (int) (size * 1.4142); /* spread by sqrt(2) */
+
+ tpic_path(0, size);
+ tpic_path(-size, 0);
+ tpic_path(0, -size);
+ tpic_path(size, 0);
+ tpic_path(0, size);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_plus(int size)
+{
+ tpic_path(0, size);
+ tpic_path(0, -size);
+ tpic_flush();
+ tpic_path(size, 0);
+ tpic_path(-size, 0);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_box(int size)
+{
+ tpic_path(size, size);
+ tpic_path(-size, size);
+ tpic_path(-size, -size);
+ tpic_path(size, -size);
+ tpic_path(size, size);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_times(int size)
+{
+ size = (int) (size / 1.4142); /* reduce by sqrt(2) */
+
+ tpic_path(size, size);
+ tpic_path(-size, -size);
+ tpic_flush();
+ tpic_path(size, -size);
+ tpic_path(-size, size);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_triangle(int size)
+{
+ int x;
+
+ size = (int) (size / 1.6119); /* reduce by sqrt(3 * sqrt(3) / 2) */
+ x = (int) (size * 1.7321);
+
+ tpic_path(0, -size * 2);
+ tpic_path(-x, size);
+ tpic_path(x, size);
+ tpic_path(0, -size * 2);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_star(int size)
+{
+ int x;
+
+ size = (int) (size / 2); /* reduce by 2 */
+ x = (int) (size * 1.7321);
+
+ tpic_path(0, size * 2);
+ tpic_path(0, -size * 2);
+ tpic_flush();
+ tpic_path(x, size);
+ tpic_path(-x, -size);
+ tpic_flush();
+ tpic_path(x, -size);
+ tpic_path(-x, size);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_hexagon(int size)
+{
+ int x;
+
+ size = (int) (size / 2); /* reduce by 2 */
+ x = (int) (size * 1.7321);
+
+ tpic_path(0, size * 2);
+ tpic_path(-x, size);
+ tpic_path(-x, -size);
+ tpic_path(0, -size * 2);
+ tpic_path(x, -size);
+ tpic_path(x, size);
+ tpic_path(0, size * 2);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_circle(int size)
+{
+ tpic_arc(size);
+ return;
+}
+
+static void
+tpic_doublecircle(int size)
+{
+ tpic_arc(size);
+ tpic_shade(0.0);
+ tpic_arc(size / 2);
+ return;
+}
+
+static void
+tpic_vercircle(int size) /* circle with | */
+{
+ tpic_arc(size);
+ tpic_path(0, size);
+ tpic_path(0, -size);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_horcircle(int size) /* circle with - */
+{
+ tpic_arc(size);
+ tpic_path(size, 0);
+ tpic_path(-size, 0);
+ tpic_flush();
+ return;
+}
+
+static void
+tpic_pluscircle(int size) /* circle with + */
+{
+ tpic_arc(size);
+ tpic_plus(size);
+ return;
+}
+
+static void
+tpic_timescircle(int size) /* circle with times */
+{
+ tpic_arc(size);
+ tpic_times(size);
+ return;
+}
+
+static void
+tpic_starcircle(int size) /* circle with star */
+{
+ tpic_arc(size);
+ tpic_star(size);
+ return;
+}
+
+static void
+tpic_dotcircle(int size) /* circle with dot (black circle) */
+{
+ tpic_arc(size);
+ tpic_shade(1.0);
+ tpic_arc(size / 2);
+ return;
+}
+
+static void
+tpic_diamondcircle(int size) /* not enough? circle with black diamond */
+{
+ tpic_arc(size);
+ tpic_shade(1.0);
+ tpic_diamond((int) (size / 1.5));
+ return;
+}
+
+static void
+tpic_boxcircle(int size) /* need more? circle with black box */
+{
+ tpic_arc(size);
+ tpic_shade(1.0);
+ tpic_box((int) (size / 1.5));
+ return;
+}
+
+static void
+tpic_trianglecircle(int size) /* circle with black triangle */
+{
+ tpic_arc(size);
+ tpic_shade(1.0);
+ tpic_triangle((int) (size / 1.5));
+ return;
+}
+
+static void
+tpic_hexagoncircle(int size) /* how about circle with black hexagon? */
+{
+ tpic_arc(size);
+ tpic_shade(1.0);
+ tpic_hexagon((int) (size / 1.2));
+ return;
+}
+
+static void
+tpic_plustimescircle(int size) /* no more idea ... with plus & times */
+{
+ tpic_arc(size);
+ tpic_plus(size);
+ tpic_times(size);
+ return;
+}
+
+/* private: draw lines */
+
+static void
+tpic_abspath(unsigned int x, unsigned int y)
+{
+ tpic_path(x, -y);
+ fputs("%\n", gpoutfile);
+ return;
+}
+
+/* private: tpic primitive functions */
+
+static void
+tpic_path(int x, int y)
+{
+ fprintf(gpoutfile, "\\special{pa %d %d}", x, y);
+ return;
+}
+
+static void
+tpic_flush()
+{
+ fputs("\\special{fp}%\n", gpoutfile);
+ return;
+}
+
+static void
+tpic_arc(int radius)
+{
+ /* actually, draw a full circle */
+ fprintf(gpoutfile, "\\special{ar 0 0 %d %d 0 7}", radius, radius);
+ return;
+}
+
+static void
+tpic_shade(double grayscale)
+{
+ fprintf(gpoutfile, "\\special{sh %f}", grayscale);
+ return;
+}
+
+static void
+tpic_pen(int thickness)
+{
+ fprintf(gpoutfile, "\\special{pn %d}", thickness);
+ return;
+}
+
+static void
+tpic_dottedflush(double interval)
+{
+ fprintf(gpoutfile, "\\special{dt %f}%%\n", interval);
+ return;
+}
+
+static void
+tpic_dashedflush(double interval)
+{
+ fprintf(gpoutfile, "\\special{da %f}%%\n", interval);
+ return;
+}
+
+#endif /* TERM_BODY */
+
+#ifdef TERM_TABLE
+
+TERM_TABLE_START(tpic_driver)
+ "tpic", "TPIC -- LaTeX picture environment with tpic \\specials",
+ TPIC_XMAX, TPIC_YMAX, TPIC_VCHAR, TPIC_HCHAR,
+ TPIC_VTIC, TPIC_HTIC, TPIC_options, TPIC_init, TPIC_reset,
+ TPIC_text, null_scale, TPIC_graphics, TPIC_move, TPIC_vector,
+ TPIC_linetype, TPIC_put_text, TPIC_text_angle,
+ TPIC_justify_text, TPIC_point, TPIC_arrow, set_font_null
+TERM_TABLE_END(tpic_driver)
+
+#undef LAST_TERM
+#define LAST_TERM tpic_driver
+
+#endif /* TERM_TABLE */
+#endif /* TERM_PROTO_ONLY */
+
+#ifdef TERM_HELP
+START_HELP(tpic)
+"1 tpic",
+"?commands set terminal tpic",
+"?set terminal tpic",
+"?set term tpic",
+"?terminal tpic",
+"?term tpic",
+"?tpic",
+" The `tpic` terminal driver supports the LaTeX picture environment with tpic",
+" \\specials. It is an alternative to the `latex` and `eepic` terminal drivers.",
+" Options are the point size, line width, and dot-dash interval.",
+"",
+" Syntax:",
+" set terminal tpic <pointsize> <linewidth> <interval>",
+"",
+" where `pointsize` and `linewidth` are integers in milli-inches and `interval`",
+" is a float in inches. If a non-positive value is specified, the default is",
+" chosen: pointsize = 40, linewidth = 6, interval = 0.1.",
+"",
+" All drivers for LaTeX offer a special way of controlling text positioning:",
+" If any text string begins with '{', you also need to include a '}' at the",
+" end of the text, and the whole text will be centered both horizontally",
+" and vertically by LaTeX. --- If the text string begins with '[', you need",
+" to continue it with: a position specification (up to two out of t,b,l,r),",
+" ']{', the text itself, and finally, '}'. The text itself may be anything",
+" LaTeX can typeset as an LR-box. \\rule{}{}'s may help for best positioning.",
+"",
+" Examples:",
+" About label positioning:",
+" Use gnuplot defaults (mostly sensible, but sometimes not really best):",
+" set title '\\LaTeX\\ -- $ \\gamma $'",
+" Force centering both horizontally and vertically:",
+" set label '{\\LaTeX\\ -- $ \\gamma $}' at 0,0",
+" Specify own positioning (top here):",
+" set xlabel '[t]{\\LaTeX\\ -- $ \\gamma $}'",
+" The other label -- account for long ticlabels:",
+" set ylabel '[r]{\\LaTeX\\ -- $ \\gamma $\\rule{7mm}{0pt}}'"
+END_HELP(tpic)
+#endif /* TERM_TABLE */