Attached are patches (relative to the base 3.5 distribution) for the following features: 1. 'call' command. Like load but with substitutable parameters. 2. 'if' command. Conditionalize command execution. Useful with load and call commands. 3. enhpost "Enhanced PostScript" terminal. Allows use of additional fonts, super/sub-scripts, change of font size, extended characters. use 'patch -p + * In its previous life, this file was divpost34.trm. + * by David Denholm, (aka "div") + * My changes include making this into a different terminal "enhpost", + * the super/subscripts are scaled in both directions, instead of just squashed + * in height. A different output format that doesn't require processing + * everything twice here (i.e., smarter PostScript), generalizing the {} grouping + * and font change notation. + * Matt Heffron Oct 29, 1993 + * + * This has been rewritten, since there has been considerable interest + * in it. I have tried to fix the justification, and have added a couple + * of new features. Also, the shift for superscript now depends on the + * fontsize. + * + * any text can contain the following special formatting instructions + * (eg use the SET FORMAT command to put them in for axis scales): + * a^x or a^{xyz} - superscript + * a_x or a_{xyz} - subscript + * {text} - allow multiple-character text, where only a single + * - character is expected. + * {/[fontname][=fontsize] text} - writes text in different font + * - and/or, optionally, different size + * + * @x is a phantom box - x is written, but occupies no width. + * Useful for a@^b_c to align superscript and subscript, and for + * overwriting an accent on a letter. + * It is common sense to put the shorter of the two in the phantom box. + * + * NOTES + * + * You can access high-numbering symbols by specifying \ascii-value (octal), + * eg {/Symbol \245} is infinity. (can't check number right now....) + * {/EuroFont \217} is angstrom - see eurofont.ps + * + * You can escape control characters using \, eg + * \\, \{, \}, \^, \@ + * + * The rest of gnuplot will not know about a change of font, so if you + * make a huge title, it will overwrite the graph. + * Perhaps it's best to set term post with the largest font, and only ever + * reduce the fontsize ??? + * + * ASIDE: + * + * I've added a couple of point-types. + * + */ + + /* + * ????? $Id: enhpost.trm%v 3.38.2.125 1993/05/05 00:13:05 woo Exp woo $ + */ + + /* GNUPLOT - enhpost.trm */ + /* + * Copyright (C) 1990 - 1993 + * + * 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 modified code. Modifications are to be distributed + * as patches to released version. + * + * This software is provided "as is" without express or implied warranty. + * + * This file is included by ../term.c. + * + * This terminal driver supports: + * enhpost Enhanced PostScript + * It is an extension to the postscript terminal driver and depends on + * that being included (in ../term.c) before this is included. + * + * AUTHORS + * Russell Lang + * David Denholm + * Matt Heffron + * + * DIV WAS HERE - we use different text routines that understand ^, _ + * and { ... } + * ^, _ and @ take only one character, unless you enclose stuff in {...} + * Its up to the user to put in two \'s, so that we can use \ to specify + * control charcters (eg "{/Symbol \245}" gives infinity) + * DIV was here AGAIN ! - teach it some more point types. + * Div's latest addition - @{text} gives a 'phantom box' containing text, but + * taking up no space, so @{text}more text will _overwrite_ text with + * more text - hopefully useful for hats and such things..? + * It's all done with recursion, so you can change font inside the phantom + * box, etc. + * + * send your comments or suggestions to (info-gnuplot@dartmouth.edu). + * + * ALMOST the same as 'postscript' except for string handling. + */ + + /* added by Matt Heffron */ + TBOOLEAN ENHps_duplex_state = FALSE; + TBOOLEAN ENHps_duplex_option = FALSE; + + char GPFAR * GPFAR ENHPS_header[] = { + "/M {moveto} bind def\n", + "/L {lineto} bind def\n", + "/R {rmoveto} bind def\n", + "/V {rlineto} bind def\n", + "/vpt2 vpt 2 mul def\n", + "/hpt2 hpt 2 mul def\n", + + /* For MFshow and MFwidth the tos is an array with the string and font info: */ + /* [ ] */ + + "/MFshow {{dup dup 0 get findfont exch 1 get scalefont setfont\n", + " [ currentpoint ] exch dup 2 get 0 exch rmoveto dup 4 get show dup\n", + " 3 get {2 get neg 0 exch rmoveto pop} {pop aload pop moveto}ifelse} forall} bind def\n", + "/MFwidth {0 exch {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont\n", + " 4 get stringwidth pop add}\n", + " {pop} ifelse} forall} bind def\n", + + /* flush left show */ + "/Lshow { currentpoint stroke M\n", + " 0 exch R MFshow } bind def\n", + + /* flush right show */ + "/Rshow { currentpoint stroke M\n", + " exch dup MFwidth neg 3 -1 roll R MFshow } def\n", + + /* centred show */ + "/Cshow { currentpoint stroke M\n", + " exch dup MFwidth -2 div 3 -1 roll R MFshow } def\n", + + /* Dash or Color Line */ + "/DL { Color {setrgbcolor Solid {pop []} if 0 setdash }\n", + " {pop pop pop Solid {pop []} if 0 setdash} ifelse } def\n", + + /* Border Lines */ + "/BL { stroke gnulinewidth 2 mul setlinewidth } def\n", + + /* Axes Lines */ + "/AL { stroke gnulinewidth 2 div setlinewidth } def\n", + + /* Plot Lines */ + "/PL { stroke gnulinewidth setlinewidth } def\n", + + /* Line Types */ + "/LTb { BL [] 0 0 0 DL } def\n", /* border */ + "/LTa { AL [1 dl 2 dl] 0 setdash 0 0 0 setrgbcolor } def\n", /* axes */ + "/LT0 { PL [] 0 1 0 DL } def\n", + "/LT1 { PL [4 dl 2 dl] 0 0 1 DL } def\n", + "/LT2 { PL [2 dl 3 dl] 1 0 0 DL } def\n", + "/LT3 { PL [1 dl 1.5 dl] 1 0 1 DL } def\n", + "/LT4 { PL [5 dl 2 dl 1 dl 2 dl] 0 1 1 DL } def\n", + "/LT5 { PL [4 dl 3 dl 1 dl 3 dl] 1 1 0 DL } def\n", + "/LT6 { PL [2 dl 2 dl 2 dl 4 dl] 0 0 0 DL } def\n", + "/LT7 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 1 0.3 0 DL } def\n", + "/LT8 { PL [2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 2 dl 4 dl] 0.5 0.5 0.5 DL } def\n", + + /* Point (Round) */ /* Matt Heffron make it round */ + "/Pnt { stroke [] 0 setdash\n", + " gsave 1 setlinecap M 0 0 V stroke grestore } def\n", + + /* Diamond */ + "/Dia { stroke [] 0 setdash 2 copy vpt add M\n", + " hpt neg vpt neg V hpt vpt neg V\n", + " hpt vpt V hpt neg vpt V closepath stroke\n", + " Pnt } def\n", + + /* Plus */ + "/Pls { stroke [] 0 setdash vpt sub M 0 vpt2 V\n", + " currentpoint stroke M\n", + " hpt neg vpt neg R hpt2 0 V stroke\n", + " } def\n", + + /* Box */ + "/Box { stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M\n", + " 0 vpt2 neg V hpt2 0 V 0 vpt2 V\n", + " hpt2 neg 0 V closepath stroke\n", + " Pnt } def\n", + + /* Cross (X) */ + "/Crs { stroke [] 0 setdash exch hpt sub exch vpt add M\n", + " hpt2 vpt2 neg V currentpoint stroke M\n", + " hpt2 neg 0 R hpt2 vpt2 V stroke } def\n", + + /* Triangle Up*/ + "/TriU { stroke [] 0 setdash 2 copy vpt 1.12 mul add M\n", + " hpt neg vpt -1.62 mul V\n", + " hpt 2 mul 0 V\n", + " hpt neg vpt 1.62 mul V closepath stroke\n", + " Pnt } def\n", + + /* Star */ + "/Star { 2 copy Pls Crs } def\n", + + /* div added filed box */ + /* Filled Box */ + "/BoxF { stroke [] 0 setdash exch hpt sub exch vpt add M\n", + " 0 vpt2 neg V hpt2 0 V 0 vpt2 V\n", + " hpt2 neg 0 V closepath fill } def\n", + + /* div added filled triangle */ + /* Triangle Up, Filled */ + "/TriUF { stroke [] 0 setdash vpt 1.12 mul add M\n", + " hpt neg vpt -1.62 mul V\n", + " hpt 2 mul 0 V\n", + " hpt neg vpt 1.62 mul V closepath fill } def\n", + + /* Matt Heffron: added a few more types */ + /* Triangle Down */ + "/TriD { stroke [] 0 setdash 2 copy vpt 1.12 mul sub M\n", + " hpt neg vpt 1.62 mul V\n", + " hpt 2 mul 0 V\n", + " hpt neg vpt -1.62 mul V closepath stroke\n", + " Pnt } def\n", + + /* Triangle Down, Filled*/ + "/TriDF { stroke [] 0 setdash vpt 1.12 mul sub M\n", + " hpt neg vpt 1.62 mul V\n", + " hpt 2 mul 0 V\n", + " hpt neg vpt -1.62 mul V closepath fill} def\n", + + /* Diamond, Filled */ + "/DiaF { stroke [] 0 setdash vpt add M\n", + " hpt neg vpt neg V hpt vpt neg V\n", + " hpt vpt V hpt neg vpt V closepath fill } def\n", + + /* Pentagon */ + "/Pent { stroke [] 0 setdash 2 copy gsave\n", + " translate 0 hpt M 4 {72 rotate 0 hpt L} repeat\n", + " closepath stroke grestore Pnt } def\n", + + /* Pentagon, Filled */ + "/PentF { stroke [] 0 setdash gsave\n", + " translate 0 hpt M 4 {72 rotate 0 hpt L} repeat\n", + " closepath fill grestore } def\n", + + /* Circle */ + "/Circle { stroke [] 0 setdash 2 copy\n", + " hpt 0 360 arc stroke Pnt } def\n", + + /* Circle,Filled */ + "/CircleF { stroke [] 0 setdash hpt 0 360 arc fill } def\n", + + NULL + }; + + #define ENHPS_POINT_TYPES 15 /* Not counting "Pnt" itself */ + + /* added by Matt Heffron */ + struct ENHPS_FontName { + char *name; + struct ENHPS_FontName *next; + } *ENHPS_DocFonts = NULL; + + extern char *alloc(); + + char *ENHPS_RememberFont(fname) + char *fname; + { + struct ENHPS_FontName *fnp; + + for (fnp=ENHPS_DocFonts; fnp && strcmp(fnp->name, fname); fnp = fnp->next); + if (fnp) + return fnp->name; /* we must have found it in the list */ + + fnp = (struct ENHPS_FontName *)alloc(sizeof(struct ENHPS_FontName), "PostScript Font record"); + fnp->name = alloc(1+strlen(fname), "PostScript Font name"); + strcpy(fnp->name, fname); + fnp->next = ENHPS_DocFonts; + ENHPS_DocFonts = fnp; + return fnp->name; + } + + ENHPS_options() + { + extern struct value *const_express(); + extern double real(); + + if (!END_OF_COMMAND) { + if (almost_equals(c_token,"p$ortrait")) { + ps_portrait=TRUE; + ps_eps=FALSE; + c_token++; + } + else if (almost_equals(c_token,"l$andscape")) { + ps_portrait=FALSE; + ps_eps=FALSE; + c_token++; + } + else if (almost_equals(c_token,"e$psf")) { + ps_portrait=TRUE; + ps_eps = TRUE; + c_token++; + } + else if (almost_equals(c_token,"d$efault")) { + ps_portrait=FALSE; + ps_eps=FALSE; + ps_color=FALSE; + strcpy(ps_font,"Helvetica"); + ps_fontsize = 14; + term_tbl[term].v_char = (unsigned int)(ps_fontsize*PS_SC); + term_tbl[term].h_char = (unsigned int)(ps_fontsize*PS_SC*6/10); + c_token++; + } + } + + if (!END_OF_COMMAND) { + if (almost_equals(c_token,"m$onochrome")) { + ps_color=FALSE; + c_token++; + } + else if (almost_equals(c_token,"c$olor")) { + ps_color=TRUE; + c_token++; + } + } + /* enhpost changes the abbreviation point for solid/dashed + * to accomodate simplex/duplex */ + if (!END_OF_COMMAND) { + if (almost_equals(c_token,"so$lid")) { + ps_solid=TRUE; + c_token++; + } + else if (almost_equals(c_token,"da$shed")) { + ps_solid=FALSE; + c_token++; + } + } + + if (!END_OF_COMMAND) { + if (almost_equals(c_token,"si$mplex")) { + ENHps_duplex_state = FALSE; + ENHps_duplex_option = TRUE; + c_token++; + } + else if (almost_equals(c_token,"du$plex")) { + ENHps_duplex_state = TRUE; + ENHps_duplex_option = TRUE; + c_token++; + } + } + + if (!END_OF_COMMAND && isstring(c_token)) { + quote_str(ps_font,c_token); + c_token++; + } + + if (!END_OF_COMMAND) { + /* We have font size specified */ + struct value a; + ps_fontsize = (int)real(const_express(&a)); + term_tbl[term].v_char = (unsigned int)(ps_fontsize*PS_SC); + term_tbl[term].h_char = (unsigned int)(ps_fontsize*PS_SC*6/10); + } + + sprintf(term_options,"%s %s %s %s \"%s\" %d", + ps_eps ? "eps" : (ps_portrait ? "portrait" : "landscape"), + ps_color ? "color" : "monochrome", + ps_solid ? "solid" : "dashed", + ENHps_duplex_option ? (ENHps_duplex_state ? "duplex" : "simplex") + : "default-plex", + ps_font,ps_fontsize); + } + + + ENHPS_init() + { + static char GPFAR psi1[] = "%%%%Creator: gnuplot\n\ + %%%%DocumentFonts: (atend)\n\ + %%%%BoundingBox: %d %d "; + static char GPFAR psi2[] = "%%%%EndComments\n\ + /gnudict 50 dict def\ngnudict begin\n\ + /Color %s def\n\ + /Solid %s def\n\ + /gnulinewidth %.3f def\n\ + /vshift %d def\n\ + /dl {%d mul} def\n\ + /hpt %.1f def\n\ + /vpt %.1f def\n"; + + struct termentry *t = &term_tbl[term]; + int i; + ps_page = 0; + if (!ps_eps) + fprintf(outfile,"%%!PS-Adobe-2.0\n"); + else + fprintf(outfile,"%%!PS-Adobe-2.0 EPSF-2.0\n"); + (void)ENHPS_RememberFont(ps_font); + fprintf(outfile, psi1, PS_XOFF, PS_YOFF); + if (ps_portrait) + fprintf(outfile,"%d %d\n", + (int)(xsize*(ps_eps ? 0.5 : 1.0)*(PS_XMAX)/PS_SC+0.5+PS_XOFF), + (int)(ysize*(ps_eps ? 0.5 : 1.0)*(PS_YMAX)/PS_SC+0.5+PS_YOFF) ); + else + fprintf(outfile,"%d %d\n", + (int)(ysize*(ps_eps ? 0.5 : 1.0)*(PS_YMAX)/PS_SC+0.5+PS_XOFF), + (int)(xsize*(ps_eps ? 0.5 : 1.0)*(PS_XMAX)/PS_SC+0.5+PS_YOFF) ); + if (!ps_eps) + fprintf(outfile,"%%%%Pages: (atend)\n"); + fprintf(outfile, psi2, + ps_color ? "true" : "false", + ps_solid ? "true" : "false", + PS_LW, /* line width */ + (int)(t->v_char)/(-3), /* shift for vertical centring */ + PS_SC, /* dash length */ + PS_HTIC/2.0, /* half point width */ + PS_VTIC/2.0); /* half point height */ + + for ( i=0; ENHPS_header[i] != NULL; i++) + fprintf(outfile,"%s",ENHPS_header[i]); + if (ENHps_duplex_option) + fprintf(outfile, "statusdict begin %s setduplexmode end\n", + ENHps_duplex_state ? "true" : "false"); + fprintf(outfile,"end\n%%%%EndProlog\n"); + } + + + ENHPS_reset() + { + fprintf(outfile,"%%%%Trailer\n"); + fprintf(outfile,"%%%%DocumentFonts: "); + while (ENHPS_DocFonts) { + struct ENHPS_FontName *fnp; + fnp = ENHPS_DocFonts->next; + fprintf(outfile, "%s%s", ENHPS_DocFonts->name, fnp ? ", " : "\n"); + free(ENHPS_DocFonts->name); + free(ENHPS_DocFonts); + ENHPS_DocFonts=fnp; + } + + if (!ps_eps) + fprintf(outfile,"%%%%Pages: %d\n",ps_page); + } + + + /* postscript point routines */ + ENHPS_point(x,y,number) + int x,y; + int number; + { + static char *pointFNS[] = {"Pnt", "Pls", "Crs", "Star", + "Box", "BoxF", "Circle", "CircleF", + "TriU", "TriUF", "TriD", "TriDF", + "Dia", "DiaF", "Pent", "PentF"}; + number %= ENHPS_POINT_TYPES; + if (number < -1) + number = -1; /* negative types are all 'dot' */ + fprintf(outfile,"%d %d %s\n", x, y, pointFNS[number+1]); + PS_relative_ok = 0; + ps_path_count = 0; + PS_linetype_last = -1; /* force next linetype change */ + } + + /* take out comments to output debugging info */ + + #define ENHPS_DEBUG(x) /* printf x; */ + + static TBOOLEAN ENHps_opened_string; /* try to cut out empty ()'s */ + + /* used in determining height of processed text */ + + static float ENHps_max_height, ENHps_min_height; + + + /*{{{ static char *ENHPS_recurse(char *p, int brace, ... )*/ + /* process a bit of string, and return the last character used. + * p is start of string + * brace is TRUE to keep processing to }, FALSE for do one character + * fontname & fontsize are obvious + * base is the current baseline + * widthflag is TRUE if the width of this should count, + * FALSE for zero width boxes + */ + + extern double strtod(); + + static char *ENHPS_recurse(p, brace, fontname, fontsize, base, widthflag) + char *p, *fontname; + TBOOLEAN brace, widthflag; + float fontsize, base; + { + + /* close a postscript string if it has been opened */ + #define ENHPS_FLUSH \ + { if (ENHps_opened_string) \ + { fputs(")]\n", outfile); \ + ENHps_opened_string = FALSE; \ + } \ + } + + #define ENHPS_OPEN \ + { if (!ENHps_opened_string) \ + { fprintf(outfile, "[(%s) %.1f %.1f %s (", \ + fontname, fontsize, base, \ + widthflag ? "true" : "false"); \ + ENHps_opened_string = TRUE; \ + } \ + } + + ENHPS_DEBUG(("RECURSE WITH [%p] %s, %d %s %.1f %.1f %d\n", p, p, brace, fontname, fontsize, base, widthflag)) + + /* Start each recursion with a clean string */ + ENHPS_FLUSH + + if (base + fontsize > ENHps_max_height) + { ENHps_max_height = base + fontsize; + ENHPS_DEBUG(("Setting max height to %.1f\n", ENHps_max_height)); + } + + if (base < ENHps_min_height) + { ENHps_min_height = base; + ENHPS_DEBUG(("Setting min height to %.1f\n", ENHps_min_height)); + } + + for ( ; *p; ++p) + { float shift; + float f=0; /* used for getting new font size */ + char *localfontname, ch; + + /*{{{ look for 'special' characters - process then 'continue'*/ + switch (*p) + { + case '}' : + /*{{{ deal with it*/ + if (brace) + return (p); + + fprintf(stderr, "enhpost printer driver - spurious }\n"); + break; + /*}}}*/ + + case '_' : + case '^' : + /*{{{ deal with super/sub script*/ + + shift = (*p == '^') ? 0.5 : -0.3; + + ENHPS_FLUSH + + p = ENHPS_recurse(p+1, FALSE, fontname, fontsize*0.8, base+shift*fontsize, widthflag); + + break; + /*}}}*/ + + case '{' : + /*{{{ recurse (possibly with a new font) */ + ENHPS_DEBUG(("Dealing with {\n")) + + if (*++p == '/') + { /* then parse a fontname, optional fontsize */ + while (*++p == ' '); + localfontname = p; + while ((ch = *p) > ' ' && ch != '=') + ++p; + if (ch == '=') + { + *p++ = '\0'; + /*{{{ get optional font size*/ + ENHPS_DEBUG(("Calling strtod(%s) ...", p)) + f = (float)strtod(p, &p); + ENHPS_DEBUG(("Retured %.1f and %s\n", f, p)) + + if (f) + f *= PS_SC; /* remember the scaling */ + else + f = fontsize; + + ENHPS_DEBUG(("Font size %.1f\n", f)) + /*}}}*/ + } + else + { + *p++ = '\0'; + f = fontsize; + } + + while (*p == ' ') + ++p; + if (*localfontname) + localfontname = ENHPS_RememberFont(localfontname); + else + localfontname = fontname; + } + else + { + localfontname = fontname; + f = fontsize; + } + /*}}}*/ + + ENHPS_DEBUG(("Before recursing, we are at [%p] %s\n", p, p)) + + p = ENHPS_recurse(p, TRUE, localfontname, f, base, widthflag); + + ENHPS_DEBUG(("BACK WITH %s\n", p)); + + ENHPS_FLUSH + + break; + /*}}}*/ + + case '@' : + /*{{{ phantom box - prints next 'char', then restores currentpoint */ + + ENHPS_FLUSH + + p = ENHPS_recurse(++p, FALSE, fontname, fontsize, base, FALSE); + + break; + /*}}}*/ + + case '(' : + case ')' : + /*{{{ an escape and print it */ + /* special cases */ + ENHPS_OPEN + fputc('\\', outfile); + fputc(*p, outfile); + break; + /*}}}*/ + + case '\\' : + /*{{{ is it an escape */ + /* special cases */ + + if (p[1]=='\\' || p[1]=='(' || p[1]==')') + { + ENHPS_OPEN + fputc('\\', outfile); + } + else if ((ch = p[1]) >= '0' && ch <= '7') + { + /* up to 3 octal digits */ + ENHPS_OPEN + fputc('\\', outfile); + fputc(ch, outfile); + ++p; + if ((ch = p[1]) >= '0' && ch <= '7') + { + fputc(ch, outfile); + ++p; + if ((ch = p[1]) >= '0' && ch <= '7') + { + fputc(ch, outfile); + ++p; + } + } + break; + } + + ++p; + /* just go and print it (fall into the 'default' case) */ + + /*}}}*/ + default: + /*{{{ print it */ + ENHPS_OPEN + + fputc(*p, outfile); + + /*}}}*/ + + } + /*}}}*/ + + /* like TeX, we only do one character in a recursion, unless it's + * in braces + */ + + if (!brace) + { + ENHPS_FLUSH + return(p); /* the ++p in the outer copy will increment us */ + } + + } + ENHPS_FLUSH + return p; + } + /*}}}*/ + + /*{{{ ENHPS_put_text(x,y,str) */ + ENHPS_put_text(x, y, str) + unsigned int x, y; + char *str; + { + /* flush any pending graphics (all the XShow routines do this...) */ + + if (!strlen(str)) + return 0; + + if (ps_path_count) + { + fputs(" stroke\n",outfile); + ps_path_count=0; + PS_relative_ok=FALSE; + } + + PS_move(x,y); + + if (ps_ang != 0) + fprintf(outfile,"currentpoint gsave translate %d rotate 0 0 moveto\n", + ps_ang*90); + + fputs("[ ",outfile); + + /* set up the globals */ + + ENHps_opened_string = FALSE; + ENHps_max_height = -1000; + ENHps_min_height = 1000; + + while (*(str = ENHPS_recurse(str, TRUE, ps_font, + (float)term_tbl[term].v_char, + (float)0.0, TRUE))); + + ENHps_max_height += ENHps_min_height; + + fprintf(outfile, "] %.1f ", -ENHps_max_height/3); + + switch(ps_justify) + { + case LEFT : fprintf(outfile, "Lshow\n"); + break; + case CENTRE : fprintf(outfile, "Cshow\n"); + break; + case RIGHT : fprintf(outfile, "Rshow\n"); + break; + } + + if (ps_ang != 0) + fputs("grestore\n", outfile); + ps_path_count = 0; + PS_relative_ok=FALSE; + } + /*}}}*/ + + *** Distrib/command.c Mon Oct 25 13:55:01 1993 --- command.c Fri Nov 12 14:24:33 1993 *************** *** 364,373 **** static enum coord_type adjustlog(); extern TBOOLEAN interactive; /* from plot.c */ /* input data, parsing variables */ struct lexical_unit token[MAX_TOKENS]; ! char input_line[MAX_LINE_LEN + 1] = ""; int num_tokens, c_token; int inline_num = 0; /* input line number */ --- 364,375 ---- static enum coord_type adjustlog(); extern TBOOLEAN interactive; /* from plot.c */ + extern TBOOLEAN do_load_arg_substitution; /* [BII] for the 'call' command */ /* input data, parsing variables */ struct lexical_unit token[MAX_TOKENS]; ! char input_line[MAX_LINE_LEN + 2] = ""; /* processed by scanner, et. al. */ ! /* [BII] Change to "+2" above to handle some REALLY PATHALOGICAL cases :-) */ int num_tokens, c_token; int inline_num = 0; /* input line number */ *************** *** 608,617 **** int_error("expecting filename", c_token); else { quote_str(sv_file, c_token); ! load_file(fp=fopen(sv_file, "r"), sv_file); /* input_line[] and token[] now destroyed! */ c_token = num_tokens = 0; } } else if (almost_equals(c_token,"rer$ead")) { fp = lf_top(); if (fp != (FILE *)NULL) rewind(fp); --- 610,648 ---- int_error("expecting filename", c_token); else { quote_str(sv_file, c_token); ! load_file(fp=fopen(sv_file, "r"), sv_file, FALSE); /* [BII] This is NOT a 'call' */ /* input_line[] and token[] now destroyed! */ c_token = num_tokens = 0; } + /* [BII]+ check for 'call' command */ + } else if (almost_equals(c_token,"ca$ll")) { + if (!isstring(++c_token)) + int_error("expecting filename",c_token); + else { + quote_str(sv_file,c_token); + load_file(fopen(sv_file,"r"), sv_file, TRUE); /* Argument list follows filename */ + /* input_line[] and token[] now destroyed! */ + c_token = num_tokens = 0; + } + /* [BII]- */ + /* [BII]+ check for 'if' command */ + } else if (almost_equals(c_token,"if")) { + float exprval; + struct value t; + if (!equals(++c_token, "(")) /* no expression */ + int_error("expecting (expression)", c_token); + exprval = real(const_express(&t)); + if (exprval != 0.0) { + /* fake the condition of a ';' between commands */ + int eolpos = token[num_tokens-1].start_index+token[num_tokens-1].length; + --c_token; + token[c_token].length = 1; + token[c_token].start_index = eolpos+2; + input_line[eolpos+2] = ';'; + input_line[eolpos+3] = '\0'; + } else + c_token = num_tokens = 0; + /* [BII]- */ } else if (almost_equals(c_token,"rer$ead")) { fp = lf_top(); if (fp != (FILE *)NULL) rewind(fp); *** Distrib/docs/gnuplot.doc Mon Oct 25 13:56:48 1993 --- docs/gnuplot.doc Thu Nov 18 19:14:58 1993 *************** *** 719,724 **** --- 719,753 ---- request. After that subtopic has been printed, the request may be extended again, or simply pressing return goes back one level to the previous topic. Eventually, the GNUPLOT command line will return. + 2 if + ?if + The `if` command allows commands to be executed conditionally. + + Syntax: + + if () + + The will be evaluated, if it is true (non-zero), then + the command(s) of the will be executed. If the + is false (equals zero), then the entire + is ignored. Note that use of ';' to allow multiple commands on the + same line will NOT end the conditionalized commands. + + Examples: + + pi=3 + if (pi!=acos(-1)) pause 0 "?Fixing pi!";pi=acos(-1);show variables + + will display: + + ?Fixing pi! + + Variables: + pi = 3.14159 + or + if (1==2) pause 0 "Never see this";pause 0 "Or this either" + + will not display anything. 2 load ?load The `load` command executes each line of the specified input file as *************** *** 725,732 **** if it had been typed in interactively. Files created by the `save` command can later be `load`ed. Any text file containing valid commands can be created and then executed by the `load` command. ! Files being `load`ed may themselves contain `load` commands. See ! `comment` for information about comments in commands. The `load` command must be the last command on the line. --- 754,761 ---- if it had been typed in interactively. Files created by the `save` command can later be `load`ed. Any text file containing valid commands can be created and then executed by the `load` command. ! Files being `load`ed may themselves contain `load` (or `call`) commands. ! See `comment` for information about comments in commands. The `load` command must be the last command on the line. *************** *** 743,748 **** --- 772,813 ---- The `load` command is performed implicitly on any file names given as arguments to GNUPLOT. These are loaded in the order specified, and then GNUPLOT exits. + 2 call + ?call + The `call` command is identical to the load command with one exception: + you can have up to 10 additional parameters to the command (delimited + according to the standard parser rules) which can be substituted into + the lines read from the file. As each line is read from the `call`ed + input-file it is scanned for the sequence `$` (dollar-sign) followed by + a digit (0-9). If found, the sequence is replaced by the corresponding + parameter from the `call` command line. If the parameter was specified + as a string in the `call` line, it is substituted without its enclosing + quotes. `$` followed by any character other than a digit will be that + character. (E.g. use `$$` to get a single `$`.) Providing more than + 10 parameters on the `call` command line will cause an error. + A parameter that was not provided, substitutes as nothing. + Files being `call`ed may themselves contain `call` or `load` commands. + + The `call` command must be the last command on the line. + + Syntax: + call "" ... + + The name of the input file must be enclosed in quotes. + + Examples: + + if the file 'calltest.gp' contains the line: + + pause 0 "p0=$0 p1=$1 p2=$2 p3=$3 p4=$4 p5=$5 p6=$6 p7=x$7x" + + entering the command: + + call 'calltest.gp' "abcd" 1.2 + "'quoted'" -- "$2" + + will display: + + p0=abcd p1=1.2 p2=+ p3='quoted' p4=- p5=- p6=$2 p7=xx 2 pause ?pause The `pause` command displays any text associated with the command and *************** *** 2746,2751 **** --- 2811,2892 ---- set size 0.7,1.4 set term post portrait color "Times-Roman" 14 + 4 enhanced postscript + ?set terminal enhpost + ?enhanced postscript + ?enhanced + ?enhpost + The "Enhanced PostScript" driver has extended capabilities + beyond the regular PostScript driver. Several options may be + set in the Enhanced PostScript driver. + + Syntax: + set terminal enhpost {} {} {} + {} {""} {} + + where is `landscape`, `portrait`, `eps` or `default`. + Selecting default sets all options to their defaults. + is either `color` or `monochrome`. + is either `solid` or `dashed`. + is either `simplex` or `duplex` (don't set this if your printer can't do it). + "" is the name of a valid PostScript font. + is the size of the font in PostScript points. + Defaults are `landscape`, `monochrome`, `dashed`, 'printer-default-plex', + "Helvetica", and 14pt. + Default size of Enhanced PostScript plot is landscape mode 10 inches wide + and 7 inches high. + + To get EPS output, use the `eps` mode and make only one plot per file. + In `eps` mode the whole plot is halved in size; the fonts are half the + given size, and the plot is 5 inches wide and 3.5 inches high. + + Examples: + + set term enhpost landscape 22 + set term enhpost eps 14 + set term enhpost landscape simplex + set size 0.7,1.4 + set term enhpost portrait color "Times-Roman" 14 + + This "enhanced" driver allows any text to contain the following special + formatting instructions (e.g., use the SET FORMAT command to put them in + for axis scales): + + @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) + #\multicolumn{3}{|c|}{Enhanced Text Control Codes} \\ + #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)\\ + %.TE + %.TS + %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) + @end table + + {text} can be used to allow multiple-character text, where only a single + character is expected (e.g., 2^{10}). To change the font and/or size, use + the full form: {/[fontname][=fontsize] text} (For example, + {/Symbol=20 G} is a 20 point GAMMA). (The '/' character MUST be the first + character after the '{'.) + + The phantom box is useful for a@^b_c to align superscript and subscript, + and for overwriting an accent on a letter. + It is common sense to put the shorter of the two in the phantom box. + + You can access special symbols numerically by specifying + \character-code (in octal), e.g., {/Symbol \245} is infinity. + + You can escape control characters using \, e.g., \\, \{, \}, \^, \@ 4 regis ?set terminal regis ?table *** Distrib/misc.c Mon Oct 25 13:59:40 1993 --- misc.c Mon Oct 25 14:39:34 1993 *************** *** 65,70 **** --- 65,71 ---- #endif extern int c_token; + extern int num_tokens; /* [BII] for 'call' processing */ extern char replot_line[]; extern struct at_type at; extern struct ft_entry ft[]; *************** *** 74,79 **** --- 75,84 ---- extern struct at_type *temp_at(); extern TBOOLEAN interactive; + /* [BII]+ these two could be in load_file, except for error recovery */ + extern TBOOLEAN do_load_arg_substitution; + extern char *call_args[10]; + /* [BII]- */ extern char *infile_name; extern int inline_num; *************** *** 85,92 **** --- 90,99 ---- FILE *fp; /* file pointer for load file */ char *name; /* name of file */ TBOOLEAN interactive; /* value of interactive flag on entry */ + TBOOLEAN do_load_arg_substitution; /* [BII] likewise ... */ int inline_num; /* inline_num on entry */ LFS *prev; /* defines a stack */ + char *call_args[10]; /* [BII] args when file is 'call'ed instead of 'load'ed */ } *lf_head = NULL; /* NULL if not in load_file */ static TBOOLEAN lf_pop(); *************** *** 726,737 **** } } ! load_file(fp, name) FILE *fp; char *name; { register int len; extern char input_line[]; int start, left; int more; --- 733,746 ---- } } ! load_file(fp, name, can_do_args) /* [BII] add third argument for 'call' command */ FILE *fp; char *name; + TBOOLEAN can_do_args; /* [BII] its a flag */ { register int len; extern char input_line[]; + char raw_input_line[MAX_LINE_LEN+1]; /* [BII] the un-substituted line from the file */ int start, left; int more; *************** *** 738,747 **** int stop = FALSE; lf_push(fp); /* save state for errors and recursion */ if (fp == (FILE *)NULL) { char errbuf[BUFSIZ]; ! (void) sprintf(errbuf, "Cannot open load file '%s'", name); os_error(errbuf, c_token); } else { /* go into non-interactive mode during load */ --- 747,758 ---- int stop = FALSE; lf_push(fp); /* save state for errors and recursion */ + do_load_arg_substitution = can_do_args; /* [BII] more state */ if (fp == (FILE *)NULL) { char errbuf[BUFSIZ]; ! (void) sprintf(errbuf, can_do_args ? "Cannot open call file '%s'" /* [BII] correct error message */ ! : "Cannot open load file '%s'", name); os_error(errbuf, c_token); } else { /* go into non-interactive mode during load */ *************** *** 750,755 **** --- 761,777 ---- inline_num = 0; infile_name = name; + if (can_do_args) { + int aix = 0; + while (++c_token < num_tokens && aix <= 9) { + if (isstring(c_token)) + m_quote_capture(&call_args[aix++], c_token, c_token); + else + m_capture(&call_args[aix++], c_token, c_token); + } + if (c_token >= num_tokens && aix > 9) + int_error("too many arguments for CALL ", ++c_token); + } while (!stop) { /* read all commands in file */ /* read one command */ left = MAX_LINE_LEN; *************** *** 757,777 **** more = TRUE; while (more) { ! if (fgets(&(input_line[start]), left, fp) == (char *)NULL) { stop = TRUE; /* EOF in file */ ! input_line[start] = '\0'; more = FALSE; } else { inline_num++; ! len = strlen(input_line) - 1; ! if (input_line[len] == '\n') { /* remove any newline */ ! input_line[len] = '\0'; /* Look, len was 1-1 = 0 before, take care here! */ if (len > 0) --len; } else if (len+1 >= left) int_error("Input line too long",NO_CARET); ! if (input_line[len] == '\\') { /* line continuation */ start = len; left = MAX_LINE_LEN - start; /* left -=len;*/ } else --- 779,799 ---- more = TRUE; while (more) { ! if (fgets(&(raw_input_line[start]), left, fp) == (char *)NULL) { /* [BII] use raw_input_line */ stop = TRUE; /* EOF in file */ ! raw_input_line[start] = '\0'; /* [BII] use raw_input_line */ more = FALSE; } else { inline_num++; ! len = strlen(raw_input_line) - 1; /* [BII] use raw_input_line */ ! if (raw_input_line[len] == '\n') { /* remove any newline */ /* [BII] use raw_input_line */ ! raw_input_line[len] = '\0'; /* [BII] use raw_input_line */ /* Look, len was 1-1 = 0 before, take care here! */ if (len > 0) --len; } else if (len+1 >= left) int_error("Input line too long",NO_CARET); ! if (raw_input_line[len] == '\\') { /* line continuation */ /* [BII] use raw_input_line */ start = len; left = MAX_LINE_LEN - start; /* left -=len;*/ } else *************** *** 779,785 **** } } ! if (strlen(input_line) > 0) { screen_ok = FALSE; /* make sure command line is echoed on error */ do_line(); --- 801,842 ---- } } ! if (strlen(raw_input_line) > 0) { ! if (can_do_args) { /* [BII]+ substitute the args */ ! register char * ril = raw_input_line; ! register char * il = input_line; ! for (left = MAX_LINE_LEN; *ril; ril++) { ! register int aix; ! if (left <= 0) { ! *il = '\0'; ! int_error("rest of line overflowed during argument substitution", ! NO_CARET); ! } ! if (*ril == '$' && ! (aix = *(++ril)) && ! aix >= '0' && ! aix <= '9') { ! if (call_args[aix -= '0']) { ! if (left < (len = strlen(call_args[aix]))) { ! *(il++) = '$'; ! *(il++) = *ril; ! *il = '\0'; ! int_error("argument substitution overflowed rest of line", ! NO_CARET); ! } ! strcpy(il, call_args[aix]); ! il += len; ! } ! } else { ! /* substitute for $ here */ ! *(il++) = *ril; ! left--; ! } ! } ! *il = '\0'; ! } else { ! strcpy(input_line, raw_input_line); ! } /* [BII]- */ screen_ok = FALSE; /* make sure command line is echoed on error */ do_line(); *************** *** 800,808 **** --- 857,873 ---- if (lf_head == NULL) return(FALSE); else { + int argindex; /* [BII] for freeing the args */ lf = lf_head; if (lf->fp != (FILE *)NULL) (void) fclose(lf->fp); + for (argindex = 0; argindex < 10; argindex++) { /* [BII]+ free the args */ + if (call_args[argindex]) { + free(call_args[argindex]); + } + call_args[argindex] = lf->call_args[argindex]; + } + do_load_arg_substitution = lf->do_load_arg_substitution; /* [BII]- */ interactive = lf->interactive; inline_num = lf->inline_num; infile_name = lf->name; *************** *** 819,824 **** --- 884,890 ---- FILE *fp; { LFS *lf; + int argindex; /* [BII] for saving the arg strings */ lf = (LFS *)alloc((unsigned long)sizeof(LFS), (char *)NULL); if (lf == (LFS *)NULL) { *************** *** 831,836 **** --- 897,907 ---- lf->name = infile_name; /* save current name */ lf->interactive = interactive; /* save current state */ lf->inline_num = inline_num; /* save current line number */ + lf->do_load_arg_substitution = do_load_arg_substitution; /* [BII]+ save state and args */ + for (argindex = 0; argindex < 10; argindex++) { + lf->call_args[argindex] = call_args[argindex]; + call_args[argindex] = NULL; /* initially no args */ + } /* [BII]- */ lf->prev = lf_head; /* link to stack */ lf_head = lf; } *** Distrib/plot.c Mon Oct 25 14:39:46 1993 --- plot.c Mon Oct 25 14:43:51 1993 *************** *** 95,100 **** --- 95,106 ---- TBOOLEAN interactive = TRUE; /* FALSE if stdin not a terminal */ TBOOLEAN noinputfiles = TRUE; /* FALSE if there are script files */ + + /* [BII]+ these 2 could be in misc.c, but are here with all the other globals */ + TBOOLEAN do_load_arg_substitution = FALSE; + char *call_args[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + /* [BII]- */ + char *infile_name = NULL; /* name of command file; NULL if terminal */ #ifndef STDOUT *************** *** 366,372 **** while (--argc > 0) { ++argv; c_token = NO_CARET; /* in case of file not found */ ! load_file(fopen(*argv,"r"), *argv); } } else { /* take commands from stdin */ --- 372,378 ---- while (--argc > 0) { ++argv; c_token = NO_CARET; /* in case of file not found */ ! load_file(fopen(*argv,"r"), *argv, FALSE); /* [BII] command line files are 'load' not 'call' */ } } else { /* take commands from stdin */ *************** *** 489,493 **** #endif } if (plotrc) ! load_file(plotrc, rcfile); } --- 495,499 ---- #endif } if (plotrc) ! load_file(plotrc, rcfile, FALSE); /* [BII] the rcfile is 'load'ed not 'call'ed */ } *** Distrib/term.c Wed Oct 27 20:10:14 1993 --- term.c Thu Nov 4 09:38:41 1993 *************** *** 468,473 **** --- 468,474 ---- #ifdef POSTSCRIPT /* POSTSCRIPT type */ #include "term/post.trm" + #include "term/enhpost.trm" #endif #ifdef PRESCRIBE /* PRESCRIBE type */ *************** *** 1280,1287 **** PS_text, null_scale, PS_graphics, PS_move, PS_vector, PS_linetype, PS_put_text, PS_text_angle, PS_justify_text, PS_point, do_arrow} - #endif #ifdef PRESCRIBE ,{"prescribe", "Prescribe - for the Kyocera Laser Printer", PRE_XMAX, PRE_YMAX, PRE_VCHAR, PRE_HCHAR, --- 1281,1306 ---- PS_text, null_scale, PS_graphics, PS_move, PS_vector, PS_linetype, PS_put_text, PS_text_angle, PS_justify_text, PS_point, do_arrow} + /* You can't have these unless you also have POSTSCRIPT */ + ,{"enhpost", "Enhanced PostScript graphics language support [mode \042fontname\042 font_size]", + PS_XMAX, PS_YMAX, PS_VCHAR, PS_HCHAR, + PS_VTIC, PS_HTIC, ENHPS_options, ENHPS_init, ENHPS_reset, + PS_text, null_scale, PS_graphics, PS_move, PS_vector, + PS_linetype, ENHPS_put_text, PS_text_angle, + PS_justify_text, ENHPS_point, do_arrow} + + # ifdef PSLATEX + ,{"pslatex", "LaTeX picture environment with PostScript \\specials", + PS_XMAX, PS_YMAX, PSLATEX_VCHAR, PSLATEX_HCHAR, + PS_VTIC, PS_HTIC, PSLATEX_options, PSLATEX_init, PSLATEX_reset, + PSLATEX_text, PSLATEX_scale, PSLATEX_graphics, PS_move, PS_vector, + PS_linetype, PSLATEX_put_text, PSLATEX_text_angle, + PSLATEX_justify_text, PS_point, do_arrow} + # endif + + #endif /* POSTSCRIPT */ + #ifdef PRESCRIBE ,{"prescribe", "Prescribe - for the Kyocera Laser Printer", PRE_XMAX, PRE_YMAX, PRE_VCHAR, PRE_HCHAR, *************** *** 1296,1310 **** PRE_linetype, PRE_put_text, null_text_angle, PRE_justify_text, line_and_point, do_arrow} #endif /* PRESCRIBE */ - - #ifdef PSLATEX - ,{"pslatex", "LaTeX picture environment with PostScript \\specials", - PS_XMAX, PS_YMAX, PSLATEX_VCHAR, PSLATEX_HCHAR, - PS_VTIC, PS_HTIC, PSLATEX_options, PSLATEX_init, PSLATEX_reset, - PSLATEX_text, PSLATEX_scale, PSLATEX_graphics, PS_move, PS_vector, - PS_linetype, PSLATEX_put_text, PSLATEX_text_angle, - PSLATEX_justify_text, PS_point, do_arrow} - #endif #ifdef PSTRICKS ,{"pstricks", "LaTeX picture environment with PSTricks macros", --- 1315,1320 ----