Initial release of Maemo 5 port of gnuplot
[gnuplot] / term / post.trm
diff --git a/term/post.trm b/term/post.trm
new file mode 100644 (file)
index 0000000..b51bdba
--- /dev/null
@@ -0,0 +1,4015 @@
+/* Hello, Emacs: this is -*-C-*- !
+ * $Id: post.trm,v 1.203.2.17 2009/03/02 17:40:06 mikulik Exp $
+ */
+
+/* GNUPLOT - post.trm */
+
+/*[
+ * Copyright 1990 - 1993, 1998, 1999, 2000, 2001, 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 terminal driver supports:
+ *     postscript
+ *
+ * AUTHORS
+ *  Russell Lang  <rjl@monu1.cc.monash.edu.au>
+ *
+ * modified 10/5/95 by drd - put in support for other postscript drivers
+ * (enhpost, pslatex, ...) so they dont have to work quite so hard
+ *
+ * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
+ *
+ * The 'postscript' driver produces landscape output 10" wide and 7" high.
+ * To change font to Times-Roman and font size to 20pts use
+ * 'set term postscript "Times-Roman" 20'.
+ * To get a smaller (5" x 3.5") eps output use 'set term post eps'
+ * and make only one plot per file.  Font size for eps will be half
+ * the specified size.
+ *
+ * Erik Luijten 30/5/97: added %%CreationDate, made %%DocumentFonts conform
+ *                       to DSC, added version no. and patchl. to %%Creator
+ * Petr Mikulik, Jan 1999: terminal entries for PM3D functionality
+ *
+ * Dick Crawford 24/5/00: added 'a{}{}' syntax to allow for overprinting
+ *
+ * Dan Sebald, 7 March 2003: terminal entry for image functionality
+ *
+ *  Harald Harders (h.harders@tu-bs.de), 2004-12-02:
+ *  Moved all terminal settings into a single structure.
+ *
+ *  Harald Harders (h.harders@tu-bs.de), 2005-02-08:
+ *  Merged functionality of postscript, pslatex, pstex, and epslatex terminals.
+ *
+ *  Ethan Merritt Mar 2006:   Break out prolog and character encodings into
+ *  separate files loaded at runtime
+ */
+
+#include "driver.h"
+
+#ifdef TERM_PROTO
+#include "variable.h"  /* For loadpath_handler used in PS_dump_prologue_file */
+#endif
+
+#ifdef TERM_REGISTER
+register_term(post)
+#endif
+
+#ifdef TERM_PROTO
+TERM_PUBLIC void PS_options __PROTO((void));
+TERM_PUBLIC void PS_common_init __PROTO((TBOOLEAN uses_fonts, unsigned int xoff, unsigned int yoff, unsigned int bb_xmin, unsigned int bb_ymin, unsigned int bb_xmax, unsigned int bb_ymax, const char **dict));
+TERM_PUBLIC void PS_init __PROTO((void));
+TERM_PUBLIC void PS_graphics __PROTO((void));
+TERM_PUBLIC void PS_text __PROTO((void));
+TERM_PUBLIC void PS_reset __PROTO((void));
+TERM_PUBLIC void PS_linetype __PROTO((int linetype));
+TERM_PUBLIC void PS_move __PROTO((unsigned int x, unsigned int y));
+TERM_PUBLIC void PS_vector __PROTO((unsigned int x, unsigned int y));
+TERM_PUBLIC void PS_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
+TERM_PUBLIC int PS_text_angle __PROTO((int ang));
+TERM_PUBLIC int PS_justify_text __PROTO((enum JUSTIFY mode));
+TERM_PUBLIC void PS_point __PROTO((unsigned int x, unsigned int y, int number));
+TERM_PUBLIC void PS_arrow __PROTO(( unsigned int sx, unsigned int sy,
+    unsigned int ex, unsigned int ey, int head));
+TERM_PUBLIC int PS_set_font __PROTO((const char * font));
+TERM_PUBLIC void PS_fillbox __PROTO((int style, unsigned int x1, unsigned int y1, unsigned int width, unsigned int height));
+TERM_PUBLIC void PS_linewidth __PROTO((double linewidth)); /* JFi [linewidth] */
+TERM_PUBLIC void PS_pointsize __PROTO((double ptsize)); /* JFi [pointsize] */
+TERM_PUBLIC int PS_make_palette (t_sm_palette *);
+TERM_PUBLIC void PS_previous_palette (void);
+TERM_PUBLIC void PS_set_color (t_colorspec *);
+TERM_PUBLIC void PS_filled_polygon (int, gpiPoint *);
+#ifdef WITH_IMAGE
+TERM_PUBLIC void PS_image __PROTO((unsigned, unsigned, coordval *, gpiPoint *, t_imagecolor));
+#endif
+
+/* To support "set term post enhanced" */
+TERM_PUBLIC void ENHPS_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
+TERM_PUBLIC int  ENHPS_set_font __PROTO((const char * font));
+TERM_PUBLIC void ENHPS_OPEN __PROTO((char * fontname, double fontsize,
+                       double base, TBOOLEAN widthflag, TBOOLEAN showflag,
+                       int overprint));
+TERM_PUBLIC void ENHPS_FLUSH __PROTO((void));
+TERM_PUBLIC void ENHPS_WRITEC __PROTO((int c));
+TERM_PUBLIC char *PS_RememberFont __PROTO((char *fname, int reencode));
+
+TERM_PUBLIC char *PS_escape_string __PROTO((char *origstr, char *escapelist));
+
+TERM_PUBLIC void PS_path __PROTO((int p));
+static TBOOLEAN PS_newpath = FALSE;
+
+#endif /* TERM_PROTO */
+
+#ifndef TERM_PROTO_ONLY
+
+#ifdef TERM_BODY
+
+#include "post.h"
+
+#define PS_FLUSH_PATH do {                     \
+    if (ps_path_count) {                       \
+       fputs("stroke\n", gppsfile);            \
+       ps_path_count = 0;                      \
+       PS_relative_ok = FALSE;                 \
+    }                                          \
+} while (0)
+
+/* Datastructure implementing inclusion of font files */
+struct ps_fontfile_def {
+    struct ps_fontfile_def *next;/* pointer to next fontfile in linked list */
+    char *fontfile_name;
+    char *fontfile_fullname;
+};
+
+/* Terminal type of postscript dialect */
+enum PS_TERMINALTYPE {
+    PSTERM_PSTEX, PSTERM_PSLATEX, PSTERM_EPSLATEX, PSTERM_POSTSCRIPT
+};
+
+enum PS_PSFORMAT {
+    PSTERM_EPS, PSTERM_PORTRAIT, PSTERM_LANDSCAPE
+};
+
+/* One struct that takes all terminal parameters
+ * by Harald Harders <h.harders@tu-bs.de> */
+typedef struct ps_params_t {
+    enum PS_TERMINALTYPE terminal;
+    int xoff;
+    int yoff;
+    enum PS_PSFORMAT psformat;
+    TBOOLEAN level1;
+    TBOOLEAN color;
+    TBOOLEAN blacktext;
+    TBOOLEAN solid;
+    float dash_length;
+    float linewidth_factor;
+    TBOOLEAN duplex_option;           /* one of duplex or simplex specified? */
+    TBOOLEAN duplex_state;
+    TBOOLEAN rounded;                 /* rounded linecaps and linejoins */
+    struct ps_fontfile_def *first_fontfile;
+    char font[MAX_ID_LEN+1];          /* name of font */
+    float fontsize;                     /* size of font in pts */
+    TBOOLEAN useauxfile;              /* only necessary for ps(la)tex */
+    TBOOLEAN rotate;                  /* only necessary for ps(la)tex */
+    int palfunc_samples;              /* setable via "palf$uncparam" */
+    double palfunc_deviation;         /* terminal option */
+    TBOOLEAN oldstyle;
+    TBOOLEAN epslatex_standalone;
+} ps_params_t;
+
+#define POST_PARAMS_DEFAULT { \
+    PSTERM_POSTSCRIPT, 50, 50, \
+    PSTERM_LANDSCAPE, FALSE, FALSE, FALSE, FALSE, 1.0, 1.0, FALSE, \
+    FALSE, FALSE, NULL, "Helvetica", 14, FALSE, FALSE, 2000, 0.003, \
+    FALSE, FALSE \
+}
+
+static ps_params_t post_params = POST_PARAMS_DEFAULT;
+static const ps_params_t post_params_default = POST_PARAMS_DEFAULT;
+
+#define EPSLATEX_PARAMS_DEFAULT { \
+    PSTERM_EPSLATEX, 50, 50, \
+    PSTERM_EPS, FALSE, FALSE, TRUE, FALSE, 1.0, 1.0, FALSE, \
+    FALSE, FALSE, NULL, "", 11, TRUE, FALSE, 2000, 0.003, \
+    FALSE, FALSE \
+}
+static ps_params_t epslatex_params = EPSLATEX_PARAMS_DEFAULT;
+static const ps_params_t epslatex_params_default = EPSLATEX_PARAMS_DEFAULT;
+
+#define PSLATEX_PARAMS_DEFAULT { \
+    PSTERM_PSLATEX, 0, 0, \
+    PSTERM_EPS, FALSE, FALSE, TRUE, FALSE, 1.0, 1.0, FALSE, \
+    FALSE, FALSE, NULL, "", 0, FALSE, TRUE, 2000, 0.003, \
+    FALSE, FALSE \
+}
+static ps_params_t pslatex_params = PSLATEX_PARAMS_DEFAULT;
+static const ps_params_t pslatex_params_default = PSLATEX_PARAMS_DEFAULT;
+
+#define PSTEX_PARAMS_DEFAULT { \
+    PSTERM_PSTEX, 0, 0, \
+    PSTERM_EPS, FALSE, FALSE, TRUE, FALSE, 1.0, 1.0, FALSE, \
+    FALSE, FALSE, NULL, "", 0, FALSE, TRUE, 2000, 0.003, \
+    FALSE, FALSE \
+}
+static ps_params_t pstex_params = PSTEX_PARAMS_DEFAULT;
+static const ps_params_t pstex_params_default = PSTEX_PARAMS_DEFAULT;
+
+static ps_params_t *ps_params = &post_params;
+
+static void make_interpolation_code __PROTO((void));
+static void make_color_model_code __PROTO((void));
+static char * save_space __PROTO((double gray));
+static void write_component_array __PROTO((const char *text, gradient_struct *grad, int cnt, int offset));
+static void write_gradient_definition __PROTO((gradient_struct *gradient, int cnt));
+static void write_color_space __PROTO((t_sm_palette *palette));
+static void make_palette_formulae __PROTO((void));
+static void PS_make_header __PROTO((t_sm_palette *palette));
+
+static float ps_fontsize;
+
+/* for enhanced mode, we keep a separate font name and size, which
+ * is restored to the default value on font of ""
+ */
+static char ps_enh_font[MAX_ID_LEN+1];
+static float ps_enh_fontsize;
+static int  ENHPS_initialized;
+
+static int ps_page = 0;                /* page count */
+static int ps_path_count = 0;  /* count of lines in path */
+static int ps_ang = 0;                 /* text angle */
+static enum JUSTIFY ps_justify = LEFT; /* text is flush left */
+
+static void delete_ps_fontfile __PROTO((struct ps_fontfile_def *, struct ps_fontfile_def *));
+
+TERM_PUBLIC void PS_load_fontfile __PROTO((struct ps_fontfile_def *,TBOOLEAN));
+TERM_PUBLIC void PS_load_fontfiles __PROTO((TBOOLEAN));
+
+static TBOOLEAN ps_explicit_size = FALSE;
+static size_units ps_explicit_units = INCHES;
+static int eps_explicit_x = 0;
+static int eps_explicit_y = 0;
+
+#define DOTS_PER_INCH (300)    /* resolution of printer we expect to use */
+
+/* name of auxiliary file */
+static char *pslatex_auxname = NULL;
+
+/* Routine to copy pre-existing prolog files into output stream */
+static void PS_dump_prologue_file __PROTO((char *));
+
+static const char GPFAR * GPFAR OldEPSL_linetypes[] = {
+/* Line Types */
+"% Redefine line types to match old epslatex driver\n",
+"/LTw { PL [] 1 setgray } def\n", /* background (assumed white) */
+"/LTb { BL [] 0 0 0 DL } def\n", /* border */
+"/LTa { AL [1 udl mul 2 udl mul] 0 setdash 0 0 0 setrgbcolor } def\n", /* axes */
+"/LT0 { PL [] 1 0 0 DL } def\n",
+"/LT1 { PL [8 dl1 5 dl1] 0 0 1 DL } def\n",
+"/LT2 { PL [4 dl1 4 dl1] 0 1 1 DL } def\n",
+"/LT3 { PL [8 dl1 5 dl1 0.5 dl1 5 dl1] 1 0 1 DL } def\n",
+NULL
+};
+
+static const char GPFAR * GPFAR ENHPS_header[] = {
+/* For MFshow and MFwidth the tos is an array with the string and font info:  */
+/*     [<fontname (a string)> <fontsize> <vertical offset> <width significant?> <printed?> <overprint> <text string>]  */
+/* EAM Mar 2004 - Add in a special case overprint 3 = save, overprint 4 = restore */
+
+"/MFshow {\n",
+"   { dup 5 get 3 ge\n",       /* EAM test for overprint 3 or 4 */
+"     { 5 get 3 eq {gsave} {grestore} ifelse }\n", /* EAM */
+"     {dup dup 0 get findfont exch 1 get scalefont setfont\n",
+"     [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6\n",
+"     get exch 4 get {show} {stringwidth pop 0 R} ifelse }if dup 5 get 0 eq\n",
+"     {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5\n",
+"     get 1 eq {dup 2 get exch dup 3 get exch 6 get stringwidth pop -2 div\n",
+"     dup 0 R} {dup 6 get stringwidth pop -2 div 0 R 6 get\n",
+"     show 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop\n",
+"     pop aload pop M} ifelse }ifelse }ifelse }\n",
+"     ifelse }\n", /* EAM */
+"   forall} bind def\n",
+
+/* get the width of the text */
+/* HH 2005-07-24 - Add in a special case overprint 3 = save, 4 = restore
+ * also for estimation of string width. This is done by interposing an 
+ * additional value on the stack. between XYsave and XYrestore,
+ * this number is increased by the strings. By pop'ing this number, all
+ * strings between XYsave and XYrestore are ignored. */
+"/MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse }\n",
+" {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont\n",
+"     6 get stringwidth pop add} {pop} ifelse} ifelse} forall} bind def\n",
+
+/* flush left show */
+"/MLshow { currentpoint stroke M\n",
+"  0 exch R\n  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def\n",
+
+/* flush right show */
+"/MRshow { currentpoint stroke M\n",
+"  exch dup MFwidth neg 3 -1 roll R\n  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def\n",
+
+/* centred show */
+"/MCshow { currentpoint stroke M\n",
+"  exch dup MFwidth -2 div 3 -1 roll R\n  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def\n",
+
+/* Save and restore for @-text (phantom box) */
+"/XYsave    { [( ) 1 2 true false 3 ()] } bind def\n",
+"/XYrestore { [( ) 1 2 true false 4 ()] } bind def\n",
+
+NULL
+};
+
+/* external/internal prologue files machinery */
+#if defined(GNUPLOT_PS_DIR)
+# if defined(_Windows)
+#  include "win/winmain.h"
+# elif defined(OS2)
+#  define INCL_DOSPROCESS
+#  define INCL_DOSMODULEMGR
+#  include <os2.h>
+# endif /* _Windows || OS2 */
+#else /* GNUPLOT_PS_DIR */
+# include "PostScript/prologues.h"
+#endif /* GNUPLOT_PS_DIR */
+
+/* added to enhpost by Matt Heffron <heffron@falstaff.css.beckman.com> */
+/* moved to post.trm by drd */
+
+static struct PS_FontName {
+       char *name;
+       struct PS_FontName *next;
+} *PS_DocFonts = NULL;
+
+static char PS_default_font[MAX_ID_LEN+1] = {'H','e','l','v','e','t','i','c','a',',','1','4','\0'};
+
+/* given a font, look in store to see if it is there already
+ * if so, return NULL. If not, reencode it if allowed to, otherwise
+ * return an appropriate re-encode string
+ */
+
+TERM_PUBLIC char *
+PS_RememberFont(char *fname, int can_reencode)
+{
+    struct PS_FontName *fnp;
+    char *recode = NULL;
+    char *myfname = "Symbol";
+
+    if (strcmp(fname, "Symbol-Oblique") != 0)
+       myfname = fname;
+
+    for (fnp = PS_DocFonts; fnp ; fnp = fnp->next)
+       if (strcmp(fnp->name, myfname) == 0)
+           return NULL;
+
+    /* we did not find the name */
+
+    fnp = (struct PS_FontName *)gp_alloc(sizeof(struct PS_FontName),
+                                        "PostScript Font record");
+    fnp->name = gp_strdup(myfname);
+    fnp->next = PS_DocFonts;
+    PS_DocFonts = fnp;
+
+    switch(encoding) {
+    case S_ENC_ISO8859_1:
+       recode = "reencodeISO def\n";
+       break;
+    case S_ENC_ISO8859_2:
+       recode = "reencodeISO2 def\n";
+       break;
+    case S_ENC_ISO8859_15:
+       recode = "reencodeISO15 def\n";
+       break;
+    case S_ENC_CP437:
+       recode = "reencodeCP437 def\n";
+       break;
+    case S_ENC_CP850 :
+       recode = "reencodeCP850 def\n";
+       break;
+    case S_ENC_CP852 :
+       recode = "reencodeCP852 def\n";
+       break;
+    case S_ENC_KOI8_R :
+       recode = "reencodeKOI8R def\n";
+       break;
+    case S_ENC_CP1250 :
+       recode = "reencodeCP1250 def\n";
+       break;
+    case S_ENC_KOI8_U :
+       recode = "reencodeKOI8U def\n";
+       break;
+    default:
+       /* do nothing */
+       break;
+    }
+
+    if (can_reencode && recode) {
+       fprintf(gppsfile,"/%s %s", myfname, recode);
+       return NULL;
+    } else
+       return recode;
+}
+
+char *
+PS_escape_string(char *origstr, char *escapelist)
+{
+    char *newstr;
+    char *n;
+
+    if (!origstr || !*origstr)
+       return NULL;
+
+    newstr = gp_alloc(2*strlen(origstr)+1,"PS_escape_string");
+    for (n=newstr; *origstr; *n++ = *origstr++) {
+       if (strchr(escapelist,*origstr))
+           *n++ = '\\';
+    }
+    *n = '\0';
+
+    return newstr;
+}
+
+static int PS_pen_x, PS_pen_y;
+static int PS_taken;
+static int PS_linetype_last;
+static double PS_linewidth_last; /* HBB NEW 20031219 */
+static TBOOLEAN PS_relative_ok;
+
+/* HBB 990914: PS_SOLID is already used by the WIN32 API headers.
+ * Renamed to PS_SOLIDE, therefore... */
+enum PS_id {
+    PS_PORTRAIT, PS_LANDSCAPE,
+    PS_EPSF, PS_DEFAULT, PS_ENHANCED, PS_NOENHANCED,
+    PS_LATEX, EPSLATEX_STANDALONE, EPSLATEX_INPUT,
+    PS_MONOCHROME, PS_COLOR, PS_BLACKTEXT, PS_COLORTEXT,
+    PS_SOLIDE, PS_DASHED, PS_DASHLENGTH, PS_LINEWIDTH,
+    PS_SIMPLEX, PS_DUPLEX, PS_DEFAULTPLEX,
+    PS_ROUNDED, PS_NOROUNDED, PS_FONTFILE, PS_NOFONTFILES,
+    PS_PALFUNCPARAM,
+    PS_LEVEL1, PS_LEVELDEFAULT, PS_FONT,
+    PSLATEX_ROTATE, PSLATEX_NOROTATE, PSLATEX_AUXFILE, PSLATEX_NOAUXFILE,
+    PSLATEX_OLDSTYLE, PSLATEX_NEWSTYLE, EPSLATEX_HEADER, EPSLATEX_NOHEADER,
+    PS_SIZE,
+    PS_OTHER
+};
+
+static struct gen_table PS_opts[] =
+{
+    { "d$efault", PS_DEFAULT },
+    { "p$ortrait", PS_PORTRAIT },
+    { "l$andscape", PS_LANDSCAPE },
+    { "ep$sf", PS_EPSF },
+    { "enh$anced", PS_ENHANCED },
+    { "noenh$anced", PS_NOENHANCED },
+    { "m$onochrome", PS_MONOCHROME },
+    { "c$olor", PS_COLOR },
+    { "c$olour", PS_COLOR },
+    { "b$lacktext", PS_BLACKTEXT },
+    { "colort$ext", PS_COLORTEXT },
+    { "colourt$ext", PS_COLORTEXT },
+    { "so$lid", PS_SOLIDE },
+    { "da$shed", PS_DASHED },
+    { "dashl$ength", PS_DASHLENGTH },
+    { "dl", PS_DASHLENGTH },
+    { "linew$idth", PS_LINEWIDTH },
+    { "lw", PS_LINEWIDTH },
+    { "size", PS_SIZE },
+    { "si$mplex", PS_SIMPLEX },
+    { "du$plex", PS_DUPLEX },
+    { "defaultp$lex", PS_DEFAULTPLEX },
+    { "butt", PS_NOROUNDED },
+    { "rou$nded", PS_ROUNDED },
+    { "fontf$ile", PS_FONTFILE },
+    { "nofontf$iles", PS_NOFONTFILES },
+    { "palf$uncparam", PS_PALFUNCPARAM },
+    { "level1", PS_LEVEL1 },
+    { "leveldefault", PS_LEVELDEFAULT },
+    { "font", PS_FONT },
+    { "stand$alone", EPSLATEX_STANDALONE },
+    { "inp$ut", EPSLATEX_INPUT },
+    { "header", EPSLATEX_HEADER },
+    { "noheader", EPSLATEX_NOHEADER },
+    { "r$otate", PSLATEX_ROTATE },
+    { "n$orotate", PSLATEX_NOROTATE },
+    { "a$uxfile", PSLATEX_AUXFILE },
+    { "noa$uxfile", PSLATEX_NOAUXFILE },
+    { "old$style", PSLATEX_OLDSTYLE },
+    { "new$style", PSLATEX_NEWSTYLE },
+    { NULL, PS_OTHER }
+};
+
+
+TERM_PUBLIC void
+PS_options()
+{
+    struct value a;
+    char *s;
+    char *ps_fontfile_char = NULL;
+    char tmp_term_options[MAX_LINE_LEN+1] = "";
+
+    TBOOLEAN set_orientation = FALSE, set_enhanced = FALSE, set_plex = FALSE;
+    TBOOLEAN set_level = FALSE, set_color = FALSE, set_dashed = FALSE;
+    TBOOLEAN set_dashlen = FALSE, set_linewidth = FALSE, set_round = FALSE;
+    TBOOLEAN set_palfunc = FALSE, set_colortext = FALSE;
+    TBOOLEAN set_standalone = FALSE, set_epslheader = FALSE;
+    TBOOLEAN set_pslrotate = FALSE, set_pslauxfile = FALSE;
+    TBOOLEAN set_psloldstyle = FALSE, set_font = FALSE, set_fontsize = FALSE;
+
+    /* Annoying hack to handle the case of 'set termoption' after */
+    /* we have already initialized the terminal.                  */
+    if (c_token != 2)
+       ps_explicit_size = FALSE;
+
+    if (strcmp(term->name, "pstex") == 0)
+       ps_params = &pstex_params;
+    else if (strcmp(term->name, "pslatex") == 0)
+       ps_params = &pslatex_params;
+    else if (strcmp(term->name, "epslatex") == 0) {
+       ps_params = &epslatex_params;
+    } else
+       ps_params = &post_params;
+
+    if (ps_params->terminal == PSTERM_POSTSCRIPT) {
+       if (pslatex_auxname)
+           free(pslatex_auxname);
+       pslatex_auxname = NULL;
+    } else {
+       term->set_font = PS_set_font;
+    }
+
+    if (!END_OF_COMMAND) {
+       if (lookup_table(&PS_opts[0],c_token) == PS_DEFAULT) {
+           switch (ps_params->terminal) {
+           case PSTERM_POSTSCRIPT:
+               while (ps_params->first_fontfile != NULL)
+                   delete_ps_fontfile((struct ps_fontfile_def *) NULL,
+                                      ps_params->first_fontfile);
+               *ps_params = post_params_default;
+               break;
+           case PSTERM_EPSLATEX:
+               *ps_params = epslatex_params_default;
+               break;
+           case PSTERM_PSLATEX:
+               *ps_params = pslatex_params_default;
+               break;
+           case PSTERM_PSTEX:
+               *ps_params = pstex_params_default;
+               break;
+           }
+           term->flags &= ~TERM_ENHANCED_TEXT;
+           c_token++;
+           if (!END_OF_COMMAND) 
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+       }
+    }
+
+    while (!END_OF_COMMAND) {
+       switch(lookup_table(&PS_opts[0],c_token)) {
+       case PS_PORTRAIT:
+           if (set_orientation || ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_orientation = TRUE;
+           ps_params->psformat = PSTERM_PORTRAIT;
+           c_token++;
+           break;
+       case PS_LANDSCAPE:
+           if (set_orientation || ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_orientation = TRUE;
+           ps_params->psformat = PSTERM_LANDSCAPE;
+           c_token++;
+           break;
+       case PS_EPSF:
+           if (set_orientation || ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_orientation = TRUE;
+           ps_params->psformat = PSTERM_EPS;
+           c_token++;
+           break;
+       case PS_LEVEL1:
+           if (set_level)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_level = TRUE;
+           ps_params->level1 = TRUE;
+           c_token++;
+           break;
+       case PS_LEVELDEFAULT:
+           if (set_level)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_level = TRUE;
+           ps_params->level1 = FALSE;
+           c_token++;
+           break;
+       case PS_DEFAULT:
+           int_error(c_token,
+                     "extraneous argument in set terminal %s",term->name);
+           c_token++;
+           break;
+       case PS_ENHANCED:
+           if (set_enhanced || ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_enhanced = TRUE;
+           term->put_text = ENHPS_put_text;
+           term->set_font = ENHPS_set_font;
+           term->flags |= TERM_ENHANCED_TEXT;
+           ++c_token;
+           break;
+       case PS_NOENHANCED:
+            if (set_enhanced || ps_params->terminal != PSTERM_POSTSCRIPT)
+                int_error(c_token,
+                          "extraneous argument in set terminal %s",term->name);
+           set_enhanced = TRUE;
+           term->put_text = PS_put_text;
+           term->set_font = PS_set_font;
+           term->flags &= ~TERM_ENHANCED_TEXT;
+           ++c_token;
+           break;
+#ifdef PSLATEX_DRIVER
+       case EPSLATEX_STANDALONE:
+           if (set_standalone || ps_params->terminal != PSTERM_EPSLATEX)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_standalone = TRUE;
+           ps_params->epslatex_standalone = TRUE;
+           ++c_token;
+           break;
+       case EPSLATEX_INPUT:
+           if (set_standalone || ps_params->terminal != PSTERM_EPSLATEX)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_standalone = TRUE;
+           ps_params->epslatex_standalone = FALSE;
+           ++c_token;
+           break;
+
+       case EPSLATEX_HEADER:
+           if (set_epslheader || ps_params->terminal != PSTERM_EPSLATEX)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_epslheader = TRUE;
+           ++c_token;
+           free(epslatex_header);
+           /* Protect against int_error() bail from try_to_get_string() */
+               epslatex_header = NULL;
+           epslatex_header = try_to_get_string();
+           if (!epslatex_header)
+               int_error(c_token,"String containing header information expected");
+           break;
+
+       case EPSLATEX_NOHEADER:
+           if (set_epslheader || ps_params->terminal != PSTERM_EPSLATEX)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_epslheader = TRUE;
+           free(epslatex_header);
+           epslatex_header = NULL;
+           ++c_token;
+           break;
+
+       case PSLATEX_ROTATE:
+           if (set_pslrotate || ((ps_params->terminal != PSTERM_PSLATEX) &&
+                                 (ps_params->terminal != PSTERM_PSTEX)))
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_pslrotate = TRUE;
+           ps_params->rotate = TRUE;
+           ++c_token;
+           break;
+       case PSLATEX_NOROTATE:
+           if (set_pslrotate || ((ps_params->terminal != PSTERM_PSLATEX) &&
+                                 (ps_params->terminal != PSTERM_PSTEX)))
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_pslrotate = TRUE;
+           ps_params->rotate = FALSE;
+           ++c_token;
+           break;
+       case PSLATEX_AUXFILE:
+           if (set_pslauxfile ||
+               ((ps_params->terminal == PSTERM_POSTSCRIPT) ||
+                (ps_params->terminal == PSTERM_EPSLATEX)))
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_pslauxfile = TRUE;
+           ps_params->useauxfile = TRUE;
+           c_token++;
+           break;
+       case PSLATEX_NOAUXFILE:
+           if (set_pslauxfile ||
+               ((ps_params->terminal == PSTERM_POSTSCRIPT) ||
+                (ps_params->terminal == PSTERM_EPSLATEX)))
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_pslauxfile = TRUE;
+           ps_params->useauxfile = FALSE;
+           c_token++;
+           break;
+       case PSLATEX_OLDSTYLE:
+           if (set_psloldstyle || ps_params->terminal == PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_psloldstyle = TRUE;
+           ps_params->oldstyle = TRUE;
+           if (ps_params->terminal == PSTERM_EPSLATEX)
+               ps_params->rounded = TRUE;
+           c_token++;
+           break;
+       case PSLATEX_NEWSTYLE:
+           if (set_psloldstyle || ps_params->terminal == PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_psloldstyle = TRUE;
+           ps_params->oldstyle = FALSE;
+           c_token++;
+           break;
+#endif
+       case PS_MONOCHROME:
+           if (set_color)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_color = TRUE;
+           ps_params->color = FALSE;
+           c_token++;
+           break;
+       case PS_COLOR:
+           if (set_color)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_color = TRUE;
+           ps_params->color = TRUE;
+           c_token++;
+           break;
+       case PS_BLACKTEXT:
+           if (set_colortext || ((ps_params->terminal != PSTERM_POSTSCRIPT) &&
+                                 (ps_params->terminal != PSTERM_EPSLATEX)))
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_colortext = TRUE;
+           ps_params->blacktext = TRUE;
+           c_token++;
+           break;
+       case PS_COLORTEXT:
+           if (set_colortext || ((ps_params->terminal != PSTERM_POSTSCRIPT) &&
+                                 (ps_params->terminal != PSTERM_EPSLATEX)))
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_colortext = TRUE;
+           ps_params->blacktext = FALSE;
+           c_token++;
+           break;
+        case PS_SOLIDE:
+           if (set_dashed)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_dashed = TRUE;
+           ps_params->solid = TRUE;
+           c_token++;
+           break;
+       case PS_DASHED:
+           if (set_dashed)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_dashed = TRUE;
+           ps_params->solid = FALSE;
+           c_token++;
+           break;
+       case PS_DASHLENGTH:
+           if (set_dashlen)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_dashlen = TRUE;
+           c_token++;
+           ps_params->dash_length = real(const_express(&a));
+           if (ps_params->dash_length <= 0.0)
+               ps_params->dash_length = 1.0;
+           break;
+       case PS_LINEWIDTH:
+           if (set_linewidth)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_linewidth = TRUE;
+           c_token++;
+           ps_params->linewidth_factor = real(const_express(&a));
+           if (ps_params->linewidth_factor <= 0.0)
+               ps_params->linewidth_factor = 1.0;
+           break;
+       case PS_SIMPLEX:
+           if (set_plex || ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_plex = TRUE;
+           ps_params->duplex_state  = FALSE;
+           ps_params->duplex_option = TRUE;
+           c_token++;
+           break;
+       case PS_DUPLEX:
+           if (set_plex || ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_plex = TRUE;
+           ps_params->duplex_state  = TRUE;
+           ps_params->duplex_option = TRUE;
+           c_token++;
+           break;
+       case PS_DEFAULTPLEX:
+           if (set_plex || ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_plex = TRUE;
+           ps_params->duplex_option = FALSE;
+           c_token++;
+           break;
+       case PS_ROUNDED:
+           if (set_round)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_round = TRUE;
+           ps_params->rounded = TRUE;
+           c_token++;
+           break;
+       case PS_NOROUNDED:
+           if (set_round)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_round = TRUE;
+           ps_params->rounded = FALSE;
+           c_token++;
+           break;
+        case PS_FONTFILE: {
+            TBOOLEAN deleteentry = FALSE;
+            c_token++;
+           if (ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+
+            if (!isstring(c_token)) {
+                if (equals(c_token, "add"))
+                    c_token++;
+                else if (almost_equals(c_token, "del$ete")) {
+                    deleteentry = TRUE;
+                    c_token++;
+                } else
+                    int_error(c_token, "Font filename expected");
+            }
+            if (isstring(c_token)) {
+                TBOOLEAN filename_doubled = FALSE;
+                struct ps_fontfile_def *curr_ps_fontfile = 
+                   ps_params->first_fontfile;
+                struct ps_fontfile_def *prev_ps_fontfile = NULL;
+                struct ps_fontfile_def *new_ps_fontfile =
+                     gp_alloc(sizeof(struct ps_fontfile_def),
+                             "new_ps_fontfile");
+
+                new_ps_fontfile->fontfile_name =
+                    gp_alloc (token_len(c_token),
+                              "new_ps_fontfile->fontfile_name");
+                quote_str(new_ps_fontfile->fontfile_name,
+                          c_token, token_len(c_token));
+                gp_expand_tilde(&(new_ps_fontfile->fontfile_name));
+               if (!deleteentry) {
+#if defined(PIPES)
+                   if (*(new_ps_fontfile->fontfile_name) != '<') {
+#endif
+                       new_ps_fontfile->fontfile_fullname =
+                           fontpath_fullname(new_ps_fontfile->fontfile_name);
+                       if (!new_ps_fontfile->fontfile_fullname)
+                           int_error(c_token, "Font file '%s' not found",
+                                     new_ps_fontfile->fontfile_name);
+#if defined(PIPES)
+                   } else
+                       new_ps_fontfile->fontfile_fullname = NULL;
+#endif
+
+               }
+                new_ps_fontfile->next = NULL;
+
+               if (!deleteentry) {
+                   LFS *lf=lf_head;
+                   if (lf) {
+                       while (lf->prev)
+                           lf=lf->prev;
+                   }
+                   if ((lf && lf->interactive) || interactive)
+                       /* if (interactive) { */
+                       PS_load_fontfile(new_ps_fontfile,FALSE);
+               }
+
+                if (ps_params->first_fontfile) {
+                    while (curr_ps_fontfile) {
+                        if (strcmp(curr_ps_fontfile->fontfile_name,
+                                   new_ps_fontfile->fontfile_name) == 0) {
+                            filename_doubled = TRUE;
+                            if (deleteentry) {
+                               delete_ps_fontfile(prev_ps_fontfile,
+                                                  curr_ps_fontfile);
+                                curr_ps_fontfile = NULL;
+                                break;
+                            }
+                        }
+                        prev_ps_fontfile = curr_ps_fontfile;
+                        curr_ps_fontfile = curr_ps_fontfile->next;
+                    }
+                    if (!filename_doubled) {
+                        if (!deleteentry)
+                            prev_ps_fontfile->next = new_ps_fontfile;
+                        else
+                            int_warn(c_token,"Can't delete Font filename '%s'",
+                                     new_ps_fontfile->fontfile_name);
+                    }
+                } else {
+                    if (!deleteentry)
+                        ps_params->first_fontfile = new_ps_fontfile;
+                    else
+                        int_warn(c_token, "Can't delete Font filename '%s'",
+                                 new_ps_fontfile->fontfile_name);
+                }
+                c_token++;
+            } else
+                int_error(c_token, "Font filename expected");
+            break;
+        }
+        case PS_NOFONTFILES:
+           if (ps_params->terminal != PSTERM_POSTSCRIPT)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           while (ps_params->first_fontfile != NULL)
+               delete_ps_fontfile((struct ps_fontfile_def *) NULL,
+                                  ps_params->first_fontfile);
+           ++c_token;
+           break;
+       case PS_PALFUNCPARAM:
+           if (set_palfunc)
+               int_error(c_token,
+                         "extraneous argument in set terminal %s",term->name);
+           set_palfunc = TRUE;
+           ++c_token;
+           ps_params->palfunc_samples = (int)real(const_express(&a));
+           if (ps_params->palfunc_samples < 2)
+               ps_params->palfunc_samples = 2;
+           if (!END_OF_COMMAND && equals(c_token, ",")) {
+               ++c_token;
+               ps_params->palfunc_deviation = fabs(real(const_express(&a)));
+               if (ps_params->palfunc_deviation >= 1)
+                   int_error(c_token-1,"allowed deviation must be < 1");
+           }
+           break;
+       
+       case PS_SIZE:
+           {
+           float xmax_t, ymax_t;
+
+           c_token++;
+           ps_explicit_size = TRUE;
+           ps_explicit_units = parse_term_size(&xmax_t, &ymax_t, INCHES);
+
+           /* PostScript *always* works in pts, not locally defined dpi */
+           term->xmax = xmax_t * PS_SC * 72./gp_resolution;
+           term->ymax = ymax_t * PS_SC * 72./gp_resolution;
+           eps_explicit_x = 2 * term->xmax;
+           eps_explicit_y = 2 * term->ymax;
+           break;
+           }
+       
+       case PS_FONT:
+           c_token++;
+           /* Fall through to attempt to read font name */
+       case PS_OTHER:
+       default:
+           if ((s = try_to_get_string())) {
+               if (set_font)
+                   int_error(c_token,
+                             "extraneous argument in set terminal %s",
+                             term->name);
+               set_font = TRUE;
+               if ((ps_params->terminal == PSTERM_POSTSCRIPT) ||
+                   (ps_params->terminal == PSTERM_EPSLATEX)) {
+                   char *comma = strrchr(s,',');
+                   if (comma && (1 == sscanf(comma+1,"%f",&ps_params->fontsize))) {
+                       set_fontsize = TRUE;
+                       *comma = '\0';
+                   }
+                   if (*s)
+                       strncpy(ps_params->font, s, sizeof(ps_params->font));
+                   free(s);
+               } else
+                   int_error(c_token-1,
+                             "terminal %s does not allow specification %s",
+                             term->name, "of font name");
+           } else {
+               if (set_fontsize)
+                   int_error(c_token,
+                             "extraneous argument in set terminal %s",
+                             term->name);
+               set_fontsize = TRUE;
+               /* We have font size specified */
+               ps_params->fontsize = real(const_express(&a));
+           }
+           break;
+       }
+    }
+
+    switch (ps_params->terminal) {
+    case PSTERM_POSTSCRIPT:
+       ps_fontsize = ps_params->fontsize;
+       break;
+    case PSTERM_EPSLATEX:
+       ps_fontsize = 2 * ps_params->fontsize;
+       break;
+    case PSTERM_PSLATEX:
+    case PSTERM_PSTEX:
+       if (ps_params->fontsize > 0)
+           ps_fontsize = 2 * ps_params->fontsize;
+       else
+           ps_fontsize = 20; /* default: 10pt */
+       break;
+    }
+    term->v_char = (unsigned int)(ps_fontsize*PS_SC);
+    if (ps_params->oldstyle)
+       term->h_char = (unsigned int)(ps_fontsize*PS_SC*5/10);
+    else
+       term->h_char = (unsigned int)(ps_fontsize*PS_SC*6/10);
+    sprintf(PS_default_font,"%s,%g",ps_params->font,ps_fontsize);
+
+    if (ps_params->terminal == PSTERM_POSTSCRIPT) {
+       if (ps_params->first_fontfile) {
+           struct ps_fontfile_def *curr_ps_fontfile =
+               ps_params->first_fontfile;
+           unsigned int totlength = 0;
+           char *running;
+
+           while (curr_ps_fontfile) {
+               totlength += strlen(curr_ps_fontfile->fontfile_name) +
+                   strlen(" fontfile \"\"");
+               curr_ps_fontfile = curr_ps_fontfile->next;
+           }
+           curr_ps_fontfile = ps_params->first_fontfile;
+           ps_fontfile_char = gp_alloc (totlength+1,"ps_fontfile_char");
+           running = ps_fontfile_char;
+           while (curr_ps_fontfile) {
+               sprintf(running," fontfile \"%s\"",
+                       curr_ps_fontfile->fontfile_name);
+               running += strlen(running);
+               curr_ps_fontfile = curr_ps_fontfile->next;
+           }
+       }
+    }
+
+    /* HBB 19990823: fixed the options string. It violated the 'save
+     * loadable output' rule */
+    if (ps_params->terminal == PSTERM_POSTSCRIPT)
+       sprintf(term_options,"%s %s %s \\\n",
+               ps_params->psformat==PSTERM_EPS ? "eps" :
+               (ps_params->psformat==PSTERM_PORTRAIT ?
+                "portrait" : "landscape"),
+               term->put_text == ENHPS_put_text ? "enhanced" : "noenhanced",
+               ps_params->duplex_option ? (ps_params->duplex_state ?
+                                           "duplex" : "simplex")
+               : "defaultplex");
+    else if (ps_params->terminal != PSTERM_EPSLATEX)
+       sprintf(term_options, "%s%s",
+               ps_params->rotate ? "rotate" : "norotate",
+               ps_params->useauxfile ? " auxfile" : "");
+    else
+       term_options[0] = '\0';
+
+    sprintf(tmp_term_options,"   %s %s %s \\\n\
+   %s dashlength %.1f linewidth %.1f %s \\\n",
+           ps_params->level1 ? "level1" : "leveldefault",
+           ps_params->color ? "color" : "monochrome",
+           ps_params->blacktext ? "blacktext" : "colortext",
+           ps_params->solid ? "solid" : "dashed",
+           ps_params->dash_length,
+           ps_params->linewidth_factor,
+           ps_params->rounded ? "rounded" : "butt");
+    strcat(term_options,tmp_term_options);
+
+    sprintf(tmp_term_options,"   palfuncparam %d,%g \\\n   ",
+           ps_params->palfunc_samples, ps_params->palfunc_deviation);
+    strcat(term_options,tmp_term_options);
+
+#ifdef PSLATEX_DRIVER
+    if ((ps_params->terminal == PSTERM_PSTEX) ||
+       (ps_params->terminal == PSTERM_PSLATEX)) {
+       sprintf(tmp_term_options, "%s %s ",
+               ps_params->rotate ? "rotate" : "norotate",
+               ps_params->useauxfile ? "auxfile" : "noauxfile");
+       strcat(term_options,tmp_term_options);
+    }
+
+    if (ps_params->terminal == PSTERM_EPSLATEX) {
+       sprintf(tmp_term_options, "%s ",
+               ps_params->epslatex_standalone ? "standalone" : "input");
+       if (epslatex_header)
+           sprintf(tmp_term_options, "header \"%s\" ", epslatex_header);
+       else
+           sprintf(tmp_term_options, "noheader ");
+       strcat(term_options,tmp_term_options);
+    }
+#endif
+
+    if (ps_explicit_size) {
+       if (ps_explicit_units == CM)
+           sprintf(tmp_term_options,"size %.2fcm, %.2fcm ",
+               2.54*(float)term->xmax/(72.*PS_SC), 2.54*(float)term->ymax/(72.*PS_SC));
+       else
+           sprintf(tmp_term_options,"size %.2fin, %.2fin ",
+               (float)term->xmax/(72.*PS_SC), (float)term->ymax/(72.*PS_SC));
+       strcat(term_options,tmp_term_options);
+    }
+
+    if (ps_params->terminal == PSTERM_POSTSCRIPT)
+       sprintf(tmp_term_options,"\"%s\" %g%s ",
+               ps_params->font,ps_params->fontsize,
+               ps_fontfile_char ? ps_fontfile_char : "");
+    else if (ps_params->terminal == PSTERM_EPSLATEX)
+       sprintf(tmp_term_options,"\"%s\" %g ",
+               ps_params->font,ps_params->fontsize);
+    else if (ps_params->fontsize)
+       sprintf(tmp_term_options,"%g ",ps_params->fontsize);
+    else
+       tmp_term_options[0]='\0';
+    if (ps_fontfile_char)
+       free(ps_fontfile_char);
+
+    strcat(term_options,tmp_term_options);
+
+}
+
+/* store settings passed to common_init() for use in PS_graphics()
+ * ps_params->psformat, etc are reserved for storing the term options
+ */
+static TBOOLEAN ps_common_uses_fonts;
+static unsigned int ps_common_xoff, ps_common_yoff;
+
+
+TERM_PUBLIC void
+PS_load_fontfile(struct ps_fontfile_def *current_ps_fontfile, TBOOLEAN doload)
+{
+    if (current_ps_fontfile) {
+       unsigned int linesread = 0;
+       FILE *ffont = NULL;
+       char line[256];
+       char ext[4];
+       char cmd[256];
+       char *fontname = NULL;
+#if defined(PIPES)
+       char *envcmd = NULL;
+       TBOOLEAN ispipe = FALSE;
+#endif
+
+       ext[0] = '\0';
+       cmd[0] = '\0';
+
+       if (doload)
+           fprintf(gppsfile,"%%%%BeginProcSet: %s\n",
+                   current_ps_fontfile->fontfile_name);
+
+       /* get filename extension if no pipe (if pipe *ext=='\0') */
+#if defined(PIPES)
+       if (*(current_ps_fontfile->fontfile_name) != '<') {
+           /* Filename is given */
+#endif
+           if (strlen(current_ps_fontfile->fontfile_name) > 3)
+               strcpy(ext, current_ps_fontfile->fontfile_name +
+                      strlen(current_ps_fontfile->fontfile_name) - 3);
+           else
+               strcpy(ext, current_ps_fontfile->fontfile_name);
+
+           /* make extension lowercase for comparison */
+           lower_case(ext);
+
+           if (!current_ps_fontfile->fontfile_fullname)
+               int_error(NO_CARET, "Font file '%s' not found",
+                         current_ps_fontfile->fontfile_name);
+#if defined(PIPES)
+       }
+#endif
+       if (strlen(ext) == 0) {
+#if defined(PIPES)
+           /* Pipe is given */
+           ispipe = TRUE;
+           strcpy(cmd,current_ps_fontfile->fontfile_name + 1);
+           ffont = popen(cmd, "r");
+           if (!ffont)
+               int_error(NO_CARET, "Could not execute pipe '%s'",
+                         current_ps_fontfile->fontfile_name + 1);
+#endif
+       }
+       else if (strcmp(ext,"ttf") == 0) {
+           /* TrueType */
+#if defined(PIPES)
+           ispipe = TRUE;
+           envcmd = getenv("GNUPLOT_TTFTOPFA");
+           if (envcmd != NULL)
+               sprintf(cmd,envcmd,current_ps_fontfile->fontfile_fullname);
+           else
+               sprintf(cmd,"ttf2pt1 -a -e -W 0 %s -",
+                       current_ps_fontfile->fontfile_fullname);
+           if (strlen(cmd) == 0)
+               int_error(NO_CARET,
+                         "No command for automatic font conversion ttf->pfa defined");
+           else {
+               ffont = popen(cmd,"r");
+               if (!ffont)
+                   int_error(NO_CARET,"Could not execute command '%s'", cmd);
+           }
+#else
+           os_error(NO_CARET,
+                    "Automatic font conversion ttf->pfa not supported");
+#endif
+       } else if (strcmp(ext,"pfb") == 0) {
+           /* PFB */
+#if defined(PIPES)
+           ispipe = TRUE;
+           envcmd = getenv("GNUPLOT_PFBTOPFA");
+           if (envcmd != NULL)
+               sprintf(cmd,envcmd,current_ps_fontfile->fontfile_fullname);
+           else
+               sprintf(cmd,"pfbtops %s",
+                       current_ps_fontfile->fontfile_fullname);
+           if (strlen(cmd) == 0)
+               int_error(NO_CARET,
+                         "No command for automatic font conversion pfb->pfa defined");
+           else {
+               ffont = popen(cmd,"r");
+               if (!ffont)
+                   int_error(NO_CARET,"Could not execute command '%s'", cmd);
+           }
+#else
+           os_error(NO_CARET,
+                    "Automatic font conversion pfb->pfa not supported");
+#endif
+       } else {
+           /* PFA */
+           if (strcmp(ext,"pfa") != 0)
+               int_warn(NO_CARET,
+                        "Font file '%s' has unknown extension. Assume it is a pfa file",
+                        current_ps_fontfile->fontfile_name);
+           ffont = fopen(current_ps_fontfile->fontfile_fullname, "r");
+           if (!ffont)
+               int_error(NO_CARET, "Font file '%s' not found",
+                         current_ps_fontfile->fontfile_name);
+       }
+       /* read the file */
+       while (fgets(line,255,ffont)) {
+           /* test file format */
+           if ((linesread == 0) &&
+                (strstr(line,"%!PS-AdobeFont") != line) &&
+                (strstr(line,"%!FontType1") != line)) {
+#if defined(PIPES)
+               if (ispipe)
+                   int_warn(NO_CARET,
+                            "Command '%s' seems not to generate PFA data",
+                            cmd);
+               else
+#endif
+                   int_warn(NO_CARET,
+                            "Font file '%s' seems not to be a PFA file",
+                            current_ps_fontfile->fontfile_name);
+           }
+           /* get fontname */
+           if (strstr(line,"/FontName") == line) {
+               char *fnende = NULL;
+               fontname = gp_alloc(strlen(line)-9,"load_fontfiles");
+               strcpy(fontname,strstr(line+1,"/")+1);
+               fnende = strstr(fontname," ");
+               *fnende = '\0';
+               /* Print font name */
+               if (!doload) {
+                   if (current_ps_fontfile->fontfile_fullname)
+                       fprintf(stderr,
+                               "Font file '%s' contains the font '%s'. Location:\n   %s\n",
+                               current_ps_fontfile->fontfile_name,
+                               fontname,
+                               current_ps_fontfile->fontfile_fullname);
+                   else
+                       fprintf(stderr,
+                               "Pipe '%s' contains the font '%s'.\n",
+                               current_ps_fontfile->fontfile_name,
+                               fontname);
+#if defined(PIPES)
+                   /* Stop reading font file in order to save time */
+                   /* This does not work for pipes because they give the */
+                   /* error message 'broken pipe' */
+                   if (!ispipe)
+#endif
+                       break;
+               }
+           }
+
+           if (doload)
+               fputs(line, gppsfile);
+
+           ++linesread;
+       }
+#if defined(PIPES)
+       if (ispipe) {
+           int exitcode;
+           if ((exitcode = pclose(ffont)) != 0)
+               int_error(NO_CARET,
+                         "Command '%s' generated error, exitcode is %d",
+                         cmd, exitcode);
+       }
+       else
+#endif
+           fclose(ffont);
+
+       if (linesread == 0) {
+#if defined(PIPES)
+           if (ispipe)
+               int_error(NO_CARET,
+                         "Command '%s' generates empty output",
+                         cmd);
+           else
+#endif
+               int_error(NO_CARET, "Font file '%s' is empty",
+                         current_ps_fontfile->fontfile_name);
+       }
+       if (doload)
+           fputs("%%EndProcSet\n", gppsfile);
+
+       /* Computer Modern Symbol font with corrected baseline if the
+        * font CMEX10 is embedded */
+       if (doload && fontname && (strcmp(fontname,"CMEX10") == 0)) {
+           fputs("%%BeginProcSet: CMEX10-Baseline\n", gppsfile);
+           fputs("/CMEX10-Baseline /CMEX10 findfont [1 0 0 1 0 1] makefont\n",
+                 gppsfile);
+           fputs("dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall\n", gppsfile);
+           fputs("currentdict end definefont pop\n", gppsfile);
+           fputs("%%EndProcSet\n",gppsfile);
+       }
+
+       if (fontname) {
+           free(fontname);
+           fontname = NULL;
+       }
+    }
+}
+
+
+TERM_PUBLIC void
+PS_load_fontfiles(TBOOLEAN doload)
+{
+    struct ps_fontfile_def *current_ps_fontfile=ps_params->first_fontfile;
+
+    while (current_ps_fontfile) {
+       PS_load_fontfile(current_ps_fontfile,doload);
+       current_ps_fontfile = current_ps_fontfile->next;
+    }
+}
+
+
+TERM_PUBLIC void
+PS_common_init(
+    TBOOLEAN uses_fonts,               /* FALSE for (e)ps(la)tex */
+    unsigned int xoff, unsigned int yoff, /* how much to translate by */
+    unsigned int bb_xmin, unsigned int bb_ymin,
+    unsigned int bb_xmax, unsigned int bb_ymax, /* bounding box */
+    const char **dict) /* extra entries for the dictionary */
+{
+    static const char GPFAR psi1[] = "\
+%%%%Creator: gnuplot %s patchlevel %s\n\
+%%%%CreationDate: %s\n\
+%%%%DocumentFonts: %s\n";
+
+    static const char GPFAR psi2[] = "\
+%%%%EndComments\n\
+%%%%BeginProlog\n\
+/gnudict 256 dict def\ngnudict begin\n\
+%%\n\
+%% The following 6 true/false flags may be edited by hand if required\n\
+%% The unit line width may also be changed\n\
+%%\n\
+/Color %s def\n\
+/Blacktext %s def\n\
+/Solid %s def\n\
+/Dashlength %g def\n\
+/Landscape %s def\n\
+/Level1 %s def\n\
+/Rounded %s def\n\
+/TransparentPatterns false def\n\
+/gnulinewidth %.3f def\n\
+/userlinewidth gnulinewidth def\n\
+%%\n\
+/vshift %d def\n\
+/dl1 {\n\
+  %.1f Dashlength mul mul\n\
+  Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if\n\
+} def\n\
+/dl2 {\n\
+  %.1f Dashlength mul mul\n\
+  Rounded { currentlinewidth 0.75 mul add } if\n\
+} def\n\
+/hpt_ %.1f def\n\
+/vpt_ %.1f def\n\
+/hpt hpt_ def\n\
+/vpt vpt_ def\n";
+
+    static const char GPFAR psi3[] = "\
+Level1 {} {\n\
+/SDict 10 dict def\n\
+systemdict /pdfmark known not {\n\
+  userdict /pdfmark systemdict /cleartomark get put\n\
+} if\n\
+SDict begin [\n\
+  /Title (%s)\n\
+  /Subject (gnuplot plot)\n\
+  /Creator (gnuplot %s patchlevel %s)\n\
+  /Author (%s)\n\
+%%  /Producer (gnuplot)\n\
+%%  /Keywords ()\n\
+  /CreationDate (%s)\n\
+  /DOCINFO pdfmark\n\
+end\n\
+} ifelse\n";
+
+
+    struct termentry *t = term;
+    int i;
+    time_t now;
+    char *timedate;
+
+    ps_common_uses_fonts = uses_fonts;
+    ps_common_xoff = xoff;
+    ps_common_yoff = yoff;
+
+    ps_page = 0;
+
+    time(&now);
+    timedate=asctime(localtime(&now));
+    timedate[strlen(timedate)-1]='\0';
+
+#ifdef PSLATEX_DRIVER
+    /* Set files for (e)ps(la)tex terminals */
+    switch (ps_params->terminal) {
+    case PSTERM_EPSLATEX:
+       EPSLATEX_common_init();
+       break;
+    case PSTERM_PSLATEX:
+    case PSTERM_PSTEX:
+       PSTEX_common_init();
+       break;
+    default:; /* do nothing, just avoid a compiler warning */
+    }
+#endif
+
+    if (ps_params->psformat == PSTERM_EPS)
+       fputs("%!PS-Adobe-2.0 EPSF-2.0\n", gppsfile);
+    else
+       fputs("%!PS-Adobe-2.0\n", gppsfile);
+
+    if (outstr)
+       fprintf(gppsfile, "%%%%Title: %s\n", outstr);   /*  JFi  */
+    fprintf(gppsfile, psi1, gnuplot_version, gnuplot_patchlevel,
+           timedate, uses_fonts ? "(atend)" : "");
+
+    fprintf(gppsfile,"%%%%BoundingBox: %d %d %d %d\n",
+           xoff + bb_xmin, yoff + bb_ymin, xoff + bb_xmax, yoff + bb_ymax);
+
+    if ((ps_params->terminal == PSTERM_POSTSCRIPT) &&
+       (ps_params->psformat != PSTERM_EPS))
+       fprintf(gppsfile,"%%%%Orientation: %s\n",
+               ps_params->psformat == PSTERM_LANDSCAPE ?
+               "Landscape" : "Portrait");
+
+    if (ps_params->psformat != PSTERM_EPS)
+       fputs("%%Pages: (atend)\n", gppsfile);
+    fprintf(gppsfile, psi2,
+           ps_params->color ? "true" : "false",
+           ps_params->blacktext ? "true" : "false",
+           ps_params->solid ? "true" : "false",
+           ps_params->dash_length,     /* dash length */
+           ps_params->psformat == PSTERM_LANDSCAPE ? "true" : "false",
+           ps_params->level1 ? "true" : "false",
+           ps_params->rounded ? "true" : "false",
+           PS_LW*ps_params->linewidth_factor,  /* line width */
+           (int)(t->v_char)/(-3),      /* shift for vertical centring */
+           PS_SC*1.0,  /* dash length */
+           PS_SC*1.0,  /* dash length */
+           PS_HTIC/2.0,                /* half point width */
+           PS_VTIC/2.0);               /* half point height */
+
+    /* HH: print pdf information interpreted by ghostscript/acrobat */
+    {
+       char *username=getusername();
+       char *username2=PS_escape_string(username,"()\\");
+       char *outstr2=PS_escape_string(outstr,"()\\");
+       fprintf(gppsfile, psi3,
+               outstr2?outstr2:"",
+               gnuplot_version, gnuplot_patchlevel,
+               username2?username2:"", 
+               timedate);
+       if (username)
+           free(username);
+       if (username2)
+           free(username2);
+       if (outstr2)
+           free(outstr2);
+    }
+
+    /* insert font encoding vector */
+    if (uses_fonts) {
+       switch (encoding) {
+           case S_ENC_ISO8859_1:   PS_dump_prologue_file("8859-1.ps"); break;
+           case S_ENC_ISO8859_2:   PS_dump_prologue_file("8859-2.ps"); break;
+           case S_ENC_ISO8859_15:  PS_dump_prologue_file("8859-15.ps"); break;
+           case S_ENC_CP437:       PS_dump_prologue_file("cp437.ps"); break;
+           case S_ENC_CP850:       PS_dump_prologue_file("cp850.ps"); break;
+           case S_ENC_CP852:       PS_dump_prologue_file("cp852.ps"); break;
+           case S_ENC_CP1250:      PS_dump_prologue_file("cp1250.ps"); break;
+           case S_ENC_KOI8_R:      PS_dump_prologue_file("koi8r.ps"); break;
+           case S_ENC_KOI8_U:      PS_dump_prologue_file("koi8u.ps"); break;
+           case S_ENC_DEFAULT:
+           default:                break;
+       }
+    }
+
+    /* Dump the body of the prologue */
+    PS_dump_prologue_file("prologue.ps");
+
+    /* Redefine old epslatex linetypes if requested */
+    if ((ps_params->terminal == PSTERM_EPSLATEX) && ps_params->oldstyle) {
+       for (i = 0; OldEPSL_linetypes[i] != NULL; i++)
+           fprintf(gppsfile,"%s",OldEPSL_linetypes[i]);
+    }
+
+    if (ps_params->duplex_option)
+       fprintf(gppsfile, "statusdict begin %s setduplexmode end\n",
+               ps_params->duplex_state ? "true" : "false");
+
+    if (dict)
+       while (*dict)
+           fputs(*(dict++), gppsfile);
+
+    if (uses_fonts) {
+       PS_load_fontfiles(TRUE);
+       PS_RememberFont(ps_params->font, 1);
+    }
+
+    fputs("end\n%%EndProlog\n", gppsfile);
+}
+
+/* the init fn for the postscript driver */
+TERM_PUBLIC void
+PS_init()
+{
+    unsigned int xmin_t = 0, ymin_t = 0, xmax_t = 0, ymax_t = 0;
+
+    switch (ps_params->psformat) {
+    case PSTERM_EPS:
+       if (ps_explicit_size) {
+           term->xmax = eps_explicit_x;
+           term->ymax = eps_explicit_y;
+       } else {
+           term->xmax = PS_XMAX;
+           if (ps_params->oldstyle)
+               term->ymax = PS_YMAX_OLDSTYLE;
+           else
+               term->ymax = PS_YMAX;
+       }
+       xmin_t = term->xmax * xoffset / (2*PS_SC);
+       xmax_t = term->xmax * (xsize + xoffset) / (2*PS_SC);
+       ymin_t = term->ymax * yoffset / (2*PS_SC);
+       ymax_t = term->ymax * (ysize + yoffset) / (2*PS_SC);
+       break;
+    case PSTERM_PORTRAIT:
+       if (!ps_explicit_size) {
+           term->xmax = PS_YMAX;
+           term->ymax = PS_XMAX;
+       }
+       xmin_t = term->xmax * xoffset / PS_SC;
+       xmax_t = term->xmax * (xsize + xoffset) / PS_SC;
+       ymin_t = term->ymax * yoffset / PS_SC;
+       ymax_t = term->ymax * (ysize + yoffset) / PS_SC;
+       break;
+    case PSTERM_LANDSCAPE:
+       if (!ps_explicit_size) {
+           term->xmax = PS_XMAX;
+           term->ymax = PS_YMAX;
+       }
+       ymin_t = term->xmax * xoffset / PS_SC;
+       ymax_t = term->xmax * (xsize+xoffset) / PS_SC;
+       xmin_t = term->ymax * (1-ysize-yoffset) / PS_SC;
+       xmax_t = term->ymax * (1-yoffset) / PS_SC;
+       break;
+    default:
+       int_error(NO_CARET, "invalid postscript format used");
+    }
+
+    /* for enhanced postscript, copy ps_params->font to ps_enh_font
+     * does no harm for non-enhanced
+     */
+    strcpy(ps_enh_font, ps_params->font);
+    ps_enh_fontsize = ps_fontsize;
+
+    switch (ps_params->terminal) {
+    case PSTERM_POSTSCRIPT:
+       gppsfile = gpoutfile;
+       break;
+    default:
+#ifdef PSLATEX_DRIVER
+       PSTEX_reopen_output();
+       break;
+    case PSTERM_EPSLATEX:
+       EPSLATEX_reopen_output();
+#endif
+       break;
+    }
+
+    PS_common_init(ps_params->terminal == PSTERM_POSTSCRIPT,
+                  ps_params->xoff, ps_params->yoff,
+                  xmin_t, ymin_t, xmax_t, ymax_t,
+                  (term->put_text == ENHPS_put_text) ? ENHPS_header : NULL);
+    
+    /* Keep track of whether we have written the enhanced text dictionary yet */
+    ENHPS_initialized = (term->put_text == ENHPS_put_text) ? 2 : 1;
+}
+
+
+TERM_PUBLIC void
+PS_graphics()
+{
+    static char GPFAR psg1[] = "0 setgray\nnewpath\n";
+    struct termentry *t = term;
+    ps_page++;
+    if (ps_params->psformat != PSTERM_EPS)
+       fprintf(gppsfile,"%%%%Page: %d %d\n",ps_page,ps_page);
+
+    /* If we are about to use enhanced text mode for the first time in a plot that */
+    /* was initialized previously without it, we need to write out the macros now */
+    if (term->put_text == ENHPS_put_text && ENHPS_initialized == 1) {
+       const char **dict = ENHPS_header;
+       while (*dict)
+           fputs(*(dict++), gppsfile);
+       fprintf(stderr,"Writing out PostScript macros for enhanced text mode\n");
+       ENHPS_initialized = 2;
+    }
+
+    fprintf(gppsfile,"\
+gnudict begin\ngsave\n\
+%d %d translate\n\
+%.3f %.3f scale\n",
+           ps_common_xoff, ps_common_yoff,
+           (ps_params->psformat == PSTERM_EPS ? 0.5 : 1.0)/PS_SC,
+           (ps_params->psformat == PSTERM_EPS ? 0.5 : 1.0)/PS_SC);
+    if (ps_params->psformat == PSTERM_LANDSCAPE)
+       fprintf(gppsfile,"90 rotate\n0 %d translate\n", -(int)(term->ymax));
+    fprintf(gppsfile, psg1);
+    if (ps_common_uses_fonts)
+       fprintf(gppsfile, "(%s) findfont %d scalefont setfont\n",
+               ps_params->font, (t->v_char));
+    ps_path_count = 0;
+    PS_relative_ok = FALSE;
+    PS_pen_x = PS_pen_y = -4000;
+    PS_taken = 0;
+    PS_linewidth_last = PS_linetype_last =  LT_UNDEFINED;
+}
+
+
+TERM_PUBLIC void
+PS_text()
+{
+    ps_path_count = 0;
+    fputs("stroke\ngrestore\nend\nshowpage\n", gppsfile);
+    /* fprintf(stderr,"taken %d times\n",PS_taken); */
+    /* informational:  tells how many times it was "cheaper"
+     * to do a relative moveto or lineto rather than an
+     * absolute one */
+}
+
+
+TERM_PUBLIC void
+PS_reset()
+{
+    fputs("%%Trailer\n", gppsfile);
+
+    /* I think the following commands should be executed
+       `if (ps_common_uses_fonts)`. So I changed the next line.
+       Please see "PS_RememberFont", too.                       */  /* JFi */
+
+    /* if (!ps_common_uses_fonts) {  */                             /* JFi */
+    if (ps_common_uses_fonts) {
+       fputs("%%DocumentFonts: ", gppsfile);
+       while (PS_DocFonts) {
+           struct PS_FontName *fnp;
+           fnp = PS_DocFonts->next;
+           fprintf(gppsfile, "%s%s", PS_DocFonts->name, fnp ? " " : "\n");
+           free(PS_DocFonts->name);
+           free(PS_DocFonts);
+           PS_DocFonts = fnp;
+       }
+    }
+    if (ps_params->psformat != PSTERM_EPS)
+       fprintf(gppsfile,"%%%%Pages: %d\n",ps_page);
+}
+
+TERM_PUBLIC void
+PS_linetype(int linetype)
+{
+    if ((ps_params->terminal == PSTERM_EPSLATEX) && ps_params->oldstyle)
+       linetype = (linetype % 4) + 3;
+    else
+       linetype = (linetype % 9) + 3;
+    if (linetype < 0)  /* LT_NODRAW, LT_BACKGROUND, LT_UNDEFINED */
+       linetype = 0;
+
+    if (PS_linetype_last == linetype) return;
+
+    PS_relative_ok = FALSE;
+    PS_FLUSH_PATH;
+
+    PS_linetype_last = linetype;
+    fprintf(gppsfile, "LT%c\n", "wba012345678"[linetype]);
+    ps_path_count = 0;
+}
+
+
+TERM_PUBLIC void
+PS_linewidth (double linewidth)
+{
+    /* HBB NEW 20031219: don't do anything if nothing changed */
+    if (ps_path_count != 0 && PS_linewidth_last == linewidth)
+       return;
+    PS_linewidth_last = linewidth;
+    PS_linetype_last = -1;     /* disable cache for next linetype change */
+
+    PS_FLUSH_PATH;
+    fprintf(gppsfile, "%.3f UL\n", linewidth);
+
+    /*
+       Documentation of the 'change linewidth' strategy of the postscript terminal:
+
+       1. define a new postscript variable with a default value:
+       /userlinewidth gnulinewidth def
+
+       2. define a new postscript command to change the contents of that variable:
+       /UL { gnulinewidth mul /userlinewidth exch def } def
+       usage:  multiplication_factor UL
+
+       3. modify the already known postscript command /PL for the plot lines:
+       /PL { stroke userlinewidth setlinewidth } def
+
+       4. issue the new command before every change of the plot linestyle:
+       example:
+       4.0 UL
+       LT0
+       result:
+       Linetype 0 is drawn four times as thick as defined by the contents
+       of the postscript variable 'gnulinewidth'.
+    */
+}
+
+
+TERM_PUBLIC void
+PS_pointsize (double ptsize)
+{
+    fprintf(gppsfile, "%.3f UP\n", ptsize);
+
+/*
+ *  Documentation of the 'change pointsize' strategy of the postscript
+ * terminal:
+ *
+ * 1. define two new postscript variables to hold the overall pointsize:
+ *    /hpt_  and  /vpt_
+ *
+ * 2. define a new postscript command to use the contents of these variables:
+ *    /UP { cf. definition above } def
+ *    usage:  multiplication_factor UP
+ *
+ * [3.] [doesn't exist, skip to next number]
+ *
+ * 4. issue the new command whereever you change the symbols (and linetype):
+ *    example:
+ *        2.5 UP
+ *        4.0 UL  % optionally change linewidth, too
+ *        LT0
+ *    result:
+ *        Next symbols will be drawn 2.5 times as big as defined by the
+ *        GNUPLOT `set pointsize` command (= overall pointsize).
+ */
+}
+
+
+TERM_PUBLIC void
+PS_move(unsigned int x, unsigned int y)
+{
+    /* Make this semi-dynamic and independent of architecture */
+    char abso[5+2*INT_STR_LEN], rel[5+2*INT_STR_LEN];
+    int dx = x - PS_pen_x;
+    int dy = y - PS_pen_y;
+
+    /* can't cancel all null moves--need a move after stroke'ing */
+    if (dx==0 && dy==0 && PS_relative_ok)
+       return;
+
+    sprintf(abso, "%d %d M\n", x, y);
+    sprintf(rel, "%d %d R\n", dx, dy);
+
+    if (PS_newpath) {
+       fprintf(gppsfile, "%d %d N\n", x, y);
+       PS_newpath = FALSE;
+    } else
+    if (strlen(rel) < strlen(abso) && PS_relative_ok) {
+       fputs(rel, gppsfile);
+       PS_taken++;
+    } else
+       fputs(abso, gppsfile);
+    PS_relative_ok = TRUE;
+    ps_path_count += 1;
+
+    PS_pen_x = x;
+    PS_pen_y = y;
+}
+
+TERM_PUBLIC void
+PS_vector(unsigned int x, unsigned int y)
+{
+    char abso[5+2*INT_STR_LEN], rel[5+2*INT_STR_LEN];
+    int dx = x - PS_pen_x;
+    int dy = y - PS_pen_y;
+
+    if (dx==0 && dy==0)
+       return;
+
+    sprintf(abso, "%d %d L\n", x, y);
+    sprintf(rel, "%d %d V\n", dx, dy);
+
+    /* The following PS_move() is executed only when the limit of ps_path_count
+     * has been reached below: then PS_FLUSH_PATH has been called which has not
+     * moved to currentpoint after the stroke. */
+    if (!PS_relative_ok)
+       PS_move(PS_pen_x, PS_pen_y);
+
+    if (strlen(rel) < strlen(abso)) {
+       fputs(rel, gppsfile);
+       PS_taken++;             /* only used for debug info */
+       ps_path_count += 1;
+    } else {
+       fputs(abso, gppsfile);
+       ps_path_count = 1;  /* If we set it to zero, it may never get flushed */
+    }
+    /* Ghostscript has a "pile-up of rounding errors" bug: a sequence of many
+     * rmove's or rlineto's does not yield the same line as move's or lineto's.
+     * Therefore, we periodically force an update of the absolute position.
+     * There was a case when 400 rlineto's were too much, so let's go a little
+     * bit higher than the default function sampling rate in gnuplot.
+     * This runs into a second ghostscript bug, that mixing relative and absolute
+     * lineto with no intervening 'stroke' is ridiculously slow to render.
+     * So we stroke the partial line, update the position in absolute terms,
+     * then continue.  This whole section can go away if ghostscript/gv is fixed.
+     */
+#define MAX_REL_PATHLEN 105
+    if (ps_path_count >= MAX_REL_PATHLEN) {
+       fprintf(gppsfile, "stroke %d %d M\n", x, y);
+       ps_path_count = 1;
+    }
+
+    PS_relative_ok = TRUE;
+    PS_pen_x = x;
+    PS_pen_y = y;
+}
+
+
+TERM_PUBLIC void
+PS_put_text(unsigned int x, unsigned int y, const char *str)
+{
+    char ch;
+
+    if (!str && !strlen(str))
+       return;
+    PS_move(x,y);
+    if (ps_ang != 0)
+       fprintf(gppsfile,"currentpoint gsave translate %d rotate 0 0 M\n",
+               ps_ang);
+    putc('(',gppsfile);
+    ch = *str++;
+    while(ch!='\0') {
+       if ((ch=='(') || (ch==')') || (ch=='\\'))
+           putc('\\', gppsfile);
+       putc(ch, gppsfile);
+       ch = *str++;
+    }
+
+    switch(ps_justify) {
+    case LEFT :
+       fputs(") Lshow\n", gppsfile);
+       break;
+    case CENTRE :
+       fputs(") Cshow\n", gppsfile);
+       break;
+    case RIGHT :
+       fputs(") Rshow\n", gppsfile);
+       break;
+    }
+    if (ps_ang != 0)
+       fputs("grestore\n", gppsfile);
+    ps_path_count = 0;
+    PS_relative_ok = FALSE;
+}
+
+
+TERM_PUBLIC int
+PS_text_angle(int ang)
+{
+    ps_ang = ang;
+    return TRUE;
+}
+
+
+TERM_PUBLIC int
+PS_justify_text(enum JUSTIFY mode)
+{
+    ps_justify = mode;
+    return TRUE;
+}
+
+
+TERM_PUBLIC int
+PS_set_font(const char *font)
+{
+    char *name;
+    unsigned int  i;
+    float size;
+    size_t sep;
+
+    if (!font || !(*font))
+       font = PS_default_font;
+    sep = strcspn(font,",");
+    name = gp_strdup(font);
+    name[sep] = NUL;
+    for (i=0; i<sep; i++)
+       if (name[i] == ' ') name[i] = '-';
+    size = ps_fontsize;
+    if (font[sep] == ',')
+       sscanf (&(font[sep+1]),"%f",&size);
+
+    /* If TeX is doing the font handling, we don't need to */
+    /* write anything into the postscript stream */
+    if (ps_params->terminal == PSTERM_POSTSCRIPT) {
+       PS_RememberFont(name,1);
+       fprintf(gppsfile, "/%s findfont %g scalefont setfont\n",
+               name, size*PS_SC);
+    }
+    free(name);
+
+    term->v_char = (unsigned int)(size*PS_SC);
+    term->h_char = (unsigned int)(size*PS_SC*6/10);
+    return TRUE;
+}
+
+
+/* postscript point routines */
+
+
+TERM_PUBLIC void
+PS_point(unsigned int x, unsigned int y, int number)
+{
+    static const char GPFAR * GPFAR pointFNS[] = {
+       "Pnt",  "Pls",   "Crs",    "Star",
+       "Box",  "BoxF",  "Circle", "CircleF",
+       "TriU", "TriUF", "TriD",   "TriDF",
+       "Dia",  "DiaF",  "Pent",   "PentF",
+       "C0",   "C1",    "C2",     "C3",
+       "C4",   "C5",    "C6",     "C7",
+       "C8",   "C9",    "C10",    "C11",
+       "C12",  "C13",   "C14",    "C15",
+       "S0",   "S1",    "S2",     "S3",
+       "S4",   "S5",    "S6",     "S7",
+       "S8",   "S9",    "S10",    "S11",
+       "S12",  "S13",   "S14",    "S15",
+       "D0",   "D1",    "D2",     "D3",
+       "D4",   "D5",    "D6",     "D7",
+       "D8",   "D9",    "D10",    "D11",
+       "D12",  "D13",   "D14",    "D15",
+       "BoxE", "CircE", "TriUE",  "TriDE",
+       "DiaE", "PentE", "BoxW",   "CircW",
+       "TriUW","TriDW", "DiaW",   "PentW"
+    };
+    static const char GPFAR * GPFAR pointFNS_OldEPSL[] = {
+       "Pnt",  "Dia",   "Circle", "Pls",
+       "Crs",  "Box",   "DiaF",   "CircleF",
+       "BoxF"
+    };
+    if ((ps_params->terminal == PSTERM_EPSLATEX) && ps_params->oldstyle) {
+       if (number < 0)
+           number = -1;                /* negative types are all 'dot' */
+       else
+           number %= sizeof(pointFNS_OldEPSL)/sizeof(pointFNS_OldEPSL[0]) -1;
+       fprintf(gppsfile, "%d %d %s\n", x, y, pointFNS_OldEPSL[number+1]);
+    } else {
+       if (number < 0)
+           number = -1;                /* negative types are all 'dot' */
+       else
+           number %= sizeof(pointFNS)/sizeof(pointFNS[0]) -1;
+       fprintf(gppsfile, "%d %d %s\n", x, y, pointFNS[number+1]);
+    }
+
+    PS_relative_ok = FALSE;
+    ps_path_count = 0;
+    PS_linewidth_last = PS_linetype_last =  -1; /* force next linetype change */
+}
+
+TERM_PUBLIC void
+PS_fillbox(
+    int style,
+    unsigned int x1, unsigned int y1,
+    unsigned int width, unsigned int height)
+{
+    double filldens;
+    int pattern;
+
+    PS_FLUSH_PATH;
+
+    switch(style & 0xf) {
+
+    case FS_SOLID:
+       /* style == 1 --> fill with intensity according to filldensity */
+        filldens = (style >> 4) / 100.0;
+        if(filldens < 0.0)
+           filldens = 0.0;
+        if(filldens > 1.0)
+           filldens = 1.0;
+        fprintf(gppsfile, "%.3f %d %d %d %d BoxColFill\n",
+               filldens, x1,y1, width,height);
+        break;
+
+    case FS_PATTERN:
+       /* style == 2 --> fill with pattern according to fillpattern */
+       /* the upper 3 nibbles of 'style' contain pattern number */
+       pattern = (style >> 4) % 8;
+       switch (pattern) {
+
+       default:
+       case 0:
+               fprintf(gppsfile, "%d %d %d %d BoxFill\n",
+                       x1, y1, width, height);
+               break;
+       case 1:
+               fprintf(gppsfile, "%d %d %d %d %d %d 1 PatternFill\n",
+                       x1, y1, width, height, 80, -45);
+               break;
+       case 2:
+               fprintf(gppsfile, "%d %d %d %d %d %d 2 PatternFill\n",
+                       x1, y1, width, height, 40,  45);
+               break;
+       case 3:
+               fprintf(gppsfile, "1 %d %d %d %d BoxColFill\n",
+                       x1, y1, width, height);
+               break;
+       case 4:
+               fprintf(gppsfile, "%d %d %d %d %d %d 0 PatternFill\n",
+                       x1, y1, width, height, 80,  45);
+               break;
+       case 5:
+               fprintf(gppsfile, "%d %d %d %d %d %d 0 PatternFill\n",
+                       x1, y1, width, height, 80, -45);
+               break;
+       case 6:
+               fprintf(gppsfile, "%d %d %d %d %d %d 0 PatternFill\n",
+                       x1, y1, width, height, 40,  30);
+               break;
+       case 7:
+               fprintf(gppsfile, "%d %d %d %d %d %d 0 PatternFill\n",
+                       x1, y1, width, height, 40, -30);
+               break;
+       }
+        break; /* end of pattern filling part */
+
+    default: /* style == 0 or unknown --> fill with background color */
+        fprintf(gppsfile, "%d %d %d %d BoxFill\n", x1, y1, width, height);
+    }
+
+    PS_relative_ok = FALSE;
+    PS_linewidth_last = PS_linetype_last =  -1;
+}
+
+
+/* ENHPOST */
+
+static TBOOLEAN ENHps_opened_string;  /* try to cut out empty ()'s */
+
+/*
+ * close a postscript string if it has been opened
+ */
+TERM_PUBLIC void
+ENHPS_FLUSH()
+{
+    if (ENHps_opened_string) {
+       fputs(")]\n", gppsfile);
+       ENHps_opened_string = FALSE;
+    }
+}
+
+/*
+ * open a postscript string
+ */
+TERM_PUBLIC void
+ENHPS_OPEN(
+    char *fontname,
+    double fontsize, double base,
+    TBOOLEAN widthflag, TBOOLEAN showflag,
+    int overprint)
+{
+    /* overprint 3 means save current position; 4 means restore saved position */
+    /* EAM FIXME - I couldn't figure out how to use less than the 7 parameters */
+    /* that the normal case macro wants. Somebody more familiar with PostScript*/
+    /* than I am please clean it up!                                           */
+    if (overprint == 3) {
+       fputs("XYsave\n", gppsfile);
+       return;
+    } else if (overprint == 4) {
+       fputs("XYrestore\n", gppsfile);
+       return;
+    }
+
+       if (!ENHps_opened_string) {
+           fprintf(gppsfile, "[(%s) %.1f %.1f %s %s %d (",
+                   fontname, fontsize, base,
+                   widthflag ? "true" : "false",
+                   showflag ? "true" : "false",
+                   overprint);
+           ENHps_opened_string = TRUE;
+       }
+}
+
+/*
+ * write one or more characters from inside enhanced text processing
+ */
+TERM_PUBLIC void
+ENHPS_WRITEC(int c)
+{
+    fputc(c, gppsfile);
+}
+
+/* a set-font routine for enhanced post : simply copies
+ * the font into a global, or restores the globals
+ * to the ps_params->font default
+ */
+
+TERM_PUBLIC int
+ENHPS_set_font(const char *font)
+{
+    if (ignore_enhanced_text)
+       return PS_set_font(font);
+
+    if (*font) {
+       size_t sep = strcspn(font,",");
+       if (sep > 0) {
+           strncpy(ps_enh_font,font,sep);
+           ps_enh_font[sep] = NUL;
+           PS_RememberFont(ps_enh_font, 1);
+       }
+       ps_enh_fontsize = ps_fontsize;
+       sscanf (font+sep+1,"%f",&ps_enh_fontsize);
+    } else {
+       /* return to defaults */
+       strcpy(ps_enh_font, ps_params->font);
+       ps_enh_fontsize = ps_fontsize;
+    }
+    term->v_char = (unsigned int)(ps_enh_fontsize*PS_SC);
+    term->h_char = (unsigned int)(ps_enh_fontsize*PS_SC*6/10);
+
+    return TRUE;
+}
+
+TERM_PUBLIC void
+ENHPS_put_text(unsigned int x, unsigned int y, const char *str)
+{
+    if (ignore_enhanced_text) {
+       PS_put_text(x,y,str);
+       return;
+    }
+
+    /* flush any pending graphics (all the XShow routines do this...) */
+
+    if (!strlen(str))
+       return;
+
+    PS_FLUSH_PATH;
+
+    /* if there are no magic characters, we should just be able
+     * punt the string to PS_put_text(), which will give shorter
+     * ps output [eg tics and stuff rarely need extra processing],
+     * but we need to make sure that the current font is the
+     * default one before we can do that. {ie I tried it and it
+     * used the wrong font !}
+     * if (!strpbrk(str, "{}^_@&~"))
+     * {
+     *   - do something to ensure default font is selected
+     *   PS_put_text(x,y,str);
+     *   return;
+     * }
+     */
+
+    PS_move(x,y);
+
+    if (ps_ang != 0)
+       fprintf(gppsfile,"currentpoint gsave translate %d rotate 0 0 moveto\n",
+               ps_ang);
+
+    fputs("[ ", gppsfile);
+
+    /* set up the global variables needed by enhanced_recursion() */
+    enhanced_max_height = -1000;
+    enhanced_min_height = 1000;
+    enhanced_fontscale = PS_SC;
+    strncpy(enhanced_escape_format,"\\%o",sizeof(enhanced_escape_format));
+
+    ENHps_opened_string = FALSE;
+
+    /* Set the recursion going. We say to keep going until a
+     * closing brace, but we don't really expect to find one.
+     * If the return value is not the nul-terminator of the
+     * string, that can only mean that we did find an unmatched
+     * closing brace in the string. We increment past it (else
+     * we get stuck in an infinite loop) and try again.
+     *
+     * ps_enh_font and ps_enh_fontsize are either set to the
+     * the defaults set on option line, or have been set to
+     * "font,size". That is to say, ps_params->font is used only
+     * at startup and by ENHPS_set_font
+     */
+    while (*(str = enhanced_recursion((char *)str, TRUE, ps_enh_font,
+                (double)(ps_enh_fontsize*PS_SC), 0.0, TRUE, TRUE, 0))) {
+       ENHPS_FLUSH();
+
+       /* I think we can only get here if *str == '}' */
+       enh_err_check(str);
+
+       if (!*++str)
+           break; /* end of string */
+
+       /* else carry on and process the rest of the string */
+    }
+
+    enhanced_max_height += enhanced_min_height;
+
+    fprintf(gppsfile, "] %.1f ", -enhanced_max_height/3);
+
+    switch(ps_justify) {
+    case LEFT :
+       fputs("MLshow\n", gppsfile);
+       break;
+    case CENTRE :
+       fputs("MCshow\n", gppsfile);
+       break;
+    case RIGHT :
+       fputs("MRshow\n", gppsfile);
+       break;
+    }
+
+    if (ps_ang != 0)
+       fputs("grestore\n", gppsfile);
+    ps_path_count = 0;
+    PS_relative_ok = FALSE;
+}
+
+static void
+make_palette_formulae()
+{
+#define R sm_palette.formulaR
+#define G sm_palette.formulaG
+#define B sm_palette.formulaB
+/* print the definition of R,G,B formulae */
+  fputs("/InterpolatedColor false def\n", gppsfile);
+if (sm_palette.ps_allcF == 0) { /* print only those 3 used formulae */
+    fprintf(gppsfile, "/cF%i {%s} bind def\t%% %s\n",
+            abs(R), ps_math_color_formulae[ 2*abs(R) ],
+            ps_math_color_formulae[ 2*abs(R)+1 ]);
+    if (abs(G) != abs(R))
+      fprintf(gppsfile, "/cF%i {%s} bind def\t%% %s\n",
+              abs(G), ps_math_color_formulae[ 2*abs(G) ],
+              ps_math_color_formulae[ 2*abs(G)+1 ]);
+    if ((abs(B) != abs(R)) && (abs(B) != abs(G)))
+      fprintf(gppsfile, "/cF%i {%s} bind def\t%% %s\n",
+              abs(B), ps_math_color_formulae[ 2*abs(B) ],
+              ps_math_color_formulae[ 2*abs(B)+1 ]);
+    }
+  else { /* all color formulae are written into the output PostScript file */
+    int i = 0;
+    while (*(ps_math_color_formulae[2*i])) {
+      fprintf(gppsfile, "/cF%i {%s} bind def\t%% %s\n",
+              i, ps_math_color_formulae[ 2*i ],
+              ps_math_color_formulae[ 2*i+1 ]);
+      i++;
+      }
+    }
+#undef R
+#undef G
+#undef B
+}
+
+
+
+static void
+make_interpolation_code()
+{
+    static const char *header[] = {
+       "/grayindex {/gidx 0 def\n",
+       "  {GrayA gidx get grayv ge {exit} if /gidx gidx 1 add def} loop} def\n",
+       "/dgdx {grayv GrayA gidx get sub GrayA gidx 1 sub get\n",
+       "  GrayA gidx get sub div} def \n",
+       "/redvalue {RedA gidx get RedA gidx 1 sub get\n",
+       "  RedA gidx get sub dgdxval mul add} def\n",
+       "/greenvalue {GreenA gidx get GreenA gidx 1 sub get\n",
+       "  GreenA gidx get sub dgdxval mul add} def\n",
+       "/bluevalue {BlueA gidx get BlueA gidx 1 sub get\n",
+       "  BlueA gidx get sub dgdxval mul add} def\n",
+       "/interpolate {\n",
+       "  grayindex grayv GrayA gidx get sub abs 1e-5 le\n",
+       "    {RedA gidx get GreenA gidx get BlueA gidx get}\n",
+       "    {/dgdxval dgdx def redvalue greenvalue bluevalue} ifelse} def\n",
+       NULL,
+    };
+    int i;
+
+    for(i=0; header[i]!=NULL; ++i) {
+       fputs(header[i], gppsfile);
+    }
+}
+
+
+static void
+make_color_model_code()
+{
+    /* Postscript version of the color space transformations in getcolor.c */
+    static const char *header[] = {
+       "/HSV2RGB {",
+       "  exch dup 0.0 eq {pop exch pop dup dup} % achromatic gray\n",
+       "  { /HSVs exch def /HSVv exch def 6.0 mul dup floor dup 3 1 roll sub\n ",
+       "    /HSVf exch def /HSVi exch cvi def /HSVp HSVv 1.0 HSVs sub mul def\n",
+       "        /HSVq HSVv 1.0 HSVs HSVf mul sub mul def \n",
+       "        /HSVt HSVv 1.0 HSVs 1.0 HSVf sub mul sub mul def\n",
+       "        /HSVi HSVi 6 mod def 0 HSVi eq {HSVv HSVt HSVp}\n",
+       "        {1 HSVi eq {HSVq HSVv HSVp}{2 HSVi eq {HSVp HSVv HSVt}\n",
+       "        {3 HSVi eq {HSVp HSVq HSVv}{4 HSVi eq {HSVt HSVp HSVv}\n",
+       "        {HSVv HSVp HSVq} ifelse} ifelse} ifelse} ifelse} ifelse\n",
+       "  } ifelse} def\n",
+       "/Constrain {\n",
+       "  dup 0 lt {0 exch pop}{dup 1 gt {1 exch pop} if} ifelse} def\n",
+       "/YIQ2RGB {\n",
+       "  3 copy -1.702 mul exch -1.105 mul add add Constrain 4 1 roll\n",
+       "  3 copy -0.647 mul exch -0.272 mul add add Constrain 5 1 roll\n",
+       "  0.621 mul exch -0.956 mul add add Constrain 3 1 roll } def\n",
+       "/CMY2RGB {",
+       "  1 exch sub exch 1 exch sub 3 2 roll 1 exch sub 3 1 roll exch } def\n",
+       "/XYZ2RGB {",
+       "  3 copy -0.9017 mul exch -0.1187 mul add exch 0.0585 mul exch add\n",
+       "  Constrain 4 1 roll 3 copy -0.0279 mul exch 1.999 mul add exch\n",
+       "  -0.9844 mul add Constrain 5 1 roll -0.2891 mul exch -0.5338 mul add\n",
+       "  exch 1.91 mul exch add Constrain 3 1 roll} def\n",
+       "/SelectSpace {ColorSpace (HSV) eq {HSV2RGB}{ColorSpace (XYZ) eq {\n",
+       "  XYZ2RGB}{ColorSpace (CMY) eq {CMY2RGB}{ColorSpace (YIQ) eq {YIQ2RGB}\n",
+       "  if} ifelse} ifelse} ifelse} def\n",
+        NULL,
+    };
+    int i;
+
+    for(i=0; header[i]!=NULL; ++i) {
+        fputs(header[i], gppsfile);
+    }
+}
+
+
+static char
+*save_space(double gray)
+{
+    /* printing the gray with 4 digits and without the leading 0
+     * ... saving space */
+    static char s[40];
+
+    gray = 0.0001*(int)(gray*10000+0.5); /* round it to 4 digits */
+    sprintf(s, "%.4g", gray);
+    if (s[0] == '0' && s[1] == '.')
+        return &(s[1]);  /* strip leading 0 */
+    else
+        return s;
+}
+
+
+static void
+write_color_space(t_sm_palette *palette)
+{
+    /* write something like
+     *   /ColorSpace (HSV) def
+     * depending on the selected cmodel in palette */
+    fputs("/ColorSpace ", gppsfile);
+    switch(palette->cmodel) {
+    case C_MODEL_RGB:
+       fputs("(RGB)", gppsfile);
+       break;
+    case C_MODEL_HSV:
+       fputs("(HSV)", gppsfile);
+       break;
+    case C_MODEL_CMY:
+       fputs("(CMY)", gppsfile);
+       break;
+    case C_MODEL_YIQ:
+       fputs("(YIQ)", gppsfile);
+       break;
+    case C_MODEL_XYZ:
+       fputs("(XYZ)", gppsfile);
+       break;
+    default:
+       fprintf(stderr,"%s:%d ooops: Unkown color model '%c'. Will be RGB\n",
+               __FILE__, __LINE__, (char)(palette->cmodel));
+       fputs("(RGB)", gppsfile);
+       break;
+    }
+    fputs(" def\n", gppsfile);
+}
+
+
+static void
+write_component_array(const char *text, gradient_struct *grad,
+                     int cnt, int offset)
+{
+    /*  write someting like
+     *     /RedA [ 0 .1 .2 .3 .35 .3 .2 .1 0 0 0 ] def
+     *  nicely formated to gppsfile
+     */
+    int i=0, len=0;
+    char *val;
+
+    fprintf(gppsfile, "/%s [", text);
+    len = strlen(text) + 4;
+    for(i=0; i<cnt; ++i) {
+        char *ref = (char*)(&(grad[i]));
+
+       ref += offset;
+        val = save_space(*((double*) (ref)));
+       len += strlen(val) + 1;
+       if(len > 77) {
+           fputs("\n  ",gppsfile);
+           len = strlen(val) + 3;
+       }
+       fprintf(gppsfile, "%s ", val);
+    }
+    fputs("] def\n", gppsfile);
+}
+
+
+static void
+write_gradient_definition(gradient_struct *gradient, int cnt)
+{
+    /* some strange pointer acrobatic here, but it seems to work... */
+    char *ref = (char*) (gradient);
+    int p = (char*) (&(gradient[0].pos)) - ref;
+    int r = (char*) (&(gradient[0].col.r)) - ref;
+    int g = (char*) (&(gradient[0].col.g)) - ref;
+    int b = (char*) (&(gradient[0].col.b)) - ref;
+
+    write_component_array("GrayA", gradient, cnt, p);
+    write_component_array("RedA", gradient, cnt, r);
+    write_component_array("GreenA", gradient, cnt, g);
+    write_component_array("BlueA", gradient, cnt, b);
+}
+
+
+static void
+PS_make_header(t_sm_palette *palette)
+{
+    /* write header for smooth colors */
+    fputs("gsave % colour palette begin\n", gppsfile);
+    fprintf(gppsfile, "/maxcolors %i def\n", sm_palette.use_maxcolors);
+    make_color_model_code();
+
+    switch(sm_palette.colorMode) {
+    case SMPAL_COLOR_MODE_GRAY:
+       fputs("/InterpolatedColor false def\n", gppsfile);
+       break;  /* nothing to do for gray */
+    case SMPAL_COLOR_MODE_RGB:
+       make_palette_formulae();
+       break;
+    case SMPAL_COLOR_MODE_FUNCTIONS: {
+       int cnt=0;
+       gradient_struct *gradient;
+
+       fputs("/InterpolatedColor true def\n", gppsfile);
+       make_interpolation_code();
+       gradient = approximate_palette(palette, ps_params->palfunc_samples,
+                                      ps_params->palfunc_deviation, &cnt);
+       write_gradient_definition(gradient, cnt);
+       free(gradient);
+       break;
+    }
+    case SMPAL_COLOR_MODE_GRADIENT:
+       fputs("/InterpolatedColor true def\n", gppsfile);
+       make_interpolation_code();
+       write_gradient_definition(palette->gradient, palette->gradient_num);
+       break;
+    default:
+       fprintf(stderr, "%s:%d ooops: Unknown color mode '%c'\n",
+                __FILE__, __LINE__, (char)(sm_palette.colorMode));
+    }
+    fputs("/pm3dround {maxcolors 0 gt {dup 1 ge\n", gppsfile);
+    fputs("\t{pop 1} {maxcolors mul floor maxcolors 1 sub div} ifelse} if} def\n",
+         gppsfile);
+    fprintf(gppsfile, "/pm3dGamma 1.0 %g div def\n", sm_palette.gamma);
+    write_color_space(palette);
+
+/* Now print something like
+   /g {dup cF7 exch dup cF5 exch cF15 setrgbcolor} bind def
+*/
+#define R sm_palette.formulaR
+#define G sm_palette.formulaG
+#define B sm_palette.formulaB
+
+/* 18.1.2009 Since the beginning of pm3d, the Color definition switched
+   between gray and colour map. This led to ambiguities for custom colour
+   palettes if they contain grays only. Thus let postscript choose always
+   always colour palette for interpolated colours ('set palette defined',
+   'set palette file') and colour/gray according to Color otherwise
+   ('set palette gray', 'set palette rgb').
+*/
+#if 0
+    fprintf(gppsfile, "Color %s and { %% COLOUR vs. GRAY map\n",
+           (sm_palette.colorMode!=SMPAL_COLOR_MODE_GRAY) ? "true":"false");
+#else
+    if (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY)
+       fputs("false { % COLOUR vs. GRAY map\n", gppsfile);
+    else
+       fputs("Color InterpolatedColor or { % COLOUR vs. GRAY map\n", gppsfile);
+#endif
+
+    fputs("  InterpolatedColor { %% Interpolation vs. RGB-Formula\n",
+         gppsfile);
+    fputs("    /g {stroke pm3dround /grayv exch def interpolate\n", gppsfile);
+    fputs("        SelectSpace setrgbcolor} bind def\n", gppsfile);
+    fputs("  }{\n", gppsfile);
+    fputs("  /g {stroke pm3dround dup ", gppsfile);
+    if (R < 0)
+       fputs("1 exch sub ", gppsfile); /* negate */
+    fprintf(gppsfile,"cF%i Constrain exch dup ", abs(R));
+    if (G < 0)
+       fputs("1 exch sub ", gppsfile); /* negate */
+    fprintf(gppsfile,"cF%i Constrain exch ", abs(G));
+    if (R<0 || G<0 || B<0)
+       fputs("\n\t", gppsfile);
+    if (B < 0)
+       fputs("1 exch sub ", gppsfile); /* negate */
+    fprintf(gppsfile,"cF%i Constrain ", abs(B));
+    fputs("\n       SelectSpace setrgbcolor} bind def\n", gppsfile);
+    fputs("  } ifelse\n", gppsfile);
+    fputs("}{\n", gppsfile);
+    fputs("  /g {stroke pm3dround pm3dGamma exp setgray} bind def\n", gppsfile);
+    fputs("} ifelse\n", gppsfile);
+#undef R
+#undef G
+#undef B
+}
+
+
+TERM_PUBLIC int PS_make_palette (t_sm_palette *palette)
+{
+    if (palette == NULL) {
+        return 0;  /* postscript can do continuous colors */
+    }
+
+    PS_make_header(palette);
+    return 0;
+}
+
+
+TERM_PUBLIC void PS_set_color (t_colorspec *colorspec)
+{
+    double gray;
+
+    PS_linetype_last = -1;  /* Force next call to linetype to be honored */
+
+    if (colorspec->type == TC_LT) {
+       int linetype = colorspec->lt;
+       PS_FLUSH_PATH;
+       if ((ps_params->terminal == PSTERM_EPSLATEX) && ps_params->oldstyle)
+           linetype = (linetype % 4) + 3;
+       else
+           linetype = (linetype % 9) + 3;
+       if (linetype < 0)       /* LT_NODRAW, LT_BACKGROUND, LT_UNDEFINED */
+           linetype = 0;
+       fprintf(gppsfile, "LC%1c setrgbcolor\n","wba012345678"[linetype]);
+    } else if (colorspec->type == TC_RGB) {
+       double r = (double)((colorspec->lt >> 16 ) & 255) / 255.;
+       double g = (double)((colorspec->lt >> 8 ) & 255) / 255.;
+       double b = (double)(colorspec->lt & 255) / 255.;
+       PS_FLUSH_PATH;
+       fprintf(gppsfile, "%3.2f %3.2f %3.2f C ",r,g,b);
+    }
+
+    if (colorspec->type != TC_FRAC)
+       return;
+
+/* map [0;1] to gray/colors */
+    gray = colorspec->value;
+    if (gray <= 0)
+       fputs("0 g ", gppsfile);
+    else {
+       if (gray >= 1)
+           fputs("1 g ", gppsfile);
+       else
+           fprintf(gppsfile, "%s g ", save_space(gray));
+    }
+    PS_relative_ok = FALSE; /* "M" required because "g" forces stroke (??) */
+}
+
+
+TERM_PUBLIC void PS_filled_polygon (int points, gpiPoint *corners)
+{
+    int i;
+    float filldens = 1.0;
+    int pattern = 0;
+    int style = corners->style;
+
+    /* Stroke the previous graphic element if required. */
+    if (PS_relative_ok)
+       PS_FLUSH_PATH;
+
+    if (points == 4 && style == FS_OPAQUE) {
+       /* Special case for pm3d surface quadrangles
+        *  <x0> <y0> ... <x4> <y4> h
+        */
+           fprintf(gppsfile, "%i %i N", corners[0].x, corners[0].y);
+           fprintf(gppsfile, " %i %i %i %i %i %i h\n",
+           corners[3].x-corners[2].x, corners[3].y-corners[2].y,
+           corners[2].x-corners[1].x, corners[2].y-corners[1].y,
+           corners[1].x-corners[0].x, corners[1].y-corners[0].y);
+    } else {
+       /* General case for solid or pattern-filled polygons
+        * gsave <x0> <y0> N <x1> <y1> ... <xn> <yn> density PolyFill
+        */
+       fprintf(gppsfile, "gsave ");
+       fprintf(gppsfile, "%i %i N", corners[0].x, corners[0].y);
+       for (i = 1; i < points; i++) {
+           /* The rationale for mixing V and L is given in PS_vector */
+           if (i % MAX_REL_PATHLEN)
+               fprintf(gppsfile, " %i %i V", corners[i].x-corners[i-1].x,
+                   corners[i].y-corners[i-1].y);
+           else
+               fprintf(gppsfile, " %i %i L", corners[i].x, corners[i].y);
+       }
+
+       switch(style & 0xf) {
+       
+       case FS_SOLID:
+           filldens = (style >> 4) / 100.0;
+           if(filldens < 0.0)
+               filldens = 0.0;
+           if(filldens >= 1.0)
+               fprintf(gppsfile, " 1 PolyFill\n");
+           else
+               fprintf(gppsfile, " %.2f PolyFill\n", filldens);
+           break;
+           
+       case FS_PATTERN:
+           pattern = (style >> 4) % 8;
+           if (pattern == 0)  {
+               filldens = 0.5;
+               fprintf(gppsfile, " %.1f PolyFill\n", filldens);
+           } else {
+               fprintf(gppsfile," Pattern%d fill grestore\n", pattern);
+           }
+           break;
+
+       default:
+           fputs(" 1 PolyFill\n", gppsfile);
+           break;
+
+       }
+    }
+
+    PS_relative_ok = FALSE;
+}
+
+#undef MAX_REL_PATHLEN
+
+TERM_PUBLIC void PS_previous_palette()
+{
+    /* Needed to stroke the previous graphic element. */
+    PS_FLUSH_PATH;
+    fputs("grestore % colour palette end\n", gppsfile);
+}
+
+
+/*
+ * The reason for having a PostScript-specific wrapper for do_arrow
+ * is that post.trm draws dotted lines for monochrome output, and
+ * dotted arrowheads are ugly.  So in that case we call do_arrow twice,
+ * the second time to retrace the head with the line style forced to solid.
+ */
+TERM_PUBLIC void PS_arrow (
+    unsigned int sx, unsigned int sy,
+    unsigned int ex, unsigned int ey,
+    int head)
+{
+    do_arrow( sx, sy, ex, ey, head );
+    if (!ps_params->solid && head != 0) {
+       PS_FLUSH_PATH;
+       fputs("gsave [] 0 setdash\n", gppsfile);
+       do_arrow( sx, sy, ex, ey, -head );
+       PS_FLUSH_PATH;
+       fputs("grestore\n", gppsfile);
+    }
+}
+
+static void
+delete_ps_fontfile(struct ps_fontfile_def *prev, struct ps_fontfile_def *this)
+{
+    if (this != NULL) {                /* there really is something to delete */
+       FPRINTF((stderr, "Remove font/kerning file `%s'\n",
+                this->fontfile_name));
+       if (prev != NULL)       /* there is a previous ps_fontfile */
+           prev->next = this->next;
+       else                    /* this = ps_params->first_fontfile */
+                               /* so change ps_params->first_fontfile */
+           ps_params->first_fontfile = this->next;
+       free(this->fontfile_name);
+       free(this->fontfile_fullname);
+       free(this);
+       this = NULL;
+    }
+}
+
+
+#ifdef WITH_IMAGE
+
+static void
+PS_encode85(unsigned long tuple4, unsigned char *tuple5)
+{
+    /* The compiler should know to carry out the powers of
+     * 85 computation at compilation time.
+     */
+    tuple5[0] = tuple4/(85*85*85*85);
+    tuple4 -= ((unsigned long)tuple5[0])*(85*85*85*85);
+    tuple5[1] = tuple4/(85*85*85);
+    tuple4 -= ((unsigned long)tuple5[1])*(85*85*85);
+    tuple5[2] = tuple4/(85*85);
+    tuple4 -= ((unsigned long)tuple5[2])*(85*85);
+    tuple5[3] = tuple4/(85);
+    tuple4 -= ((unsigned long)tuple5[3])*(85);
+    tuple5[4] = tuple4;
+}
+
+enum PS_ENCODING {
+    PS_ASCII_HEX,
+    PS_ASCII85
+} PS_ENCODING;
+
+/* Returns pointer to encoded image, allocated on heap that the
+ * caller must free.  Can error to command line so make sure all
+ * heap memory is recorded in static pointers when calling this
+ * routine.
+ */
+static char *
+PS_encode_image(unsigned M, unsigned N, coordval *image, t_imagecolor color_mode, 
+               int bits_per_component, int max_colors, double cscale,
+               enum PS_ENCODING encoding, int *return_num_bytes)
+{
+    unsigned coord_remaining;
+    coordval *coord_ptr;
+    unsigned short i_line;
+    unsigned i_element;
+    unsigned end_of_line;
+    unsigned short bits_remaining, bits_start;
+
+    unsigned long tuple4;
+    unsigned char tuple5[5];
+    int max_encoded_bytes;
+    char *encoded_image, *encoded_image_ptr;
+    unsigned long total_bits;
+
+#define ASCII_PER_LINE 78
+
+    /* 18.1.2009 RGB images ("plot ... with rgbimage") are drawn always in color,
+     * i.e. for both "set term post color" and "set term post mono".
+     */
+    total_bits = bits_per_component*M*N*((color_mode == IC_RGB /* && ps_params->color */) ? 3 : 1);
+
+    /* At the end of each image line, data is aligned to the nearest 8 bits,
+     * which means potentially adding 7 bits per line.
+     */
+    end_of_line = M;
+    total_bits += N*7;
+
+    /* Compute max number of ascii characters encoding will require.
+     */
+    if (encoding == PS_ASCII_HEX) {
+       /* Straight hex encoding */
+       max_encoded_bytes = (total_bits/4 + 1);
+       max_encoded_bytes += max_encoded_bytes / ASCII_PER_LINE; /* newline characters */
+    } else {
+       /* ASCII85 encoding */
+       max_encoded_bytes = (total_bits/32 + 1)*5 + 2; /* 5 tuples and additional ~> */
+       max_encoded_bytes += max_encoded_bytes / ASCII_PER_LINE; /* newline characters */
+    }
+
+    /* Reserve enough memory. */
+    if (!(encoded_image = gp_alloc(max_encoded_bytes, "encoded image")))
+       int_error(NO_CARET, "GNUPLOT (post.trm):  Error allocating memory.\n");
+    encoded_image_ptr = encoded_image;
+
+    coord_ptr = image;
+    i_line = ASCII_PER_LINE;
+    i_element = 0;
+    coord_remaining = M*N;
+    if (color_mode == IC_RGB /* && ps_params->color */) {
+       end_of_line *= 3;
+       coord_remaining *= 3;
+    }
+    bits_remaining = 32;
+    bits_start = 0;
+    tuple4 = 0;
+
+    while (coord_remaining) {
+       unsigned short us_tmp;
+       if (0 /* color_mode == IC_RGB && !ps_params->color */) {
+           coordval c_tmp;
+           c_tmp = *coord_ptr++;
+           c_tmp += *coord_ptr++;
+           c_tmp += *coord_ptr++;
+           us_tmp = (unsigned short) (c_tmp*(max_colors-1)/3.0 + 0.5);
+       } else
+           us_tmp = (unsigned short) ((*coord_ptr++) * max_colors);
+
+       if (us_tmp > (max_colors-1)) us_tmp = max_colors-1;
+
+       /* Rescale to accommodate a mismatch between max_colors and # of bits */
+       us_tmp *= cscale;
+
+       if (bits_remaining < bits_per_component) {
+           tuple4 <<= bits_remaining;
+           bits_start = bits_per_component - bits_remaining;
+           bits_remaining = 0;
+           tuple4 |= (us_tmp >> bits_start);
+       } else {
+           tuple4 <<= bits_per_component;
+           tuple4 |= us_tmp;
+           bits_remaining -= bits_per_component;
+       }
+
+       /* If this is last pixel in line, pad to nearest 8 bits. */
+       i_element++;
+       if (i_element == end_of_line) {
+           register unsigned short bit_align = (bits_remaining & 0x7);
+           tuple4 <<= bit_align;
+           bits_remaining -= bit_align;
+           i_element = 0;
+       }
+
+       /* Check if another 4-tuple is complete. */
+       if (!bits_remaining) {
+           if (ps_params->level1) {
+               /* A straight hex encoding for every 4 bits. */
+               unsigned char tuple8[8];
+               int i;
+               for (i=7; i >= 0; i--) {
+                   tuple8[i] = tuple4 & 0xf;
+                   tuple4 >>= 4;
+               }
+               for (i=0; i < 8; i++) {
+                   sprintf(encoded_image_ptr++, "%1x", tuple8[i]);
+                   i_line--;
+                   if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
+               }
+           } else {
+               /* Convert to ASCII85 representation. */
+               if (tuple4) {
+                   int i;
+                   PS_encode85(tuple4, tuple5);
+                   tuple4 = 0;
+                   for (i=0; i < 5; i++) {
+                       sprintf(encoded_image_ptr++, "%c", tuple5[i]+'!');
+                       i_line--;
+                       if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
+                   }
+               } else {
+                   *encoded_image_ptr++ = 'z';
+                   i_line--;
+                   if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
+               }
+           }
+
+           /* Now pick up any bits that may have not made it into the 4-tuple. */
+           if (bits_start) {tuple4 = us_tmp - ((us_tmp>>bits_start)<<bits_start);}
+           bits_remaining = 32 - bits_start;
+           bits_start = 0;
+
+       }
+
+       coord_remaining--;
+
+    }
+
+    if (bits_remaining < 32) {
+       int i;
+       int n = 4 - bits_remaining/8;
+       if (ps_params->level1) {
+           /* A straight hex encoding for every 4 bits. */
+           unsigned char tuple8[8];
+           for (i=2*n-1; i >= 0; i--) {
+               tuple8[i] = tuple4 & 0xf;
+               tuple4 >>= 4;
+           }
+           for (i=0; i < 2*n; i++) {
+               sprintf(encoded_image_ptr++, "%1x", tuple8[i]);
+               i_line--;
+               if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
+           }
+       } else {
+           /* Convert to ASCII85 representation.
+            *
+            * The case where not all bytes in a tuple are used is slightly different.
+            * There is no use of 'z' as a special character and the remaining bytes
+            * need to be filled.  Then use only a portion of the final 5-tuple.
+            */
+           tuple4 <<= bits_remaining;
+           PS_encode85(tuple4, tuple5);
+           /* Write first n+1 bytes. */
+           for (i=0; i <= n; i++) {
+               sprintf(encoded_image_ptr++, "%c", tuple5[i]+'!');
+               i_line--;
+               if (!i_line) {i_line = ASCII_PER_LINE; *encoded_image_ptr++ = '\n';}
+           }
+       }
+    }
+
+    if (!ps_params->level1) {
+       sprintf(encoded_image_ptr, "~>");
+       encoded_image_ptr += 2;
+    }
+
+    *return_num_bytes = (encoded_image_ptr - encoded_image);
+    assert(*return_num_bytes <= max_encoded_bytes); 
+    return encoded_image;
+}
+
+
+static void
+print_five_operand_image(unsigned M, unsigned N, gpiPoint *corner, t_imagecolor color_mode, unsigned short bits_per_component)
+{
+    char *space = ps_params->level1 ? "" : "  ";
+
+    fprintf(gppsfile, "%sgsave\n", space);
+    if (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY)
+       fprintf(gppsfile, "%s{pm3dGamma exp} settransfer\n", space);
+    fprintf(gppsfile, "%s%d %d translate\n", space, corner[0].x, corner[0].y);
+    fprintf(gppsfile, "%s%d %d scale\n", space, (corner[1].x - corner[0].x), (corner[1].y - corner[0].y));
+    fprintf(gppsfile, "%s%d %d %d\n", space, M, N, bits_per_component);
+    fprintf(gppsfile, "%s[ %d 0 0 %d 0 0 ]\n", space, M, N);
+    if (ps_params->level1) {
+       fprintf(gppsfile, "/imagebuf %d string def\n", 
+               (M*N*bits_per_component*((color_mode == IC_RGB /* && ps_params->color */) ? 3 : 1) + 7)/8);
+        fputs("{currentfile imagebuf readhexstring pop}\n", gppsfile);
+    } else
+       fprintf(gppsfile, "  currentfile /ASCII85Decode filter\n");
+    if (color_mode == IC_RGB /* && ps_params->color */) {
+       fprintf(gppsfile, "%sfalse 3\n"
+                         "%scolorimage\n", space, space);
+    } else
+       fprintf(gppsfile, "%simage\n", space);
+}
+
+
+TERM_PUBLIC void
+PS_image (unsigned M, unsigned N, coordval *image, gpiPoint *corner, t_imagecolor color_mode)
+{
+    char *encoded_image;
+    int num_encoded_bytes;
+    unsigned short bits_per_component = 0;
+    int max_colors, i_tmp;
+    TBOOLEAN five_operand_image;
+    double cscale;
+
+#define DEFAULT_BITS_PER_COMPONENT 8
+#define DEFAULT_COMPONENT_MAX (1<<DEFAULT_BITS_PER_COMPONENT)
+
+    if (sm_palette.use_maxcolors > 0)
+       max_colors = sm_palette.use_maxcolors;
+    else
+       max_colors = DEFAULT_COMPONENT_MAX;
+
+    i_tmp = 1;
+    while (i_tmp < max_colors) {
+       bits_per_component++;
+       i_tmp <<= 1;
+    }
+
+    if (bits_per_component < 1 || bits_per_component > 12) {
+       fprintf(stderr, "GNUPLOT (post.trm):  Component bits (%d) out of range.\n", bits_per_component);
+       return;
+    }
+
+    if (bits_per_component > 8)
+        bits_per_component = 12;
+    else if (bits_per_component > 4)
+        bits_per_component = 8;
+    else if (bits_per_component > 2)
+        bits_per_component = 4;
+
+    /* Color and gray scale images do not need a palette and can use
+     * the 5 operand form of the image routine.
+     */
+#if 0
+    /* 18.1.2009 It was decided to use the custom palette (i.e. colours) also
+       for the monochrome postscript output.
+    */
+    if ((color_mode == IC_RGB) || (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY) || !ps_params->color)
+#else
+    if ((color_mode == IC_RGB) || (sm_palette.colorMode == SMPAL_COLOR_MODE_RGB && !ps_params->color) || (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY))
+#endif
+        five_operand_image = TRUE;
+    else
+        five_operand_image = FALSE;
+
+    /* The five operand image doesn't have a palette and the values are
+     * such that 0 maps to 0.0 and 2^bits_per_component - 1 maps to 1.0
+     * in the PostScript driver.  Without any other knowledge, we scale
+     * things so that our max colors corresponds to 1.0.
+     */
+    if (five_operand_image)
+       cscale =  (float)((1 << bits_per_component)-1) / (float)(max_colors-1);
+    else
+       cscale = 1.0;
+
+    encoded_image = PS_encode_image(M, N, image, color_mode, 
+                               bits_per_component, max_colors, cscale,
+                               (ps_params->level1 ? PS_ASCII_HEX : PS_ASCII85), &num_encoded_bytes);
+
+    fputs("%%%%BeginImage\n", gppsfile);
+
+    /* Clip image to requested bounding box */
+    fprintf(gppsfile,"gsave %d %d N %d %d L %d %d L %d %d L Z clip\n",
+       corner[2].x, corner[2].y, corner[2].x, corner[3].y, corner[3].x, corner[3].y, corner[3].x, corner[2].y);
+
+    /* Color and gray scale images do not need a palette and can use
+     * the 5 operand form of the image routine.  For other types of
+     * palettes, the 1 operand form of the image routine must be used
+     * and an indexed palette needs to be constructed.
+     */
+    if (five_operand_image) {
+
+       if (ps_params->level1) {
+           print_five_operand_image(M, N, corner, color_mode, bits_per_component);
+       } else {
+           fputs("InterpretLevel1 {\n"
+                 "  %% Construct a box instead of image\n"
+                 "  LTb\n", gppsfile);
+           fprintf(gppsfile, "  %d %d M\n", corner[0].x, corner[0].y);
+           fprintf(gppsfile, "  %d 0 V\n", (corner[1].x - corner[0].x));
+           fprintf(gppsfile, "  0 %d V\n", (corner[1].y - corner[0].y));
+           fprintf(gppsfile, "  %d 0 V\n", -(corner[1].x - corner[0].x));
+           fprintf(gppsfile, "  %d %d L\n", corner[0].x, corner[0].y);
+           fputs("  40 -110 R\n"
+                 "  (PS level 2 image) Lshow\n"
+                 "  % Read data but ignore it\n", gppsfile);
+           fprintf(gppsfile, "  /imagebuf %d string def\n", num_encoded_bytes);
+           fputs("  currentfile imagebuf readstring\n"
+                 "} {\n", gppsfile);
+           print_five_operand_image(M, N, corner, color_mode, bits_per_component);
+           fputs("} ifelse\n", gppsfile);
+       }
+
+    }
+    else {
+
+       int allocated;
+       unsigned short i_tuple;
+       double fact = 1.0 / (double)(max_colors-1);
+       if (!ps_params->level1) {
+           fputs("InterpretLevel1 {\n"
+                 "  %% Construct a box instead of image\n"
+                 "  LTb\n", gppsfile);
+           fprintf(gppsfile, "  %d %d M\n", corner[0].x, corner[0].y);
+           fprintf(gppsfile, "  %d 0 V\n", (corner[1].x - corner[0].x));
+           fprintf(gppsfile, "  0 %d V\n", (corner[1].y - corner[0].y));
+           fprintf(gppsfile, "  %d 0 V\n", -(corner[1].x - corner[0].x));
+           fprintf(gppsfile, "  %d %d L\n", corner[0].x, corner[0].y);
+           fprintf(gppsfile, "  40 -110 R\n"
+                   "  (PS level 2 image) Lshow\n"
+                   "  %% Read data but ignore it\n"
+                   "  /imagebuf %d string def\n"
+                   "  currentfile imagebuf readstring\n", num_encoded_bytes);
+           fputs("} {\n", gppsfile);
+       }
+       fputs("gsave\n", gppsfile);
+       fprintf(gppsfile, "%d %d translate\n", corner[0].x, corner[0].y);
+       fprintf(gppsfile, "%d %d scale\n", (corner[1].x - corner[0].x), (corner[1].y - corner[0].y));
+       fputs("%%%%BeginPalette\n", gppsfile);
+       fprintf(gppsfile, "[ /Indexed\n  /DeviceRGB %d\n  <", (max_colors-1));
+
+#define TUPLES_PER_LINE 8
+
+       for (allocated = 0, i_tuple = 0; allocated < max_colors; allocated++, i_tuple--) {
+           double gray = (double) allocated * fact;
+           rgb255_color color;
+           rgb255maxcolors_from_gray( gray, &color );
+           if (!i_tuple) { fprintf(gppsfile,"\n  "); i_tuple = TUPLES_PER_LINE; }
+           fprintf(gppsfile," %2.2x%2.2x%2.2x", (int)color.r, (int)color.g, (int)color.b);
+       }
+
+       fputs("\n  >\n] setcolorspace\n", gppsfile);
+       fputs("%%%%EndPalette\n", gppsfile);
+       fprintf(gppsfile, "<<\n  /ImageType 1\n  /Width %d\n  /Height %d\n", M, N);
+       fprintf(gppsfile, "  /BitsPerComponent %d\n  /ImageMatrix [ %d 0 0 %d 0 0 ]\n", bits_per_component, M, N);
+       fprintf(gppsfile, "  /Decode [ 0 %d ]\n", ((1<<bits_per_component)-1));
+       if (ps_params->level1) {
+           fprintf(gppsfile, "  /imagebuf %d string def\n", (M*N*bits_per_component + 7)/8);
+           fputs("  /DataSource {currentfile imagebuf readhexstring pop}\n", gppsfile);
+       } else {
+           fputs("  /DataSource currentfile /ASCII85Decode filter\n", gppsfile);
+       }
+       fputs("  /MultipleDataSources false\n", gppsfile);
+       fputs("  /Interpolate false\n"
+             ">>\n"
+             "image\n", gppsfile);
+       if (!ps_params->level1)
+           fputs("} ifelse\n", gppsfile);
+
+    }
+
+    /* Send encoded image to file. */
+    {
+    char *encoded_image_ptr;
+    for (i_tmp=0, encoded_image_ptr = encoded_image; i_tmp < num_encoded_bytes; i_tmp++)
+       fputc(*encoded_image_ptr++, gppsfile);
+    }
+
+    if (ps_params->level1)
+       fputs("\ngrestore\n", gppsfile);
+    else
+       fputs("\nInterpretLevel1 not {\n"
+             "  grestore\n"
+             "} if\n", gppsfile);
+    fputs("grestore\n", gppsfile);
+    fputs("%%%%EndImage\n", gppsfile);
+
+    free(encoded_image);
+
+    return;
+}
+
+#endif /* WITH_IMAGE */
+
+/* First look for the GNUPLOT_PS_DIR environment variable
+ * If unsuccessful, look for hardcoded absolute path on UNIX,
+ * or hardcoded relative path on Windows and OS2,
+ * or files included at compile time. */
+static void
+PS_dump_prologue_file(char *name)
+{
+    char *fullname;
+    char *ps_prologue_dir;
+    FILE *prologue_fd;
+    char buf[256];
+
+    if ((ps_prologue_dir = getenv("GNUPLOT_PS_DIR")) == NULL) {
+#ifdef GNUPLOT_PS_DIR
+# if defined(_Windows)
+       /* retrieve prologues path relatively to gnuplot executable,
+        * whose path is in szModuleName (winmain.c) */
+       ps_prologue_dir = gp_alloc(strlen((char*) szModuleName)
+                       + strlen(GNUPLOT_PS_DIR) + 2, "Prolog path");
+       strcpy(ps_prologue_dir, (char*) szModuleName);
+       strcat(ps_prologue_dir, "\\");
+       /* GNUPLOT_PS_DIR is _relative_ path */
+       strcat(ps_prologue_dir, GNUPLOT_PS_DIR);
+# elif defined(OS2)
+       const ULONG bufsiz = 1024;
+       CHAR exepath[bufsiz];
+       PPIB ppib;
+       ULONG rc;
+       
+       rc = DosGetInfoBlocks(NULL, &ppib);
+       if (!rc)
+               rc = DosQueryModuleName(ppib->pib_hmte, bufsiz, (PCHAR) &exepath);
+       if (!rc) {
+           char *p = strrchr(exepath, '\\');
+           *(++p) = '\0';
+           ps_prologue_dir = gp_alloc(strlen(exepath) + strlen(GNUPLOT_PS_DIR) + 2,
+                       "Prolog path");
+           strcpy(ps_prologue_dir, exepath);
+           strcat(ps_prologue_dir, "\\");
+           /* GNUPLOT_PS_DIR is _relative_ path */
+           strcat(ps_prologue_dir, GNUPLOT_PS_DIR);
+       }
+       else {
+           ps_prologue_dir = gp_alloc(1, "Prolog path");
+           /* unsucessful to retrieve executable path */
+           strcpy(ps_prologue_dir,"");
+       }
+# else /* !_Windows && !OS2 */
+       /* use hardcoded _absolute_ path */
+       ps_prologue_dir = GNUPLOT_PS_DIR;
+# endif
+#else /* using headers included at compile time */
+       const char **dump = NULL;
+       int i;
+
+       /* load from included header */
+       if (!strcmp(name,"8859-15.ps"))
+               dump = prologue_8859_15_ps;
+       else if (!strcmp(name,"8859-1.ps"))
+               dump = prologue_8859_1_ps;
+       else if (!strcmp(name,"8859-2.ps"))
+               dump = prologue_8859_2_ps;
+       else if (!strcmp(name,"cp1250.ps"))
+               dump = prologue_cp1250_ps;
+       else if (!strcmp(name,"cp437.ps"))
+               dump = prologue_cp437_ps;
+       else if (!strcmp(name,"cp850.ps"))
+               dump = prologue_cp850_ps;
+       else if (!strcmp(name,"cp852.ps"))
+               dump = prologue_cp852_ps;
+       else if (!strcmp(name,"koi8r.ps"))
+               dump = prologue_koi8r_ps;
+       else if (!strcmp(name,"koi8u.ps"))
+               dump = prologue_koi8u_ps;
+       else if (!strcmp(name,"prologue.ps"))
+               dump = prologue_prologue_ps;
+       else
+               int_error(NO_CARET,"Requested Postscript prologue is not included");
+
+       if (dump) {
+               for (i = 0; dump[i] != NULL; ++i)
+               fprintf(gppsfile, "%s", dump[i]);
+       }
+       return;
+#endif /* GNUPLOT_PS_DIR */
+    }
+
+    fullname = gp_alloc(strlen(ps_prologue_dir) + strlen(name) + 4,"Prolog name");
+    strcpy(fullname,ps_prologue_dir);
+#if defined(_Windows) || defined(OS2)
+    if (fullname[strlen(fullname)-1] != '\\')
+       strcat(fullname,"\\");
+#elif !defined(VMS)
+    if (fullname[strlen(fullname)-1] != '/')
+       strcat(fullname,"/");
+#endif
+    strcat(fullname,name);
+    prologue_fd = fopen(fullname,"r");
+#if defined(_Windows) || defined(OS2)
+    if (getenv("GNUPLOT_PS_DIR") == NULL)
+       free(ps_prologue_dir);
+#endif
+    if (!prologue_fd)
+       prologue_fd = loadpath_fopen(name,"r");
+    if (!prologue_fd) {
+       fprintf(stderr,"Can't find PostScript prologue file %s\n", fullname);
+       loadpath_handler(ACTION_SHOW,NULL);
+       free(fullname);
+       fprintf(stderr,"Please copy %s to one of the above directories\n",name);
+       fprintf(stderr,"or set the loadpath appropriately\n");
+       fprintf(stderr,"or set the environmental variable GNUPLOT_PS_DIR\n");
+       int_error(NO_CARET,"Plot failed!");
+    }
+    free(fullname);
+    while (fgets(buf, sizeof(buf), prologue_fd))
+       fputs(buf, gppsfile);
+    fclose(prologue_fd);
+}
+
+TERM_PUBLIC void
+PS_path(int p)
+{
+    switch (p) {
+       case 0: /* Start new path */
+               PS_FLUSH_PATH;
+               PS_newpath = TRUE;
+               break;
+
+       case 1: /* Close path */
+               fprintf(gppsfile, "Z ");
+               PS_FLUSH_PATH;
+               break;
+    }
+
+}
+
+#endif /* TERM_BODY */
+
+#ifdef TERM_TABLE
+
+TERM_TABLE_START(post_driver)
+    "postscript",
+    "PostScript graphics, including EPSF embedded files (*.eps)",
+    PS_XMAX, PS_YMAX, PS_VCHAR, PS_HCHAR, 
+    PS_VTIC, PS_HTIC, PS_options, PS_init, PS_reset, 
+    PS_text, null_scale, PS_graphics, PS_move, PS_vector, 
+    PS_linetype, PS_put_text, PS_text_angle, 
+    PS_justify_text, PS_point, PS_arrow, PS_set_font, PS_pointsize,
+    TERM_BINARY|TERM_IS_POSTSCRIPT|TERM_CAN_CLIP /*flags*/, 
+    0 /*suspend*/, 0 /*resume*/, PS_fillbox, PS_linewidth
+#ifdef USE_MOUSE
+    , 0, 0, 0, 0, 0 /* no mouse support for postscript */
+#endif
+    , PS_make_palette,
+    PS_previous_palette, /* write grestore */
+    PS_set_color,
+    PS_filled_polygon
+#ifdef WITH_IMAGE
+    , PS_image
+#endif
+    , ENHPS_OPEN, ENHPS_FLUSH, ENHPS_WRITEC
+    , 0                /* layer control */
+    , PS_path
+TERM_TABLE_END(post_driver)
+
+#undef LAST_TERM
+#define LAST_TERM post_driver
+
+#endif /* TERM_TABLE */
+
+#endif /* TERM_PROTO_ONLY */
+
+#ifdef TERM_HELP
+/* This is a pseudo help section that is labeled with 00psglobal to be
+ * sure that it is sorted in before `post', `epslatex', and `pslatex'.
+ * This section just defines commonly used text snippets for all three
+ * help sections defined in this file. Defining PS_COMMON_OPTS1,
+ * PS_COMMON_OPTS2, and PS_COMMON_DOC1 outside START_HELP()...END_HELP()
+ * does not work.
+ * The last line before the END_HELP(00psglobal) contains one single line
+ * of "text" that is necessary to avoid errors.
+ */
+START_HELP(00psglobal)
+#define PS_COMMON_OPTS1 \
+"                               {level1 | leveldefault}",\
+"                               {color | colour | monochrome}",\
+"                               {solid | dashed}",\
+"                               {dashlength | dl <DL>}",\
+"                               {linewidth | lw <LW>}",\
+"                               {rounded | butt}",\
+"                               {palfuncparam <samples>{,<maxdeviation>}}",\
+"                               {size <XX>{unit},<YY>{unit}}",
+#define PS_COMMON_OPTS2 \
+"                               {blacktext | colortext | colourtext}",\
+"                               {{font} \"fontname{,fontsize}\" {<fontsize>}}",
+#define PS_COMMON_PROLOG_INFO \
+" If you see the error message",\
+"       \"Can't find PostScript prologue file ... \"",\
+" Please see and follow the instructions in `postscript prologue`.",\
+"",
+#define PS_COMMON_DOC1 \
+" The option `color` enables color, while `monochrome` prefers black and white",\
+" drawing elements. Further, `monochrome` uses gray `palette` but it does not",\
+" change color of objects specified with an explicit `colorspec`."\
+"",\
+" `solid` draws all plots with solid lines, overriding any dashed patterns.",\
+" `dashlength` or `dl` scales the length of the dashed-line segments by <DL>,",\
+" which is a floating-point number greater than zero.",\
+" `linewidth` or `lw` scales all linewidths by <LW>.",\
+"",\
+" By default the generated PostScript code uses language features that were",\
+" introduced in PostScript Level 2, notably filters and pattern-fill of",\
+" irregular objects such as filledcurves.  PostScript Level 2 features are",\
+" conditionally protected so that PostScript Level 1 interpreters do not issue",\
+" errors but, rather, display a message or a PostScript Level 1 approximation.",\
+" The `level1` option substitutes PostScript Level 1 approximations of these",\
+" features and uses no PostScript Level 2 code.  This may be required by some",\
+" old printers and old versions of Adobe Illustrator.  The flag `level1` can be", \
+" toggled later by editing a single line in the PostScript output file to force",\
+" PostScript Level 1 interpretation.  In the case of files containing level 2",\
+" code, the above features will not appear or will be replaced by a note when",\
+" this flag is set or when the interpreting program does not indicate that it",\
+" understands level 2 PostScript or higher.",\
+"",\
+" `rounded` sets line caps and line joins to be rounded; `butt` is the",\
+" default, butt caps and mitered joins;",\
+"",\
+" `palfuncparam` controls how `set palette functions` are encoded as gradients",\
+" in the output. Analytic color component functions (set via",\
+" `set palette functions`) are encoded as linear interpolated gradients in the",\
+" postscript output:  The color component functions are sampled at <samples>",\
+" points and all points are removed from this gradient which can be removed",\
+" without changing the resulting colors by more than <maxdeviation>. For",\
+" almost every useful palette you may savely leave the defaults of",\
+" <samples>=2000 and <maxdeviation>=0.003 untouched.",\
+"",\
+" The default size for postscript output is 10 inches x 7 inches. The default",\
+" for eps output is 5 x 3.5 inches.  The `size` option changes this to",\
+" whatever the user requests. By default the X and Y sizes are taken to be in",\
+" inches, but other units are possibly (currently only cm). The BoundingBox",\
+" of the plot is correctly adjusted to contain the resized image.",\
+" Screen coordinates always run from 0.0 to 1.0 along the full length of the",\
+" plot edges as specified by the `size` option.",\
+" NB: `this is a change from the previously recommended method of using the",\
+" set size command prior to setting the terminal type`.  The old method left",\
+" the BoundingBox unchanged and screen coordinates did not correspond to the",\
+" actual limits of the plot.",\
+"",
+""
+END_HELP(00psglobal)
+
+START_HELP(epslatex)
+"1 epslatex",
+"?commands set terminal epslatex",
+"?set terminal epslatex",
+"?set term epslatex",
+"?terminal epslatex",
+"?term epslatex",
+"?epslatex",
+" The `epslatex` driver generates output for further processing by LaTeX.",
+"",
+" Syntax:",
+"       set terminal epslatex   {default}",
+"       set terminal epslatex   {standalone | input}",
+"                               {oldstyle | newstyle}",
+PS_COMMON_OPTS1
+"                               {header <header> | noheader}",
+PS_COMMON_OPTS2
+"",
+" The epslatex terminal prints a plot as `terminal postscript eps`",
+" but transfers the texts to LaTeX instead of including in the PostScript",
+" code. Thus, many options are the same as in the `postscript terminal`.",
+"",
+" From version 4.0 to 4.2, some changes have been invoked into the default ",
+" appearance of the epslatex terminal to reach better consistency with the",
+" postscript terminal:  The plot size has been changed from 5 x 3 inches to",
+" 5 x 3.5 inches;  the character width is now estimated to be 60% of the font",
+" size while the old epslatex terminal used 50%;  now, the larger number of",
+" postscript linetypes and symbols are used.  To reach an appearance that is",
+" nearly identical to the old one specify the option `oldstyle`. (In fact",
+" some small differences remain: the symbol sizes are slightly different, the",
+" tics are half as large as in the old terminal which can be changed using",
+" `set tics scale`, and the arrows have all features as in the postscript",
+" terminal.)",
+"",
+PS_COMMON_PROLOG_INFO
+PS_COMMON_DOC1
+" `blacktext` forces all text to be written in black even in color mode;",
+"",
+" The epslatex driver offers a special way of controlling text positioning:",
+" (a) 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.  (b) If the text string begins with '[', you need",
+" to continue it with: a position specification (up to two out of t,b,l,r,c),",
+" ']{', 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.",
+" See also the documentation for the `pslatex` terminal driver.",
+" To create multiline labels, use \\shortstack, for example",
+"    set ylabel '[r]{\\shortstack{first line \\\\ second line}}' ",
+"",
+" The `back` option of `set label` commands is handled slightly different",
+" than in other terminals. Labels using 'back' are printed behind all other",
+" elements of the plot while labels using 'front' are printed above ",
+" everything else.",
+"",
+" The driver produces two different files, one for the eps part of the figure",
+" and one for the LaTeX part. The name of the LaTeX file is taken from the",
+" `set output` command. The name of the eps file is derived by replacing",
+" the file extension (normally `.tex`) with `.eps` instead.  There is no",
+" LaTeX output if no output file is given!  Remember to close the",
+" `output file` before next plot unless in `multiplot` mode.",
+"",
+" In your LaTeX documents use '\\input{filename}' to include the figure.",
+" The `.eps` file is included by the command \\includegraphics{...}, so you",
+" must also include \\usepackage{graphicx} in the LaTeX preamble.  If you",
+" want to use coloured text (option `textcolour`) you also have to include",
+" \\usepackage{color} in the LaTeX preamble.",
+"",
+" Pdf files can be made from the eps file using 'epstopdf'. If the graphics",
+" package is properly configured, the LaTeX files can also be processed by",
+" pdflatex without changes, using the pdf files instead of the eps files."
+"",
+" The behaviour concerning font selection depends on the header mode.",
+" In all cases, the given font size is used for the calculation of proper",
+" spacing. When not using the `standalone` mode the actual LaTeX font and",
+" font size at the point of inclusion is taken, so use LaTeX commands for",
+" changing fonts. If you use e.g. 12pt as font size for your LaTeX",
+" document, use '\"\" 12' as options. The font name is ignored. If using",
+" `standalone` the given font and font size are used, see below for a",
+" detailed description.",
+"",
+" If text is printed coloured is controlled by the TeX booleans \\ifGPcolor",
+" and \\ifGPblacktext. Only if \\ifGPcolor is true and \\ifGPblacktext is",
+" false, text is printed coloured. You may either change them in the",
+" generated TeX file or provide them globally in your TeX file, for example",
+" by using",
+"    \\newif\\ifGPblacktext",
+"    \\GPblacktexttrue",
+" in the preamble of your document. The local assignment is only done if no",
+" global value is given.",
+"",
+" When using the epslatex terminal give the name of the TeX file in the",
+" `set output` command including the file extension (normally \".tex\").",
+" The eps filename is generated by replacing the extension by \".eps\".",
+"",
+" If using the `standalone` mode a complete LaTeX header is added to the",
+" LaTeX file; and \"-inc\" is added to the filename of the eps file.",
+" The `standalone` mode generates a TeX file that produces",
+" output with the correct size when using dvips, pdfTeX, or VTeX.",
+" The default, `input`, generates a file that has to be included into a",
+" LaTeX document using the \\input command.",
+"",
+" If a font other than \"\" or \"default\" is given it is interpreted as",
+" LaTeX font name.  It contains up to three parts, separated by a comma:",
+" 'fontname,fontseries,fontshape'.  If the default fontshape or fontseries",
+" are requested, they can be omitted.  Thus, the real syntax for the fontname",
+" is '[fontname][,fontseries][,fontshape]'.  The naming convention for all",
+" parts is given by the LaTeX font scheme.  The fontname is 3 to 4 characters",
+" long and is built as follows: One character for the font vendor, two",
+" characters for the name of the font, and optionally one additional",
+" character for special fonts, e.g., 'j' for fonts with old-style numerals",
+" or 'x' for expert fonts. The names of many fonts is described in",
+"^ <a href=\"http://www.tug.org/fontname/fontname.pdf\">",
+"           http://www.tug.org/fontname/fontname.pdf",
+"^ </a>",
+" For example, 'cmr' stands for Computer Modern Roman, 'ptm' for Times-Roman,",
+" and 'phv' for Helvetica.  The font series denotes the thickness of the",
+" glyphs, in most cases 'm' for normal (\"medium\") and 'bx' or 'b' for bold",
+" fonts.  The font shape is 'n' for upright, 'it' for italics, 'sl' for",
+" slanted, or 'sc' for small caps, in general.  Some fonts may provide",
+" different font series or shapes.",
+"",
+" Examples:",
+"",
+" Use Times-Roman boldface (with the same shape as in the surrounding text):",
+"       set terminal epslatex 'ptm,bx'",
+" Use Helvetica, boldface, italics:",
+"       set terminal epslatex 'phv,bx,it'",
+" Continue to use the surrounding font in slanted shape:",
+"       set terminal epslatex ',,sl'",
+" Use small capitals:",
+"       set terminal epslatex ',,sc'",
+"",
+" By this method, only text fonts are changed. If you also want to change",
+" the math fonts you have to use the \"gnuplot.cfg\" file or the `header`",
+" option, described below.",
+"",
+" In standalone mode, the font size is taken from the given font size in the",
+" `set terminal` command. To be able to use a specified font size, a file",
+" \"size<size>.clo\" has to reside in the LaTeX search path.  By default,",
+" 10pt, 11pt, and 12pt are supported.  If the package \"extsizes\" is",
+" installed, 8pt, 9pt, 14pt, 17pt, and 20pt are added.",
+"",
+" The `header` option takes a string as argument.  This string is written",
+" into the generated LaTeX file.  If using the `standalone` mode, it is ",
+" written into the preamble, directly before the \\begin{document} command.",
+" In the `input` mode, it is placed directly after the \\begingroup command",
+" to ensure that all settings are local to the plot.",
+"",
+" Examples:",
+"",
+" Use T1 fontencoding, change the text and math font to Times-Roman as well",
+" as the sans-serif font to Helvetica:",
+"     set terminal epslatex standalone header \\",
+"     \"\\\\usepackage[T1]{fontenc}\\n\\\\usepackage{mathptmx}\\n\\\\usepackage{helvet}\"",
+" Use a boldface font in the plot, not influencing the text outside the plot:",
+"     set terminal epslatex input header \"\\\\bfseries\"",
+"",
+" If the file \"gnuplot.cfg\" is found by LaTeX it is input in the preamble",
+" the LaTeX document, when using `standalone` mode.  It can be used for",
+" further settings, e.g., changing the document font to Times-Roman,",
+" Helvetica, and Courier, including math fonts (handled by \"mathptmx.sty\"):",
+"       \\usepackage{mathptmx}",
+"       \\usepackage[scaled=0.92]{helvet}",
+"       \\usepackage{courier}",
+" The file \"gnuplot.cfg\" is loaded before the header information given",
+" by the `header` command.  Thus, you can use `header` to overwrite some of",
+" settings performed using \"gnuplot.cfg\"",
+""
+END_HELP(epslatex)
+
+START_HELP(pslatex)
+"1 pslatex and pstex",
+"?commands set terminal pslatex",
+"?set terminal pslatex",
+"?set term pslatex",
+"?terminal pslatex",
+"?term pslatex",
+"?pslatex",
+"?commands set terminal pstex",
+"?set terminal pstex",
+"?set term pstex",
+"?terminal pstex",
+"?term pstex",
+"?pstex",
+" The `pslatex` driver generates output for further processing by LaTeX,",
+" while the `pstex` driver generates output for further processing by",
+" TeX. `pslatex` uses \\specials understandable by dvips and xdvi. Figures",
+" generated by `pstex` can be included in any plain-based format (including",
+" LaTeX).",
+"",
+" Syntax:",
+"       set terminal [pslatex | pstex] {default}",
+"       set terminal [pslatex | pstex]",
+"                               {rotate | norotate}",
+"                               {oldstyle | newstyle}",
+"                               {auxfile | noauxfile}",
+PS_COMMON_OPTS1
+"                               {<font_size>}",
+"",
+PS_COMMON_PROLOG_INFO
+PS_COMMON_DOC1
+" if `rotate` is specified, the y-axis label is rotated.",
+" <font_size> is the size (in pts) of the desired font.",
+"",
+" If `auxfile` is specified, it directs the driver to put the PostScript",
+" commands into an auxiliary file instead of directly into the LaTeX file.",
+" This is useful if your pictures are large enough that dvips cannot handle",
+" them.  The name of the auxiliary PostScript file is derived from the name of",
+" the TeX file given on the `set output` command; it is determined by replacing",
+" the trailing `.tex` (actually just the final extent in the file name) with",
+" `.ps` in the output file name, or, if the TeX file has no extension, `.ps`",
+" is appended.  The `.ps` is included into the `.tex` file by a",
+" \\special{psfile=...} command.  Remember to close the `output file` before",
+" next plot unless in `multiplot` mode.",
+"",
+" Gnuplot versions prior version 4.2 have generated plots of the size",
+" 5 x 3 inches using the ps(la)tex terminal while the current version generates",
+" 5 x 3.5 inches to be consistent with the postscript eps terminal.  In",
+" addition, the character width is now estimated to be 60% of the font size",
+" while the old epslatex terminal used 50%. To reach the old format specify",
+" the option `oldstyle`.",
+"",
+" The pslatex driver offers a special way of controlling text positioning: ",
+" (a) 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.  (b) 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.",
+"",
+" The options not described here are identical to the `Postscript terminal`.",
+" Look there if you want to know what they do.",
+"",
+" Examples:",
+"       set term pslatex monochrome dashed rotate       # set to defaults",
+" To write the PostScript commands into the file \"foo.ps\":",
+"       set term pslatex auxfile",
+"       set output \"foo.tex\"; plot ...; set output",
+" 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}}'",
+"",
+" Linewidths and pointsizes may be changed with `set style line`."
+""
+END_HELP(pslatex)
+
+START_HELP(post)
+"1 postscript",
+"?commands set terminal postscript",
+"?set terminal postscript",
+"?set term postscript",
+"?terminal postscript",
+"?term postscript",
+"?postscript",
+" Several options may be set in the `postscript` driver.",
+"",
+" Syntax:",
+"       set terminal postscript {default}",
+"       set terminal postscript {landscape | portrait | eps}",
+"                               {enhanced | noenhanced}",
+"                               {defaultplex | simplex | duplex}",
+"                               {fontfile [add | delete] \"<filename>\"",
+"                                | nofontfiles}",
+PS_COMMON_OPTS1
+PS_COMMON_OPTS2
+PS_COMMON_PROLOG_INFO
+"",
+" `landscape` and `portrait` choose the plot orientation.",
+" `eps` mode generates EPS (Encapsulated PostScript) output, which is just",
+" regular PostScript with some additional lines that allow the file to be",
+" imported into a variety of other applications.  (The added lines are",
+" PostScript comment lines, so the file may still be printed by itself.)  To",
+" get EPS output, use the `eps` mode and make only one plot per file.  In `eps`",
+" mode the whole plot, including the fonts, is reduced to half of the default",
+" size.",
+"",
+" `enhanced` enables enhanced text mode features (subscripts,",
+" superscripts and mixed fonts). See `enhanced` for more information.",
+" `blacktext` forces all text to be written in black even in color mode;",
+"",
+" Duplexing in PostScript is the ability of the printer to print on both",
+" sides of the same sheet of paper.  With `defaultplex`, the default setting",
+" of the printer is used; with `simplex` only one side is printed; `duplex`",
+" prints on both sides (ignored if your printer can't do it).",
+"",
+" `\"<fontname>\"` is the name of a valid PostScript font; and `<fontsize>` is",
+" the size of the font in PostScript points.",
+" In addition to the standard postscript fonts, an oblique version of the",
+" Symbol font, useful for mathematics, is defined. It is called",
+" \"Symbol-Oblique\".",
+"",
+" `default` sets all options to their defaults: `landscape`, `monochrome`,",
+" `dashed`, `dl 1.0`, `lw 1.0`, `defaultplex`, `noenhanced`, \"Helvetica\" and",
+" 14pt.  Default size of a PostScript plot is 10 inches wide and 7 inches high.",
+PS_COMMON_DOC1
+" Fonts listed by `fontfile` or `fontfile add` encapsulate the font",
+" definitions of the listed font from a postscript Type 1 or TrueType font",
+" file directly into the gnuplot output postscript file.  Thus, the enclosed",
+" font can be used in labels, titles, etc.  See the section",
+" `postscript fontfile` for more details.  With `fontfile delete`, a fontfile",
+" is deleted from the list of embedded files.  `nofontfiles` cleans the list",
+" of embedded fonts.",
+"",
+" Examples:",
+"       set terminal postscript default       # old postscript",
+"       set terminal postscript enhanced      # old enhpost",
+"       set terminal postscript landscape 22  # old psbig",
+"       set terminal postscript eps 14        # old epsf1",
+"       set terminal postscript eps 22        # old epsf2",
+"       set size 0.7,1.4; set term post portrait color \"Times-Roman\" 14",
+"       set term post \"VAGRoundedBT_Regular\" 14 fontfile \"bvrr8a.pfa\"",
+"",
+" Linewidths and pointsizes may be changed with `set style line`.",
+"",
+" The `postscript` driver supports about 70 distinct pointtypes, selectable",
+" through the `pointtype` option on `plot` and `set style line`.",
+"",
+" Several possibly useful files about `gnuplot`'s PostScript are included",
+" in the /docs/psdoc subdirectory of the `gnuplot` distribution and at the",
+" distribution sites.  These are \"ps_symbols.gpi\" (a `gnuplot` command file",
+" that, when executed, creates the file \"ps_symbols.ps\" which shows all the",
+" symbols available through the `postscript` terminal), \"ps_guide.ps\" (a",
+" PostScript file that contains a summary of the enhanced syntax and a page",
+" showing what the octal codes produce with text and symbol fonts),",
+" \"ps_file.doc\" (a text file that contains a discussion of the organization",
+" of a PostScript file written by `gnuplot`), and \"ps_fontfile_doc.tex\"",
+" (a LaTeX file which contains a short documentation concerning the",
+" encapsulation of LaTeX fonts with a glyph table of the math fonts).",
+"",
+" A PostScript file is editable, so once `gnuplot` has created one, you are",
+" free to modify it to your heart's desire.  See the `editing postscript`",
+" section for some hints.",
+"2 enhanced postscript",
+"?commands set terminal postscript enhanced",
+"?set terminal postscript enhanced",
+"?set term postscript enhanced",
+"?terminal postscript enhanced",
+"?term postscript enhanced",
+"?enhanced_postscript",
+"?enhanced postscript",
+"?Enhanced postscript",
+"?enhanced text",
+"?Enhanced text",
+"?enhanced",
+" Several terminal types support an enhanced text mode in which ",
+" additional formatting information is embedded in the text string.",
+"",
+"@start table - first is interactive cleartext form",
+"  Control      Examples        Explanation",
+"   ^           a^x             superscript",
+"   _           a_x             subscript",
+"   @           @x or a@^b_c    phantom box (occupies no width)",
+"   &           &{space}        inserts space of specified length",
+"   ~           ~a{.8-}         overprints '-' on 'a', raised by .8",
+"                               times the current fontsize",
+"#\\begin{tabular}{|ccl|} \\hline",
+"#\\multicolumn{3}{|c|}{Enhanced Text Control Codes} \\\\ \\hline",
+"#Control & Examples & Explanation \\\\ \\hline",
+"#\\verb~^~ & \\verb~a^x~ & superscript\\\\",
+"#\\verb~_~ & \\verb~a_x~ & subscript\\\\",
+"#\\verb~@~ & \\verb~@x or a@^b_c~ & phantom box (occupies no width)\\\\",
+"#\\verb~&~ & \\verb~&{space}~ & inserts space of specified length\\\\",
+"#\\verb|~| & \\verb|~a{.8-}| & overprints '-' on 'a', raised by .8\\\\",
+"#\\verb~ ~ & \\verb~ ~ & times the current fontsize\\\\",
+"%c c l .",
+"%.TE", /* ugly - doc2ms uses @ for column separator, but here we */
+"%.TS", /* need @ in table, so end and restart the table ! */
+"%center box tab ($) ;",
+"%c c l .",
+"%Control$Examples$Explanation",
+"%_",
+"%^$a^x$superscript",
+"%\\&_$a\\&_x$subscript",
+"% @ $ @x or a\\&@^b\\&_c$phantom box (occupies no width)",
+"% & $ &{space}$inserts space of specified length",
+"% ~ $ ~a{.8-}$overprints '-' on 'a', raised by .8",
+"%   $   $times the current fontsize",
+"@end table",
+"",
+" Braces can be used to place multiple-character text where a single character",
+" is expected (e.g., 2^{10}).  To change the font and/or size, use the full",
+" form:  {/[fontname][=fontsize | *fontscale] text}.  Thus {/Symbol=20 G} is a",
+" 20-point GAMMA and {/*0.75 K} is a K at three-quarters of whatever fontsize",
+" is currently in effect.  (The '/' character MUST be the first character after",
+" the '{'.)",
+"",
+" If the encoding vector has been changed by `set encoding`, the default",
+" encoding vector can be used instead by following the slash with a dash.  This",
+" is unnecessary if you use the Symbol font, however---since /Symbol uses its",
+" own encoding vector, `gnuplot` will not apply any other encoding vector to",
+" it.",
+"",
+" The phantom box is useful for a@^b_c to align superscripts and subscripts",
+" but does not work well for overwriting an accent on a letter.  (To do the",
+" latter, it is much better to use 'set encoding iso_8859_1' to change to the",
+" ISO Latin-1 encoding vector, which contains a large variety of letters with",
+" accents or other diacritical marks.)  Since the box is non-spacing, it is",
+" sensible to put the shorter of the subscript or superscript in the box (that",
+" is, after the @).",
+"",
+" Space equal in length to a string can be inserted using the '&' character.",
+" Thus",
+"         'abc&{def}ghi'",
+" would produce",
+"         'abc   ghi'.",
+"",
+" The '~' character causes the next character or bracketed text to be",
+" overprinted by the following character or bracketed text.  The second text",
+" will be horizontally centered on the first.  Thus '~a/' will result in an 'a'",
+" with a slash through it.  You can also shift the second text vertically by",
+" preceding the second text with a number, which will define the fraction of the",
+" current fontsize by which the text will be raised or lowered.  In this case",
+" the number and text must be enclosed in brackets because more than one",
+" character is necessary.  If the overprinted text begins with a number, put a",
+" space between the vertical offset and the text ('~{abc}{.5 000}'); otherwise",
+" no space is needed ('~{abc}{.5---}').  You can change the font for one or",
+" both strings ('~a{.5 /*.2 o}'---an 'a' with a one-fifth-size 'o' on top---and",
+" the space between the number and the slash is necessary), but you can't",
+" change it after the beginning of the string.  Neither can you use any other",
+" special syntax within either string.  You can, of course, use control",
+" characters by escaping them (see below), such as '~a{\\^}'",
+"",
+" You can access special symbols numerically by specifying \\character-code (in",
+" octal), e.g., {/Symbol \\245} is the symbol for infinity.",
+"",
+" You can escape control characters using \\, e.g.,  \\\\, \\{, and so on.",
+"",
+" But be aware that strings in double-quotes are parsed differently than those",
+" enclosed in single-quotes.  The major difference is that backslashes may need",
+" to be doubled when in double-quoted strings.",
+"",
+" Examples (these are hard to describe in words---try them!):",
+"       set xlabel 'Time (10^6 {/Symbol m}s)'",
+"       set title '{/Symbol=18 \\362@_{/=9.6 0}^{/=12 x}} \\",
+"                  {/Helvetica e^{-{/Symbol m}^2/2} d}{/Symbol m}'",
+"",
+" The file \"ps_guide.ps\" in the /docs/psdoc subdirectory of the `gnuplot` source",
+" distribution contains more examples of the enhanced syntax.",
+"2 editing postscript",
+"?commands set terminal postscript editing",
+"?set terminal postscript editing",
+"?set term postscript editing",
+"?terminal postscript editing",
+"?term postscript editing",
+"?editing_postscript",
+"?editing postscript",
+" The PostScript language is a very complex language---far too complex to",
+" describe in any detail in this document.  Nevertheless there are some things",
+" in a PostScript file written by `gnuplot` that can be changed without risk of",
+" introducing fatal errors into the file.",
+"",
+" For example, the PostScript statement \"/Color true def\" (written into the",
+" file in response to the command `set terminal postscript color`), may be",
+" altered in an obvious way to generate a black-and-white version of a plot.",
+" Similarly line colors, text colors, line weights and symbol sizes can also be",
+" altered in straight-forward ways.  Text (titles and labels) can be edited to",
+" correct misspellings or to change fonts.  Anything can be repositioned, and",
+" of course anything can be added or deleted, but modifications such as these",
+" may require deeper knowledge of the PostScript language.",
+"",
+" The organization of a PostScript file written by `gnuplot` is discussed in",
+" the text file \"ps_file.doc\" in the docs/ps subdirectory of the gnuplot",
+" source distribution.",
+"2 postscript fontfile",
+"?commands set terminal postscript fontfile",
+"?set terminal postscript fontfile",
+"?set term postscript fontfile",
+"?terminal postscript fontfile",
+"?term postscript fontfile",
+"?postscript fontfile",
+"?fontfile",
+" The `fontfile` or `fontfile add` option takes one file name as argument",
+" and encapsulates this file into the postscript output in order to make",
+" this font available for text elements (labels, tic marks, titles, etc.).",
+" The `fontfile delete` option also takes one file name as argument. It",
+" deletes this file name from the list of encapsulated files.",
+"",
+" The postscript terminal understands some",
+" font file formats: Type 1 fonts in ASCII file format (extension \".pfa\"),",
+" Type 1 fonts in binary file format (extension \".pfb\"), and TrueType",
+" fonts (extension \".ttf\"). Pfa files are understood directly, pfb and ttf",
+" files are converted on the fly if appropriate conversion tools are",
+" installed (see below). You have to specify the full filename including the",
+" extension. Each `fontfile` option takes exact one font file name. This",
+" option can be used multiple times in order to include more than one font",
+" file.",
+"",
+" The font file is searched in the working directory and in all directories",
+" listed in the fontpath which is determined by `set fontpath`.",
+" In addition, the fontpath can be set using the environment variable",
+" GNUPLOT_FONTPATH. If this is not set a system dependent default search",
+" list is used. See `set fontpath` for more details.",
+"",
+" For using the encapsulated font file you have to specify the font name",
+" (which normally is not the same as the file name). When embedding a",
+" font file by using the `fontfile` option in interactive mode, the ",
+" font name is printed on the screen. E.g.",
+"    Font file 'p052004l.pfb' contains the font 'URWPalladioL-Bold'. Location:",
+"    /usr/lib/X11/fonts/URW/p052004l.pfb",
+"",
+" When using pfa or pfb fonts, you can also find it out by looking into the",
+" font file. There is a line similar to \"/FontName /URWPalladioL-Bold def\".",
+" The middle string without the slash is the fontname, here",
+" \"URWPalladioL-Bold\".",
+" For TrueType fonts, this is not so easy since the font name is stored in a",
+" binary format. In addition, they often have spaces in the font names which",
+" is not supported by Type 1 fonts (in which a TrueType is converted on the",
+" fly). The font names are changed in order to eliminate the spaces in the",
+" fontnames. The easiest way to find out which font name is generated for",
+" use with gnuplot, start gnuplot in interactive mode and type in",
+" \"set terminal postscript fontfile '<filename.ttf>'\".",
+"",
+" For converting font files (either ttf or pfb) to pfa format, the conversion",
+" tool has to read the font from a file and write it to standard output. If",
+" the output cannot be written to standard output, on-the-fly conversion is",
+" not possible.",
+"",
+" For pfb files \"pfbtops\" is a tool which can do this. If this program",
+" is installed on your system the on the fly conversion should work.",
+" Just try to encapsulate a pfb file. If the compiled in program call does",
+" not work correctly you can specify how this program is called by",
+" defining the environment variable GNUPLOT_PFBTOPFA e.g. to",
+" \"pfbtops %s\". The `%s` will be replaced by the font file name and thus",
+" has to exist in the string.",
+"",
+" If you don't want to do the conversion on the fly but get a pfa file of",
+" the font you can use the tool \"pfb2pfa\" which is written in simple c",
+" and should compile with any c compiler.",
+" It is available from many ftp servers, e.g.",
+"^ <a href=\"ftp://ftp.dante.de/tex-archive/fonts/utilities/ps2mf/\">",
+"           ftp://ftp.dante.de/tex-archive/fonts/utilities/ps2mf/",
+"^ </a>",
+" In fact, \"pfbtopfa\" and \"pfb2ps\" do the same job. \"pfbtopfa\" puts",
+" the resulting pfa code into a file, whereas \"pfbtops\" writes it to",
+" standard output.",
+"",
+" TrueType fonts are converted into Type 1 pfa format, e.g.",
+" by using the tool \"ttf2pt1\" which is available from",
+"^ <a href=\"http://ttf2pt1.sourceforge.net/\">",
+"           http://ttf2pt1.sourceforge.net/",
+"^ </a>",
+" If the builtin conversion does not",
+" work, the conversion command can be changed by the environment variable",
+" GNUPLOT_TTFTOPFA. For usage with ttf2pt1 it may be set to",
+" \"ttf2pt1 -a -e -W 0 %s - \". Here again, `%s` stands for the",
+" file name.",
+"",
+" For special purposes you also can use a pipe (if available for your",
+" operating system). Therefore you start the file name definition with ",
+" the character \"<\" and append a program call. This program has ",
+" to write pfa data to standard output. Thus, a pfa file may be accessed",
+" by `set fontfile \"< cat garamond.pfa\"`.",
+"",
+" For example, including Type 1 font files can be used for including the",
+" postscript output in LaTeX documents. The \"european computer modern\"",
+" font (which is a variant of the \"computer modern\" font) is available",
+" in pfb format from any CTAN server, e.g.",
+"^ <a href=\"ftp://ftp.dante.de/tex-archive/fonts/ps-type1/cm-super/\">",
+"           ftp://ftp.dante.de/tex-archive/fonts/ps-type1/cm-super/",
+"^ </a>",
+" For example, the file \"sfrm1000.pfb\" contains the normal upright fonts",
+" with serifs in the design size 10pt (font name \"SFRM1000\").",
+" The computer modern fonts, which are still necessary for mathematics,",
+" are available from",
+"^ <a href=\"ftp://ftp.dante.de/tex-archive/fonts/cm/ps-type1/bluesky\">",
+"           ftp://ftp.dante.de/tex-archive/fonts/cm/ps-type1/bluesky",
+"^ </a>",
+" With these you can use any character available in TeX. However, the",
+" computer modern fonts have a strange encoding. (This is why you should not",
+" use cmr10.pfb for text, but sfrm1000.pfb instead.)",
+" The usage of TeX fonts is shown in one of the demos.",
+" The file \"ps_fontfile_doc.tex\" in the /docs/psdoc subdirectory of the",
+" `gnuplot` source distribution contains a table with glyphs of the TeX",
+" mathfonts.",
+"",
+" If the font \"CMEX10\" is embedded (file \"cmex10.pfb\") gnuplot defines",
+" the additional font \"CMEX10-Baseline\". It is shifted vertically in order",
+" to fit better to the other glyphs (CMEX10 has its baseline at the top of",
+" the symbols).",
+"2 postscript prologue",
+"?commands set terminal postscript prologue",
+"?set terminal postscript prologue",
+"?terminal postscript prologue",
+"?postscript prologue",
+"?prologue",
+" Each PostScript output file includes a %%Prolog section and possibly some",
+" additional user-defined sections containing, for example, character",
+" encodings. These sections are copied from a set of PostScript prologue files",
+" which are either compiled in the gnuplot executable or stored elsewhere on your",
+" computer. This behaviour and the default directory where these files live are",
+" controlled at the time gnuplot is built. However, you can control this",
+" either by defining an environment variable GNUPLOT_PS_DIR or by using the",
+" gnuplot command `set loadpath`. See `set loadpath`.",
+"",
+""
+END_HELP(post)
+#endif /* TERM_HELP */