- Optification is done by auto builder now
[gnuplot] / term / pslatex.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: pslatex.trm,v 1.69.2.3 2009/05/11 21:47:30 sfeam Exp $
3  */
4
5 /* GNUPLOT - pslatex.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 file supplies the terminal drivers:
41  *     pslatex  -- LaTeX with embedded postscript
42  *     pstex    -- plain TeX with embedded postscript
43  *     epslatex -- LaTeX using \includegraphics, postscript part in an 
44  *                 external file
45  *
46  * AUTHORS
47  *  George Phillips
48  *  Russell Lang
49  *  David Kotz
50  *
51  *  Petr Mikulik, May 2000: terminal entries for PM3D functionality
52  *
53  *  Dan Sebald, 5 March 2003: terminal entry for image functionality
54  *
55  *  Theo Hopman
56  *      23 May 2003:
57  *              - added epslatex support. Replaces epslatex.trm; pointtype
58  *              and linetypes for epslatex terminal are now identical to
59  *              those of pslatex terminal.
60  *              - added arbitrary text rotations to all [e]ps[la]tex
61  *              terminals.
62  *      27 May 2004:
63  *              - epslatex patch updated for gnuplot 4.0
64  *      
65  *  Harald Harders (h.harders@tu-bs.de), 2005-02-08:
66  *  - Merged functionality of postscript, pslatex, pstex, and
67  *    epslatex terminals. Therefore deleted epslatex.trm.
68  *  - Added a standalone mode to the epslatex mode for standalone use without
69  *    an additional LaTeX document.
70  *  - Fixed text rotation of ps(la)tex terminals.
71  *
72  * Send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
73  */
74
75 #include "driver.h"
76
77 #ifdef TERM_REGISTER
78 register_term(pslatex)
79 register_term(pstex)
80 register_term(epslatex)
81 #endif
82
83 #ifdef TERM_PROTO
84 /* Common functions for epslatex and ps(la)tex */
85 /* All these routines begin with PSLATEX_ */
86 TERM_PUBLIC void PSLATEX_reset __PROTO((void));
87
88 /* Functions for ps(la)tex */
89 /* All these routines begin with PSTEX_ */
90 TERM_PUBLIC void PSTEX_reopen_output __PROTO((void));
91 TERM_PUBLIC void PSTEX_common_init __PROTO((void));
92 TERM_PUBLIC void PSTEX_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
93 TERM_PUBLIC void PSTEX_text __PROTO((void));
94
95 /* Functions for epslatex */
96 /* All these routines begin with EPSLATEX_ */
97 TERM_PUBLIC void EPSLATEX_reopen_output __PROTO((void));
98 TERM_PUBLIC void EPSLATEX_common_init __PROTO((void));
99 TERM_PUBLIC void EPSLATEX_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
100 TERM_PUBLIC void EPSLATEX_linetype __PROTO((int linetype));
101 TERM_PUBLIC void EPSLATEX_layer __PROTO((t_termlayer syncpoint));
102
103 /* additional LaTeX header information for epslatex terminal */
104 TERM_PUBLIC char *epslatex_header = NULL;
105
106 #endif /* TERM_PROTO */
107
108
109 #ifndef TERM_PROTO_ONLY
110
111 #ifdef TERM_BODY
112
113 #include "post.h"
114
115 struct pstex_text_command {
116     int x, y, angle, justify;
117     char *label;
118     struct pstex_text_command *next;
119 };
120
121 static struct pstex_text_command *pstex_labels = NULL;
122 static int epslatex_text_layer = 0;
123
124 /* Support for optimization of set_color */
125 static t_colorspec tex_previous_colorspec = {-1, 0, 0.0};  /* Initialize to invalid type */
126 static char tex_current_color[64];
127 static TBOOLEAN tex_color_synced = FALSE;
128
129 #define EPSLATEX_sync_color \
130     do { \
131         if (!tex_color_synced) { \
132             fputs(tex_current_color,gpoutfile); \
133             tex_color_synced = TRUE; \
134         } \
135     } while (0)
136
137 /* Common functions for epslatex and ps(la)tex */
138
139 TERM_PUBLIC void
140 PSLATEX_reset()
141 {
142     switch (ps_params->terminal) {
143     case PSTERM_EPSLATEX:
144         PS_reset();
145         if (gpoutfile) {
146             fprintf(gpoutfile, "\
147     \\gplbacktext\n\
148     \\put(0,0){\\includegraphics{%s}}%%\n\
149     \\gplfronttext\n\
150   \\end{picture}%%\n\
151 \\endgroup\n", pslatex_auxname);
152             if (ps_params->epslatex_standalone)
153                 fputs("\\end{document}\n", gpoutfile);
154         }
155         break;
156     case PSTERM_PSLATEX:
157         fputs("\
158 \\end{picture}%\n\
159 \\endgroup\n\
160 \\endinput\n", gpoutfile);
161         break;
162     case PSTERM_PSTEX:
163         fputs("\
164 \\endGNUPLOTpicture\n\
165 \\endgroup\n\
166 \\endinput\n", gpoutfile);
167         break;
168     default:; /* do nothing, just avoid a compiler warning */
169     }
170
171     if (pslatex_auxname) {
172         free(pslatex_auxname);
173         pslatex_auxname = NULL;
174     }
175     if (gppsfile && (gppsfile != gpoutfile)) {
176         fclose(gppsfile);
177         gppsfile = NULL;
178     }
179 }
180
181
182 /* Functions for ps(la)tex */
183
184 TERM_PUBLIC void
185 PSTEX_reopen_output()
186 {
187     if (outstr) {
188         char *dotIndex;
189
190         /* if there's no extension, append ".ps" */
191         if ((dotIndex = strrchr(outstr, '.')) == NULL)
192             dotIndex = strchr(outstr, NUL);
193
194         /* try to open the auxiliary file for the postscript parts. */
195         if (ps_params->useauxfile) {
196             /* length of outstr plus ('.' or '\0') plus "eps" plus '\0' */
197             pslatex_auxname = gp_realloc(pslatex_auxname,dotIndex - outstr + 5,
198                                           "pslatex aux filename");
199             if (pslatex_auxname) {
200                 /* include period or '\0' */
201                 strncpy(pslatex_auxname, outstr, (dotIndex - outstr) + 1);
202                 /* period or '\0' is overwritten with period, and "ps" appended */
203                 strcpy(pslatex_auxname + (dotIndex - outstr), ".ps");
204                 gppsfile = fopen(pslatex_auxname, "w");
205                 if (gppsfile  == (FILE *) NULL) {
206                     fprintf(stderr, "Cannot open aux file %s for output. Switching off auxfile option.\n",
207                             pslatex_auxname);
208                     free(pslatex_auxname);
209                     pslatex_auxname = NULL;
210                     ps_params->useauxfile = FALSE;
211                     gppsfile = gpoutfile;
212                 }
213             } else {
214                 fprintf(stderr, "Cannot make PostScript file name from %s\n",
215                         outstr);
216                 fprintf(stderr, "Turning off auxfile option\n");
217                 ps_params->useauxfile = FALSE;
218                 gppsfile = gpoutfile;
219             }
220         } else
221             gppsfile = gpoutfile;
222     } else {
223         if (ps_params->useauxfile) {
224             fprintf(stderr, "Cannot use aux file on stdout. Switching off auxfile option.\n");
225             ps_params->useauxfile = FALSE;
226         }
227         gppsfile = gpoutfile;
228     }
229 }
230
231
232 TERM_PUBLIC void
233 PSTEX_common_init()
234 {
235     switch (ps_params->terminal) {
236     case PSTERM_PSLATEX:
237         fprintf(gpoutfile,"\
238 %% GNUPLOT: LaTeX picture with Postscript\n\
239 \\begingroup%%\n\
240 \\makeatletter%%\n\
241 \\newcommand{\\GNUPLOTspecial}{%%\n\
242   \\@sanitize\\catcode`\\%%=14\\relax\\special}%%\n\
243 \\setlength{\\unitlength}{%.4fbp}%%\n", 1.0 / (2*PS_SC));
244         fprintf(gpoutfile, "\\begin{picture}(%d,%d)(0,0)%%\n",
245                 (int) (xsize * term->xmax), (int) (ysize * term->ymax));
246         break;
247     case PSTERM_PSTEX:
248         /* write plain TeX header */
249         fprintf(gpoutfile, "\
250 %% GNUPLOT: plain TeX with Postscript\n\
251 \\begingroup\n\
252 \\catcode`\\@=11\\relax\n\
253 \\def\\GNUPLOTspecial{%%\n\
254   \\def\\do##1{\\catcode`##1=12\\relax}\\dospecials\n\
255   \\catcode`\\{=1\\catcode`\\}=2\\catcode\\%%=14\\relax\\special}%%\n\
256 %%\n\
257 \\expandafter\\ifx\\csname GNUPLOTpicture\\endcsname\\relax\n\
258   \\csname newdimen\\endcsname\\GNUPLOTunit\n\
259   \\gdef\\GNUPLOTpicture(#1,#2){\\vbox to#2\\GNUPLOTunit\\bgroup\n\
260     \\def\\put(##1,##2)##3{\\unskip\\raise##2\\GNUPLOTunit\n\
261       \\hbox to0pt{\\kern##1\\GNUPLOTunit ##3\\hss}\\ignorespaces}%%\n\
262     \\def\\ljust##1{\\vbox to0pt{\\vss\\hbox to0pt{##1\\hss}\\vss}}%%\n\
263     \\def\\cjust##1{\\vbox to0pt{\\vss\\hbox to0pt{\\hss ##1\\hss}\\vss}}%%\n\
264     \\def\\rjust##1{\\vbox to0pt{\\vss\\hbox to0pt{\\hss ##1}\\vss}}%%\n\
265     \\def\\stack##1{\\let\\\\=\\cr\\tabskip=0pt\\halign{\\hfil ####\\hfil\\cr ##1\\crcr}}%%\n\
266     \\def\\lstack##1{\\hbox to0pt{\\vbox to0pt{\\vss\\stack{##1}}\\hss}}%%\n\
267     \\def\\cstack##1{\\hbox to0pt{\\hss\\vbox to0pt{\\vss\\stack{##1}}\\hss}}%%\n\
268     \\def\\rstack##1{\\hbox to0pt{\\vbox to0pt{\\stack{##1}\\vss}\\hss}}%%\n\
269     \\vss\\hbox to#1\\GNUPLOTunit\\bgroup\\ignorespaces}%%\n\
270   \\gdef\\endGNUPLOTpicture{\\hss\\egroup\\egroup}%%\n\
271 \\fi\n\
272 \\GNUPLOTunit=%.4fbp\n", 1.0 / (2*PS_SC));
273         fprintf(gpoutfile, "\\GNUPLOTpicture(%d,%d)\n",
274                 (int) (xsize * term->xmax), (int) (ysize * term->ymax));
275         break;
276     default:; /* do nothing, just avoid a compiler warning */
277     }
278
279     if (gppsfile != gpoutfile) {
280         /* these are taken from the post.trm file computation
281          * of the bounding box, but without the X_OFF and Y_OFF */
282         int urx = (int) (xsize * term->xmax / (2*PS_SC) + 0.5);
283         int ury = (int) (ysize * term->ymax / (2*PS_SC) + 0.5);
284         /* moved this code here from beginning of the function
285          * pslatex_auxname is only != NULL with the `auxfile' option */
286         char *psfile_basename = strrchr(pslatex_auxname, DIRSEP1);
287
288         /* If pslatex_auxname is not a simple file name, but a path,
289          * we need to strip the path off the auxiliary file name,
290          * because tex file and ps aux file end up in the same directory! */
291         if (psfile_basename)
292             psfile_basename++;
293         else {
294 #if DIRSEP2 != NUL
295             psfile_basename = strrchr(pslatex_auxname, DIRSEP2);
296             if (psfile_basename)
297                 psfile_basename++;
298             else
299                 psfile_basename = pslatex_auxname;
300 #else
301             psfile_basename = pslatex_auxname;
302 #endif
303         }
304
305         /* generate special which xdvi and dvips can handle */
306         fprintf(gpoutfile,
307                 "  \\special{psfile=%s llx=0 lly=0 urx=%d ury=%d rwi=%d}\n",
308                 psfile_basename, urx, ury, 10 * urx);
309     } else
310         fputs("  {\\GNUPLOTspecial{\"\n", gpoutfile);
311
312     /* HH: really necessary?
313     ps_ang = 0;
314     ps_justify = 0;
315     */
316     pstex_labels = (struct pstex_text_command *) NULL;
317 }
318
319
320 TERM_PUBLIC void
321 PSTEX_put_text(unsigned int x, unsigned int y, const char *str)
322 {
323     struct pstex_text_command *tc;
324
325     /* ignore empty strings */
326     if (str[0] == NUL)
327         return;
328
329     /* Save the text for later printing after the core graphics */
330     tc = (struct pstex_text_command *) gp_alloc(sizeof(struct pstex_text_command),
331                                                 term->name);
332     tc->x = x;
333     tc->y = y;
334     tc->label = (char *) gp_alloc(strlen(str) + 1, term->name);
335     strcpy(tc->label, str);
336     tc->justify = ps_justify;
337     tc->angle = ps_ang;
338
339     tc->next = pstex_labels;
340     pstex_labels = tc;
341 }
342
343 TERM_PUBLIC void
344 PSTEX_text()
345 {
346     struct pstex_text_command *tc;
347
348     PS_text();
349     if (gppsfile == gpoutfile)
350         fputs("  }}%\n", gpoutfile);
351
352     if (ps_params->fontsize) {
353         if (ps_params->terminal == PSTERM_PSLATEX)
354             fprintf(gpoutfile, "\\fontsize{%g}{\\baselineskip}\\selectfont\n",
355                     ps_params->fontsize);
356         /* Should have an else clause here to handle pstex equivalent */
357     }
358
359     for (tc = pstex_labels;
360          tc != (struct pstex_text_command *) NULL;
361          tc = tc->next) {
362         fprintf(gpoutfile, "  \\put(%d,%d){", tc->x, tc->y);
363         if ((ps_params->rotate) && (tc->angle != 0))
364             fprintf(gpoutfile, "\
365 %%\n  \\special{ps: gsave currentpoint currentpoint translate\n\
366 %d rotate neg exch neg exch translate}%%\n  ", 360 - tc->angle);
367         if ((ps_params->terminal == PSTERM_PSLATEX) &&
368             ((tc->label[0] == '{') || (tc->label[0] == '['))) {
369             fprintf(gpoutfile, "\\makebox(0,0)%s", tc->label);
370         } else
371             switch (tc->justify) {
372             case LEFT:
373                 fprintf(gpoutfile, (ps_params->terminal == PSTERM_PSLATEX
374                                     ? "\\makebox(0,0)[l]{\\strut{}%s}"
375                                     : "\\ljust{\\strut{}%s}"), tc->label);
376                 break;
377             case CENTRE:
378                 fprintf(gpoutfile, (ps_params->terminal == PSTERM_PSLATEX
379                                     ? "\\makebox(0,0){\\strut{}%s}"
380                                     : "\\cjust{\\strut{}%s}"), tc->label);
381                 break;
382             case RIGHT:
383                 fprintf(gpoutfile, (ps_params->terminal == PSTERM_PSLATEX
384                                     ? "\\makebox(0,0)[r]{\\strut{}%s}"
385                                     : "\\rjust{\\strut{}%s}"), tc->label);
386                 break;
387             }
388         if ((ps_params->rotate) && (tc->angle != 0))
389             fputs("%\n  \\special{ps: currentpoint grestore moveto}%\n  ",
390                   gpoutfile);
391         fputs("}%\n", gpoutfile);
392     }
393
394     while (pstex_labels) {
395         tc = pstex_labels->next;
396         free(pstex_labels->label);
397         free(pstex_labels);
398         pstex_labels = tc;
399     }
400
401 }
402
403
404 /* Functions for epslatex */
405
406 /* the common init function for the epslatex driver */
407 TERM_PUBLIC void
408 EPSLATEX_common_init()
409 {
410     char *fontfamily = NULL;
411     char *fontseries = NULL;
412     char *fontshape = NULL;
413
414     if (!gpoutfile) {
415         char *temp = gp_alloc(strlen(outstr) + 1, "temp file string");
416         if (temp) {
417             strcpy(temp, outstr);
418             term_set_output(temp);  /* will free outstr */
419             if (temp != outstr) {
420                 if (temp)
421                     free(temp);
422                 temp = outstr;
423             }
424         } else
425             os_error(c_token, "Cannot reopen output files");
426     }
427     if (!outstr)
428         os_error(c_token,
429                  "epslatex terminal cannot write to standard output");
430     if (gpoutfile) {
431         char *inputenc = NULL;
432
433         fprintf(gpoutfile, "%% GNUPLOT: LaTeX picture with Postscript\n");
434
435         switch(encoding) {
436         case S_ENC_DEFAULT:
437             break;
438         case S_ENC_ISO8859_1:
439             inputenc = "latin1";
440             break;
441         case S_ENC_ISO8859_2:
442             inputenc = "latin2";
443             break;
444         case S_ENC_ISO8859_15:
445             inputenc = "latin9";
446             break;
447         case S_ENC_CP437:
448             inputenc = "cp437de";
449             break;
450         case S_ENC_CP850:
451             inputenc = "cp850";
452             break;
453         case S_ENC_CP852:
454             inputenc = "cp852";
455             break;
456         case S_ENC_CP1250:
457             inputenc = "cp1250";
458             break;
459         case S_ENC_KOI8_R:
460             inputenc = "koi8-r";
461             break;
462         case S_ENC_KOI8_U:
463             inputenc = "koi8-u";
464             break;
465         case S_ENC_INVALID:
466             int_error(NO_CARET, "invalid input encoding used");
467             break;
468         default:
469             /* do nothing */
470             break;
471         }
472
473         /* Clear previous state */
474         tex_previous_colorspec.type = -1;
475
476         /* Clear any leftover text-layering state */
477         EPSLATEX_layer(TERM_LAYER_RESET);
478
479         /* Analyse LaTeX font name 'family,series,shape' */
480         if ((strlen(ps_params->font) > 0) &&
481             (strcmp(ps_params->font,"default") != 0)) {
482             char *comma = NULL;
483             fontfamily = gp_alloc(strlen(ps_params->font)+1,
484                                   "EPSLATEX_common_init");
485             fontseries = gp_alloc(strlen(ps_params->font)+1,
486                                   "EPSLATEX_common_init");
487             fontshape = gp_alloc(strlen(ps_params->font)+1,
488                                  "EPSLATEX_common_init");
489             strcpy(fontfamily,ps_params->font);
490             *fontseries = '\0';
491             *fontshape = '\0';
492             if ((comma = strchr(fontfamily, ',')) != NULL) {
493                 *comma = '\0';
494                 strcpy(fontseries,comma+1);
495                 if ((comma = strchr(fontseries, ',')) != NULL) {
496                     *comma = '\0';
497                     strcpy(fontshape,comma+1);
498                 }
499             }
500         }
501             
502         if (ps_params->epslatex_standalone) {
503             fprintf(gpoutfile, "\
504 \\documentclass{minimal}\n\
505 %% Set font size\n\
506 \\makeatletter\n\
507 \\def\\@ptsize{%d}\n\
508 \\InputIfFileExists{size%d.clo}{}{%%\n\
509    \\GenericError{(gnuplot) \\space\\space\\space\\@spaces}{%%\n\
510       Gnuplot Error: File `size%d.clo' not found! Could not set font size%%\n\
511    }{See the gnuplot documentation for explanation.%%\n\
512    }{For using a font size a file `size<fontsize>.clo' has to exist.\n\
513         Falling back ^^Jto default fontsize 10pt.}%%\n\
514   \\def\\@ptsize{0}\n\
515   \\input{size10.clo}%%\n\
516 }%%\n\
517 \\makeatother\n",
518                     (int)(ps_params->fontsize-10),
519                     (int)(ps_params->fontsize),
520                     (int)(ps_params->fontsize));
521
522             if (fontfamily && strlen(fontfamily) > 0)
523                 fprintf(gpoutfile, "\\renewcommand*\\rmdefault{%s}%%\n",
524                         fontfamily);
525             if (fontseries && strlen(fontseries) > 0)
526                 fprintf(gpoutfile, "\\renewcommand*\\mddefault{%s}%%\n",
527                         fontseries);
528             if (fontshape && strlen(fontshape) > 0)
529                 fprintf(gpoutfile, "\\renewcommand*\\updefault{%s}%%\n",
530                         fontshape);
531
532             fputs("\
533 % Load packages\n\
534 \\usepackage{graphicx}\n\
535 \\usepackage{color}\n", gpoutfile);
536
537             if (inputenc)
538                 fprintf(gpoutfile, "\\usepackage[%s]{inputenc}\n", inputenc);
539
540             fprintf(gpoutfile, "\
541 \\makeatletter\n\
542 %% Select an appropriate default driver (from TeXLive graphics.cfg)\n\
543 \\begingroup\n\
544   \\chardef\\x=0 %%\n\
545   %% check pdfTeX\n\
546   \\@ifundefined{pdfoutput}{}{%%\n\
547     \\ifcase\\pdfoutput\n\
548     \\else\n\
549       \\chardef\\x=1 %%\n\
550     \\fi\n\
551   }%%\n\
552   %% check VTeX\n\
553   \\@ifundefined{OpMode}{}{%%\n\
554     \\chardef\\x=2 %%\n\
555   }%%\n\
556 \\expandafter\\endgroup\n\
557 \\ifcase\\x\n\
558   %% default case\n\
559   \\PassOptionsToPackage{dvips}{geometry}\n\
560 \\or\n\
561   %% pdfTeX is running in pdf mode\n\
562   \\PassOptionsToPackage{pdftex}{geometry}\n\
563 \\else\n\
564   %% VTeX is running\n\
565   \\PassOptionsToPackage{vtex}{geometry}\n\
566 \\fi\n\
567 \\makeatother\n\
568 %% Set papersize\n\
569 \\usepackage[papersize={%.2fbp,%.2fbp},text={%.2fbp,%.2fbp}]{geometry}\n\
570 %% No page numbers and no paragraph indentation\n\
571 \\pagestyle{empty}\n\
572 \\setlength{\\parindent}{0bp}%%\n\
573 %% Load configuration file\n\
574 \\InputIfFileExists{gnuplot.cfg}{%%\n\
575   \\typeout{Using configuration file gnuplot.cfg}%%\n\
576 }{%%\n\
577  \\typeout{No configuration file gnuplot.cfg found.}%%\n\
578 }%%\n\
579 %s\n\
580 \\begin{document}\n",
581                     term->xmax * xsize / (2.0*PS_SC),
582                     term->ymax * ysize / (2.0*PS_SC),
583                     term->xmax * xsize / (2.0*PS_SC),
584                     term->ymax * ysize / (2.0*PS_SC),
585                     epslatex_header ? epslatex_header : "%" );
586         }
587
588         fputs("\\begingroup\n", gpoutfile);
589         
590         if (inputenc)
591             fprintf(gpoutfile, "\
592   %% Encoding inside the plot.  In the header of your document, this encoding\n\
593   %% should to defined, e.g., by using\n\
594   %% \\usepackage[%s,<other encodings>]{inputenc}\n\
595   \\inputencoding{%s}%%\n", inputenc, inputenc);
596
597         if (!ps_params->epslatex_standalone) {
598             if (fontfamily && strlen(fontfamily) > 0)
599                 fprintf(gpoutfile, "  \\fontfamily{%s}%%\n",
600                         fontfamily);
601             if (fontseries && strlen(fontseries) > 0)
602                 fprintf(gpoutfile, "  \\fontseries{%s}%%\n",
603                         fontseries);
604             if (fontshape && strlen(fontshape) > 0)
605                 fprintf(gpoutfile, "  \\fontshape{%s}%%\n",
606                         fontshape);
607             if (fontfamily || fontseries || fontshape)
608                 fputs("  \\selectfont\n", gpoutfile);
609             if (epslatex_header)
610                 fprintf(gpoutfile, "%s\n", epslatex_header );
611         }
612
613         fprintf(gpoutfile, "\
614   \\makeatletter\n\
615   \\providecommand\\color[2][]{%%\n\
616     \\GenericError{(gnuplot) \\space\\space\\space\\@spaces}{%%\n\
617       Package color not loaded in conjunction with\n\
618       terminal option `colourtext'%%\n\
619     }{See the gnuplot documentation for explanation.%%\n\
620     }{Either use 'blacktext' in gnuplot or load the package\n\
621       color.sty in LaTeX.}%%\n\
622     \\renewcommand\\color[2][]{}%%\n\
623   }%%\n\
624   \\providecommand\\includegraphics[2][]{%%\n\
625     \\GenericError{(gnuplot) \\space\\space\\space\\@spaces}{%%\n\
626       Package graphicx or graphics not loaded%%\n\
627     }{See the gnuplot documentation for explanation.%%\n\
628     }{The gnuplot epslatex terminal needs graphicx.sty or graphics.sty.}%%\n\
629     \\renewcommand\\includegraphics[2][]{}%%\n\
630   }%%\n\
631   \\providecommand\\rotatebox[2]{#2}%%\n\
632   \\@ifundefined{ifGPcolor}{%%\n\
633     \\newif\\ifGPcolor\n\
634     \\GPcolor%s\n\
635   }{}%%\n\
636   \\@ifundefined{ifGPblacktext}{%%\n\
637     \\newif\\ifGPblacktext\n\
638     \\GPblacktext%s\n\
639   }{}%%\n\
640   %% define a \\g@addto@macro without @ in the name:\n\
641   \\let\\gplgaddtomacro\\g@addto@macro\n\
642   %% define empty templates for all commands taking text:\n\
643   \\gdef\\gplbacktext{}%%\n\
644   \\gdef\\gplfronttext{}%%\n\
645   \\makeatother\n",
646                 (ps_params->color?"true":"false"),
647                 (ps_params->blacktext?"true":"false") );
648
649         /* use \expandafter\def\csname LT0\endcsname{...} 
650          * instead of \def\LT0{...} because digits may not be part of
651          * \... sequences */
652         fputs("\
653   \\ifGPblacktext\n\
654     % no textcolor at all\n\
655     \\def\\colorrgb#1{}%\n\
656     \\def\\colorgray#1{}%\n\
657   \\else\n\
658     % gray or color?\n\
659     \\ifGPcolor\n\
660       \\def\\colorrgb#1{\\color[rgb]{#1}}%\n\
661       \\def\\colorgray#1{\\color[gray]{#1}}%\n\
662       \\expandafter\\def\\csname LTw\\endcsname{\\color{white}}%\n\
663       \\expandafter\\def\\csname LTb\\endcsname{\\color{black}}%\n\
664       \\expandafter\\def\\csname LTa\\endcsname{\\color{black}}%\n",
665               gpoutfile);
666         if (ps_params->oldstyle) {
667             fputs("\
668       \\expandafter\\def\\csname LT0\\endcsname{\\color[rgb]{1,0,0}}%\n\
669       \\expandafter\\def\\csname LT1\\endcsname{\\color[rgb]{0,0,1}}%\n\
670       \\expandafter\\def\\csname LT2\\endcsname{\\color[rgb]{0,1,1}}%\n\
671       \\expandafter\\def\\csname LT3\\endcsname{\\color[rgb]{1,0,1}}%\n",
672                   gpoutfile);
673         } else {
674             fputs("\
675       \\expandafter\\def\\csname LT0\\endcsname{\\color[rgb]{1,0,0}}%\n\
676       \\expandafter\\def\\csname LT1\\endcsname{\\color[rgb]{0,1,0}}%\n\
677       \\expandafter\\def\\csname LT2\\endcsname{\\color[rgb]{0,0,1}}%\n\
678       \\expandafter\\def\\csname LT3\\endcsname{\\color[rgb]{1,0,1}}%\n\
679       \\expandafter\\def\\csname LT4\\endcsname{\\color[rgb]{0,1,1}}%\n\
680       \\expandafter\\def\\csname LT5\\endcsname{\\color[rgb]{1,1,0}}%\n\
681       \\expandafter\\def\\csname LT6\\endcsname{\\color[rgb]{0,0,0}}%\n\
682       \\expandafter\\def\\csname LT7\\endcsname{\\color[rgb]{1,0.3,0}}%\n\
683       \\expandafter\\def\\csname LT8\\endcsname{\\color[rgb]{0.5,0.5,0.5}}%\n",
684                   gpoutfile);
685         }
686         fputs("\
687     \\else\n\
688       % gray\n\
689       \\def\\colorrgb#1{\\color{black}}%\n\
690       \\def\\colorgray#1{\\color[gray]{#1}}%\n\
691       \\expandafter\\def\\csname LTw\\endcsname{\\color{white}}%\n\
692       \\expandafter\\def\\csname LTb\\endcsname{\\color{black}}%\n\
693       \\expandafter\\def\\csname LTa\\endcsname{\\color{black}}%\n\
694       \\expandafter\\def\\csname LT0\\endcsname{\\color{black}}%\n\
695       \\expandafter\\def\\csname LT1\\endcsname{\\color{black}}%\n\
696       \\expandafter\\def\\csname LT2\\endcsname{\\color{black}}%\n\
697       \\expandafter\\def\\csname LT3\\endcsname{\\color{black}}%\n\
698       \\expandafter\\def\\csname LT4\\endcsname{\\color{black}}%\n\
699       \\expandafter\\def\\csname LT5\\endcsname{\\color{black}}%\n\
700       \\expandafter\\def\\csname LT6\\endcsname{\\color{black}}%\n\
701       \\expandafter\\def\\csname LT7\\endcsname{\\color{black}}%\n\
702       \\expandafter\\def\\csname LT8\\endcsname{\\color{black}}%\n\
703     \\fi\n\
704   \\fi\n", gpoutfile);
705
706         fprintf(gpoutfile,"\
707   \\setlength{\\unitlength}{%.4fbp}%%\n\
708   \\begin{picture}(%.2f,%.2f)%%\n",
709                 1.0 / (2*PS_SC), term->xmax * xsize, term->ymax * ysize);
710     }
711
712     if (fontfamily)
713         free(fontfamily);
714     if (fontseries)
715         free(fontseries);
716     if (fontshape)
717         free(fontshape);
718 }
719
720
721 TERM_PUBLIC void
722 EPSLATEX_put_text(unsigned int x, unsigned int y, const char *str)
723 {
724     if (gpoutfile) {
725         EPSLATEX_sync_color;
726         fprintf(gpoutfile, "      \\put(%d,%d){", x, y);
727         if (ps_ang)
728             fprintf(gpoutfile,"\\rotatebox{%d}{", ps_ang);
729         if (((str[0] == '{') || (str[0] == '['))) {
730             fprintf(gpoutfile, "\\makebox(0,0)%s", str);
731         } else
732             switch (ps_justify) {
733             case LEFT:
734                 fprintf(gpoutfile, "\\makebox(0,0)[l]{\\strut{}%s}", str);
735                 break;
736             case CENTRE:
737                 fprintf(gpoutfile, "\\makebox(0,0){\\strut{}%s}", str);
738                 break;
739             case RIGHT:
740                 fprintf(gpoutfile, "\\makebox(0,0)[r]{\\strut{}%s}", str);
741                 break;
742             }
743         if (ps_ang) {
744             fputs("}", gpoutfile);
745         }
746         fputs("}%\n", gpoutfile);
747     }
748 }
749
750
751 /* assigns dest to outstr, so it must be allocated or NULL
752  * and it must not be outstr itself !
753  */
754 void
755 EPSLATEX_reopen_output()
756 {
757     char *psoutstr = NULL;
758
759     if (outstr) {
760         unsigned int outstrlen = strlen(outstr);
761         if (strrchr(outstr, '.') != &outstr[outstrlen-4] ) {
762             int_error(NO_CARET,
763                       "epslatex outputfile may not have dots inside %s",
764                       "their filenames before the extension .tex or .eps");
765         }
766
767         /* copy filename to postsript output */
768         psoutstr = gp_alloc(outstrlen+5, "epslatex eps filename");
769         strcpy( psoutstr, outstr);
770
771         if ((!strncmp( &outstr[outstrlen-4], ".eps", 4 )) ||
772             (!strncmp( &outstr[outstrlen-4], ".EPS", 4 ))) {
773             if (ps_params->epslatex_standalone)
774                 int_error(NO_CARET,
775                           "For epslatex standalone mode, you have to %s",
776                           "give the tex filename as output");
777             /* rename primary output (tex) */
778             strncpy( &outstr[outstrlen-4], ".tex", 4);
779             /* redirect FILE stream */
780             gppsfile = gpoutfile;
781             gpoutfile = fopen(outstr,"w");
782             int_warn(NO_CARET, "Resetting primary output file to %s,\n\
783                   PostScript output to %s", outstr, psoutstr);
784             if (!gpoutfile)
785                 int_error(NO_CARET, "--- reopen failed");
786         } else {
787             if (ps_params->epslatex_standalone)
788                 strncpy( &psoutstr[outstrlen-4], "-inc.eps", 9);
789             else
790                 strncpy( &psoutstr[outstrlen-4], ".eps", 4);
791             gppsfile = fopen(psoutstr,"w");
792         }
793         if (!gppsfile)
794             int_error(NO_CARET, "open of postscipt output file %s failed",
795                       psoutstr);
796
797         /* set the name for the \includegraphics command */
798         pslatex_auxname = gp_alloc(strlen(psoutstr)-3,
799                                    "epslatex TeX filename");
800         strncpy( pslatex_auxname, psoutstr, strlen(psoutstr)-4 );
801         pslatex_auxname[strlen(psoutstr)-4] = '\0';
802
803         free(psoutstr);
804     }
805 }
806
807
808 TERM_PUBLIC void
809 EPSLATEX_set_color(t_colorspec *colorspec)
810 {
811     double gray;
812
813     /* EAM Jul 2006 - Filter out duplicate requests */
814     if (!memcmp(&tex_previous_colorspec, colorspec, sizeof(t_colorspec)))
815         return;
816     else
817         memcpy(&tex_previous_colorspec, colorspec, sizeof(t_colorspec));
818
819     /* Fancy footwork to deal with mono/grayscale plots */
820     if (colorspec->type == TC_LT && !ps_params->color)
821         PS_linetype(colorspec->lt);
822     else
823         PS_set_color(colorspec);
824
825     /* Many [most? all?] of the set_color commands only affect the *.eps     */
826     /* output stream.  So rather than printing them all to the *.tex stream, */
827     /* we update the current color and set a flag to say it has changed.     */
828     /* Only when some TeX object is output do we sync the current color by   */
829     /* writing it out.                                                       */
830     tex_color_synced = FALSE;
831
832     if (colorspec->type == TC_RGB) {
833         double r = (double)((colorspec->lt >> 16 ) & 255) / 255.;
834         double g = (double)((colorspec->lt >> 8 ) & 255) / 255.;
835         double b = (double)(colorspec->lt & 255) / 255.;
836         sprintf(tex_current_color, "      \\colorrgb{%3.2f,%3.2f,%3.2f}%%\n",r,g,b);
837     }
838
839     if (colorspec->type == TC_LT) {
840         int linetype = colorspec->lt;
841         if (ps_params->oldstyle)
842             linetype = (linetype % 4) + 3;
843         else
844             linetype = (linetype % 9) + 3;
845
846         sprintf(tex_current_color, "      \\csname LT%c\\endcsname%%\n",
847                 "wba012345678"[linetype]);
848     }
849
850     if (colorspec->type != TC_FRAC)
851         return;
852
853 /* map [0;1] to gray/colors */
854     gray = colorspec->value;
855
856     if (ps_params->blacktext) {
857         if (gray <= 0)
858             sprintf(tex_current_color, "      \\color{black}%%\n");
859         else if (gray >= 1)
860             sprintf(tex_current_color, "      \\color{white}%%\n");
861         else
862             sprintf(tex_current_color, "      \\colorgray{%s}%%\n",save_space(gray));
863     } else {
864         rgb_color color;
865         rgb1_from_gray( colorspec->value, &color );
866         sprintf(tex_current_color, "      \\colorrgb{%3.2f,%3.2f,%3.2f}%%\n",color.r,color.g,color.b);
867     }
868 }
869
870 TERM_PUBLIC void
871 EPSLATEX_linetype(int linetype)
872 {
873     t_colorspec tempcol = {TC_LT, 0, 0.0};
874     tempcol.lt = linetype;
875     PS_linetype(linetype);
876
877     /* This leads to redundant *.eps output */
878     EPSLATEX_set_color(&tempcol);
879 }
880
881 /*
882  * The TERM_LAYER mechanism is used here to signal a difference between
883  * "front" text and "back" text.
884  */
885 TERM_PUBLIC void
886 EPSLATEX_layer(t_termlayer syncpoint)
887 {
888     switch (syncpoint) {
889
890     case TERM_LAYER_RESET:        /* Start of plot; reset flag */
891         epslatex_text_layer = 0;
892         break;
893
894     case TERM_LAYER_BACKTEXT: /* Start of "back" text layer */
895         if (epslatex_text_layer == 1)
896             break;
897         if (epslatex_text_layer == 2)
898             fputs("    }%\n", gpoutfile);
899         epslatex_text_layer = 1;
900         fputs("    \\gplgaddtomacro\\gplbacktext{%\n", gpoutfile);
901         break;
902
903     case TERM_LAYER_FRONTTEXT:/* Start of "front" text layer */
904         if (epslatex_text_layer == 2)
905             break;
906         if (epslatex_text_layer == 1)
907             fputs("    }%\n", gpoutfile);
908         epslatex_text_layer = 2;
909         fputs("    \\gplgaddtomacro\\gplfronttext{%\n", gpoutfile);
910         break;
911
912     case TERM_LAYER_END_TEXT:     /* Close off front or back macro before leaving */
913         if (epslatex_text_layer == 1 || epslatex_text_layer == 2)
914             fputs("    }%\n", gpoutfile);
915         epslatex_text_layer = 0;
916         break;
917
918     default:
919         break;
920     }
921 }
922
923 #endif /* TERM_BODY */
924
925 #ifdef TERM_TABLE
926
927 #ifndef GOT_POST_PROTO
928 #define TERM_PROTO_ONLY
929 #include "post.trm"
930 #undef TERM_PROTO_ONLY
931 #endif /* GOT_POST_PROTO */
932
933 TERM_TABLE_START(epslatex_driver)
934     "epslatex", "LaTeX picture environment using graphicx package",
935     PS_XMAX, PS_YMAX, EPSLATEX_VCHAR, EPSLATEX_HCHAR,
936     PS_VTIC, PS_HTIC, PS_options, PS_init, PSLATEX_reset,
937     PS_text, null_scale, PS_graphics, PS_move,
938     PS_vector, EPSLATEX_linetype, EPSLATEX_put_text, PS_text_angle,
939     PS_justify_text, PS_point, do_arrow, PS_set_font,
940     PS_pointsize, TERM_BINARY|TERM_IS_POSTSCRIPT|TERM_CAN_CLIP /*flags */,
941     0 /*suspend */, 0 /*resume */,
942     PS_fillbox, PS_linewidth,
943 #ifdef USE_MOUSE
944     0, 0, 0, 0, 0, /* no mouse support for postscript */
945 #endif
946     PS_make_palette, PS_previous_palette,
947     EPSLATEX_set_color, PS_filled_polygon,
948 #ifdef WITH_IMAGE
949     PS_image,
950 #endif
951     0, 0, 0, /* Enhanced text mode not used */
952     EPSLATEX_layer, /* Used to signal front/back text */
953     PS_path
954 TERM_TABLE_END(epslatex_driver)
955 #undef LAST_TERM
956 #define LAST_TERM epslatex_driver
957
958 TERM_TABLE_START(pslatex_driver)
959     "pslatex", "LaTeX picture environment with PostScript \\specials",
960     PS_XMAX, PS_YMAX, PSTEX_VCHAR, PSTEX_HCHAR,
961     PS_VTIC, PS_HTIC, PS_options, PS_init, PSLATEX_reset,
962     PSTEX_text, null_scale, PS_graphics, PS_move,
963     PS_vector, PS_linetype, PSTEX_put_text, PS_text_angle,
964     PS_justify_text, PS_point, PS_arrow, set_font_null,
965     PS_pointsize, TERM_CAN_CLIP /*flags */ , 0 /*suspend */
966     , 0 /*resume */ ,
967     PS_fillbox, PS_linewidth
968 #ifdef USE_MOUSE
969    , 0, 0, 0, 0, 0 /* no mouse support for postscript */
970 #endif
971    , PS_make_palette,
972    PS_previous_palette, /* write grestore */
973    PS_set_color,
974    PS_filled_polygon
975 #ifdef WITH_IMAGE
976     , PS_image
977     , 0, 0, 0   /* No enhanced text mode because this is LaTeX */
978     , 0         /* layer */
979     , PS_path
980 #endif
981 TERM_TABLE_END(pslatex_driver)
982 #undef LAST_TERM
983 #define LAST_TERM pslatex_driver
984
985 TERM_TABLE_START(pstex_driver)
986     "pstex", "plain TeX with PostScript \\specials",
987     PS_XMAX, PS_YMAX, PSTEX_VCHAR, PSTEX_HCHAR,
988     PS_VTIC, PS_HTIC, PS_options, PS_init, PSLATEX_reset,
989     PSTEX_text, null_scale, PS_graphics, PS_move,
990     PS_vector, PS_linetype, PSTEX_put_text, PS_text_angle,
991     PS_justify_text, PS_point, PS_arrow, set_font_null,
992     PS_pointsize, TERM_CAN_CLIP /*flags */ , 0 /*suspend */
993     , 0 /*resume */ ,
994     PS_fillbox, PS_linewidth
995 #ifdef USE_MOUSE
996    , 0, 0, 0, 0, 0 /* no mouse support for postscript */
997 #endif
998    , PS_make_palette,
999    PS_previous_palette, /* write grestore */
1000    PS_set_color,
1001    PS_filled_polygon
1002 #ifdef WITH_IMAGE
1003     , PS_image
1004 #endif
1005     , 0, 0, 0   /* No enhanced text mode because this is LaTeX */
1006     , 0         /* layer */
1007     , PS_path
1008 TERM_TABLE_END(pstex_driver)
1009 #undef LAST_TERM
1010 #define LAST_TERM pstex_driver
1011
1012 #endif /* TERM_TABLE */
1013 #endif /* TERM_PROTO_ONLY */
1014
1015