summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/dospecial.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/dvipsk/dospecial.c
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipsk/dospecial.c')
-rw-r--r--Build/source/texk/dvipsk/dospecial.c962
1 files changed, 962 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/dospecial.c b/Build/source/texk/dvipsk/dospecial.c
new file mode 100644
index 00000000000..34e0dacdcb1
--- /dev/null
+++ b/Build/source/texk/dvipsk/dospecial.c
@@ -0,0 +1,962 @@
+/*
+ * This routine handles special commands;
+ * predospecial() is for the prescan, dospecial() for the real thing.
+ */
+#include "dvips.h" /* The copyright notice in that file is included too! */
+
+#ifdef KPATHSEA
+#include <kpathsea/c-ctype.h>
+#include <kpathsea/tex-hush.h>
+#else /* ! KPATHSEA */
+#include <ctype.h>
+#include <stdlib.h>
+#ifndef WIN32
+extern int atoi();
+extern int system();
+#endif /* WIN32*/
+#endif
+/*
+ * These are the external routines called:
+ */
+/**/
+#include "protos.h"
+
+/* IBM: color - end */
+#ifdef HPS
+extern Boolean PAGEUS_INTERUPPTUS ;
+extern integer HREF_COUNT ;
+extern Boolean NEED_NEW_BOX ;
+extern Boolean HPS_FLAG ;
+#endif
+extern char errbuf[] ;
+extern shalfword linepos;
+extern Boolean usesspecial ;
+extern Boolean usescolor ; /* IBM: color */
+extern int landscape ;
+extern char *paperfmt ;
+extern char *nextstring;
+extern char *maxstring;
+extern char *oname;
+extern FILE *bitfile;
+extern int quiet;
+extern fontdesctype *curfnt ;
+extern int actualdpi ;
+extern int vactualdpi ;
+extern integer hh, vv;
+extern int lastfont ;
+extern real conv ;
+extern real vconv ;
+extern integer hpapersize, vpapersize ;
+extern Boolean pprescan ;
+#ifndef KPATHSEA
+extern char *figpath ;
+#endif
+extern int prettycolumn ;
+extern Boolean disablecomments ;
+
+#ifdef DEBUG
+extern integer debug_flag;
+#endif
+
+static int specialerrors = 20 ;
+
+struct bangspecial {
+ struct bangspecial *next ;
+ char actualstuff[1] ; /* more space will actually be allocated */
+} *bangspecials = NULL ;
+
+void specerror P1C(char *, s)
+{
+ if (specialerrors > 0
+#ifdef KPATHSEA
+ && !kpse_tex_hush ("special")
+#endif
+ ) {
+ error(s) ;
+ specialerrors-- ;
+ } else if (specialerrors == 0
+#ifdef KPATHSEA
+ && !kpse_tex_hush ("special")
+#endif
+ ) {
+ error("more errors in special, being ignored . . .") ;
+ error("(perhaps dvips doesn't support your macro package?)");
+ specialerrors-- ;
+ }
+}
+
+static void trytobreakout P1C(register char *, p)
+{
+ register int i ;
+ register int instring = 0 ;
+ int lastc = 0 ;
+
+ i = 0 ;
+ (void)putc('\n', bitfile) ;
+ while (*p) {
+ if (i > 65 && *p == ' ' && instring == 0) {
+ (void)putc('\n', bitfile) ;
+ i = 0 ;
+ } else {
+ (void)putc(*p, bitfile) ;
+ i++ ;
+ }
+ if (*p == '(' && lastc != '\\')
+ instring = 1 ;
+ else if (*p == ')' && lastc != '\\')
+ instring = 0 ;
+ lastc = *p ;
+ p++ ;
+ }
+ (void)putc('\n', bitfile) ;
+}
+
+static void dobs P1C(register struct bangspecial *, q)
+{
+ if (q) {
+ dobs(q->next) ;
+ trytobreakout(q->actualstuff) ;
+ }
+}
+
+void
+outbangspecials P1H(void) {
+ if (bangspecials) {
+ cmdout("TeXDict") ;
+ cmdout("begin") ;
+ cmdout("@defspecial\n") ;
+ dobs(bangspecials) ;
+ cmdout("\n@fedspecial") ;
+ cmdout("end") ;
+ }
+}
+
+/* We recommend that new specials be handled by the following general
+ * (and extensible) scheme, in which the user specifies one or more
+ * `key=value' pairs separated by spaces.
+ * The known keys are given in KeyTab; they take values
+ * of one of the following types:
+ *
+ * None: no value, just a keyword (in which case the = sign is omitted)
+ * String: the value should be "<string without double-quotes"
+ * or '<string without single-quotes'
+ * Integer: the value should be a decimal integer (%d format)
+ * Number: the value should be a decimal integer or real (%f format)
+ * Dimension: like Number, but will be multiplied by the scaledsize
+ * of the current font and converted to default PostScript units
+ * (Actually, strings are allowed in all cases; the delimiting quotes
+ * are simply stripped off if present.)
+ *
+ */
+
+typedef enum {None, String, Integer, Number, Dimension} ValTyp;
+typedef struct {
+ char *Entry;
+ ValTyp Type;
+} KeyDesc;
+
+#define NKEYS (sizeof(KeyTab)/sizeof(KeyTab[0]))
+
+KeyDesc KeyTab[] = {{"psfile", String}, /* j==0 in the routine below */
+ {"ifffile", String}, /* j==1 */
+ {"tekfile", String}, /* j==2 */
+ {"hsize", Number},
+ {"vsize", Number},
+ {"hoffset", Number},
+ {"voffset", Number},
+ {"hscale", Number},
+ {"vscale", Number},
+ {"angle", Number},
+ {"llx", Number},
+ {"lly", Number},
+ {"urx", Number},
+ {"ury", Number},
+ {"rwi", Number},
+ {"rhi", Number},
+ {"clip", None}};
+
+#ifndef KPATHSEA
+#define TOLOWER Tolower
+#ifdef VMS
+#ifndef __GNUC__ /* GNUC tolower is too simple */
+#define Tolower tolower
+#endif
+#else
+#ifdef VMCMS /* IBM: VM/CMS */
+#define Tolower __tolower
+#else
+#ifdef MVSXA /* IBM: MVS/XA */
+#define Tolower __tolower
+#else
+/*
+ * compare strings, ignore case
+ */
+char Tolower P1C(register char, c)
+{
+ if ('A' <= c && c <= 'Z')
+ return(c+32) ;
+ else
+ return(c) ;
+}
+#endif
+#endif /* IBM: VM/CMS */
+#endif
+#endif /* !KPATHSEA */
+int IsSame P2C(char *, a, char *, b)
+{
+ for( ; *a != '\0'; ) {
+ if( TOLOWER(*a) != TOLOWER(*b) )
+ return( 0 );
+ a++ ;
+ b++ ;
+ }
+ return( *b == '\0' );
+}
+
+char *KeyStr, *ValStr ; /* Key and String values found */
+long ValInt ; /* Integer value found */
+float ValNum ; /* Number or Dimension value found */
+
+char *GetKeyVal P2C(char *, str, int *, tno) /* returns NULL if none found, else next scan point */
+ /* str : starting point for scan */
+ /* tno : table entry number of keyword, or -1 if keyword not found */
+{
+ register char *s ;
+ register int i ;
+ register char t ;
+
+ for (s=str; *s <= ' ' && *s; s++) ; /* skip over blanks */
+ if (*s == '\0')
+ return (NULL) ;
+ KeyStr = s ;
+ while (*s>' ' && *s!='=') s++ ;
+ if (0 != (t = *s))
+ *s++ = 0 ;
+
+ for(i=0; i<NKEYS; i++)
+ if( IsSame(KeyStr, KeyTab[i].Entry) )
+ goto found ;
+ *tno = -1;
+ return (s) ;
+
+found: *tno = i ;
+ if (KeyTab[i].Type == None)
+ return (s) ;
+
+ if (t && t <= ' ') {
+ for (; *s <= ' ' && *s; s++) ; /* now look for the value part */
+ if ((t = *s)=='=')
+ s++ ;
+ }
+ ValStr = "" ;
+ if ( t == '=' ) {
+ while (*s <= ' ' && *s)
+ s++ ;
+ if (*s=='\'' || *s=='\"')
+ t = *s++ ; /* get string delimiter */
+ else t = ' ' ;
+ ValStr = s ;
+ while (*s!=t && *s)
+ s++ ;
+ if (*s)
+ *s++ = 0 ;
+ }
+ switch (KeyTab[i].Type) {
+ case Integer:
+ if(sscanf(ValStr,"%ld",&ValInt)!=1) {
+ sprintf(errbuf,"Non-integer value (%s) given for keyword %s",
+ ValStr, KeyStr) ;
+ specerror(errbuf) ;
+ ValInt = 0 ;
+ }
+ break ;
+ case Number:
+ case Dimension:
+ if(sscanf(ValStr,"%f",&ValNum)!=1) {
+ sprintf(errbuf,"Non-numeric value (%s) given for keyword %s",
+ ValStr, KeyStr) ;
+ specerror(errbuf) ;
+ ValNum = 0.0 ;
+ }
+ if (KeyTab[i].Type==Dimension) {
+ if (curfnt==NULL)
+ error("! No font selected") ;
+ ValNum = ValNum * ((double)curfnt->scaledsize) * conv * 72 / DPI ;
+ }
+ break ;
+ default: break ;
+ }
+ return (s) ;
+}
+
+/*
+ * Now our routines. We get the number of bytes specified and place them
+ * into the string buffer, and then parse it. Numerous conventions are
+ * supported here for historical reasons.
+ *
+ * To support GNUplot's horribly long specials, we go ahead and malloc a
+ * new string buffer if necessary.
+ */
+
+void predospecial P2C(integer, numbytes, Boolean, scanning)
+{
+ register char *p = nextstring ;
+ register int i = 0 ;
+ int j ;
+ static int omega_specials = 0;
+
+ if (nextstring + numbytes > maxstring) {
+ p = nextstring = mymalloc(1000 + 2 * numbytes) ;
+ maxstring = nextstring + 2 * numbytes + 700 ;
+ }
+ for (i=numbytes; i>0; i--)
+#ifdef VMCMS /* IBM: VM/CMS */
+ *p++ = ascii2ebcdic[(char)dvibyte()] ;
+#else
+#ifdef MVSXA /* IBM: MVS/XA */
+ *p++ = ascii2ebcdic[(char)dvibyte()] ;
+#else
+ *p++ = (char)dvibyte() ;
+#endif /* IBM: VM/CMS */
+#endif
+ if (pprescan)
+ return ;
+ while (p[-1] <= ' ' && p > nextstring)
+ p-- ; /* trim trailing blanks */
+ if (p==nextstring) return ; /* all blank is no-op */
+ *p = 0 ;
+ p = nextstring ;
+ while (*p <= ' ')
+ p++ ;
+#ifdef DEBUG
+ if (dd(D_SPECIAL))
+ (void)fprintf(stderr, "Preprocessing special: %s\n", p) ;
+#endif
+
+/*
+ * We use strncmp() here to also pass things like landscape()
+ * or landscape: or such.
+ */
+
+ switch (*p) {
+case 'o':
+ if (strncmp(p, "om:", 3)==0) { /* Omega specials ignored */
+ if (omega_specials==0) {
+ fprintf(stderr, "Omega specials are currently ignored\n");
+ omega_specials++;
+ }
+ return;
+ }
+ break ;
+case 'l':
+ if (strncmp(p, "landscape", 9)==0) {
+ if (hpapersize || vpapersize)
+ error(
+ "both landscape and papersize specified: ignoring landscape") ;
+ else
+ landscape = 1 ;
+ return ;
+ }
+ break ;
+case 'p':
+ if (strncmp(p, "pos:", 4)==0) return ; /* positional specials */
+ if (strncmp(p, "papersize", 9)==0) {
+ p += 9 ;
+ while (*p == '=' || *p == ' ')
+ p++ ;
+ if (hpapersize == 0 || vpapersize == 0) {
+ if (landscape) {
+ error(
+ "both landscape and papersize specified: ignoring landscape") ;
+ landscape = 0 ;
+ }
+ handlepapersize(p, &hpapersize, &vpapersize) ;
+ }
+ return ;
+ }
+ break ;
+case 'x':
+ if (strncmp(p, "xtex:", 5)==0) return ;
+ break ;
+case 's':
+ if (strncmp(p, "src:", 4)==0) return ; /* source specials */
+ break ;
+
+case 'h':
+ if (strncmp(p, "header", 6)==0) {
+ char *q, *r, *pre = NULL, *post = NULL ;
+ p += 6 ;
+ while ((*p <= ' ' || *p == '=' || *p == '(') && *p != 0)
+ p++ ;
+ if(*p == '{') {
+ p++;
+ while ((*p <= ' ' || *p == '=' || *p == '(') && *p != 0)
+ p++;
+ q = p ;
+ while (*p != '}' && *p != 0)
+ p++;
+ r = p-1 ;
+ while ((*r <= ' ' || *r == ')') && r >= q)
+ r-- ;
+ if (*p != 0) p++ ;
+ r[1] = 0 ; /* q is the file name */
+ while ((*p <= ' ' || *p == '=' || *p == '(') && *p != 0)
+ p++ ;
+ if(strncmp(p, "pre", 3) == 0) {
+ int bracecount = 1, numbytes = 0, j ;
+ while(*p != '{' && *p != 0)
+ p++ ;
+ if (*p != 0) p++;
+ for(r = p; *r != 0; r++) {
+ if (*r == '{') bracecount++ ;
+ else if (*r == '}') bracecount-- ;
+ if (bracecount == 0) break ;
+ numbytes++ ;
+ }
+ pre = (char *)malloc(numbytes+1);
+ r = pre ;
+ for (j=0; j < numbytes; j++)
+ *r++ = *p++;
+ *r = 0;
+ if (*p != 0) p++;
+ }
+ while ((*p <= ' ' || *p == '=' || *p == '(') && *p != 0)
+ p++ ;
+ if(strncmp(p, "post", 4) == 0) {
+ int bracecount = 1, numbytes = 0, j ;
+ while(*p != '{' && *p != 0)
+ p++ ;
+ if (*p != 0) p++;
+ for(r = p; *r != 0; r++) {
+ if (*r == '{') bracecount++ ;
+ else if (*r == '}') bracecount-- ;
+ if (bracecount == 0) break ;
+ numbytes++ ;
+ }
+ post = (char *)malloc(numbytes+1);
+ r = post ;
+ for (j=0; j < numbytes; j++)
+ *r++ = *p++;
+ *r = 0;
+ }
+ if (strlen(q) > 0)
+ (void)add_header_general(q, pre, post) ;
+ } else {
+ q = p ; /* we will remove enclosing parentheses */
+ p = p + strlen(p) - 1 ;
+ while ((*p <= ' ' || *p == ')') && p >= q)
+ p-- ;
+ p[1] = 0 ;
+ if (p >= q)
+ (void)add_header(q) ;
+ }
+ }
+ break ;
+/* IBM: color - added section here for color header and color history */
+/* using strncmp in this fashion isn't perfect; if later someone wants
+ to introduce a verb like colorspace, well, just checking
+ strcmp(p, "color", 5) will not do. But we leave it alone for the moment.
+ --tgr */
+case 'b':
+ if (strncmp(p, "background", 10) == 0) {
+ usescolor = 1 ;
+ p += 10 ;
+ while ( *p && *p <= ' ' ) p++ ;
+ background(p) ;
+ return ;
+ }
+ break ;
+case 'c':
+ if (strncmp(p, "color", 5) == 0) {
+ usescolor = 1 ;
+ p += 5 ;
+ while ( *p && *p <= ' ' ) p++ ;
+ if (strncmp(p, "push", 4) == 0 ) {
+ p += 4 ;
+ while ( *p && *p <= ' ' ) p++ ;
+ pushcolor(p, 0) ;
+ } else if (strncmp(p, "pop", 3) == 0 ) {
+ popcolor(0) ;
+ } else {
+ resetcolorstack(p,0) ;
+ }
+ } /* IBM: color - end changes */
+ break ;
+case '!':
+ {
+ register struct bangspecial *q ;
+ p++ ;
+ q = (struct bangspecial *)mymalloc((integer)
+ (sizeof(struct bangspecial) + strlen(p))) ;
+ (void)strcpy(q->actualstuff, p) ;
+ q->next = bangspecials ;
+ bangspecials = q ;
+ usesspecial = 1 ;
+ return ;
+ }
+ break ;
+default:
+#if 0
+ {
+ /* Unknown special, must return */
+ return;
+ }
+#endif
+ break ;
+ }
+ usesspecial = 1 ; /* now the special prolog will be sent */
+ if (scanning && *p != '"' && (p=GetKeyVal(p, &j)) != NULL && j==0
+ && *ValStr != '`') /* Don't bother to scan compressed files. */
+ scanfontcomments(ValStr) ;
+}
+
+int maccess P1C(char *, s)
+{
+ FILE *f = search(figpath, s, "r") ;
+ if (f)
+ (*close_file) (f) ;
+ return (f != 0) ;
+}
+
+char *tasks[] = { 0, "iff2ps", "tek2ps" } ;
+
+static char psfile[511] ;
+void dospecial P1C(integer, numbytes)
+{
+ register char *p = nextstring ;
+ register int i = 0 ;
+ int j, systemtype = 0 ;
+ register char *q ;
+ Boolean psfilewanted = 1 ;
+ char *task = 0 ;
+ char cmdbuf[111] ;
+#ifdef HPS
+if (HPS_FLAG && PAGEUS_INTERUPPTUS) {
+ HREF_COUNT-- ;
+ start_new_box() ;
+ PAGEUS_INTERUPPTUS = 0 ;
+ }
+if (HPS_FLAG && NEED_NEW_BOX) {
+ vertical_in_hps();
+ NEED_NEW_BOX = 0;
+ }
+#endif
+ if (nextstring + numbytes > maxstring)
+ error("! out of string space in dospecial") ;
+ for (i=numbytes; i>0; i--)
+#ifdef VMCMS /* IBM: VM/CMS */
+ *p++ = ascii2ebcdic[(char)dvibyte()] ;
+#else
+#ifdef MVSXA /* IBM: MVS/XA */
+ *p++ = ascii2ebcdic[(char)dvibyte()] ;
+#else
+ *p++ = (char)dvibyte() ;
+#endif /* IBM: VM/CMS */
+#endif
+ while (p[-1] <= ' ' && p > nextstring)
+ p-- ; /* trim trailing blanks */
+ if (p==nextstring) return ; /* all blank is no-op */
+ *p = 0 ;
+ p = nextstring ;
+ while (*p <= ' ')
+ p++ ;
+#ifdef DEBUG
+ if (dd(D_SPECIAL))
+ (void)fprintf(stderr, "Processing special: %s\n", p) ;
+#endif
+
+ switch (*p) {
+case 'o':
+ if (strncmp(p, "om:", 3)==0) { /* Omega specials ignored */
+ return;
+ }
+ break ;
+case 'e':
+ if (strncmp(p, "em:", 3)==0) { /* emTeX specials in emspecial.c */
+ emspecial(p);
+ return;
+ }
+ break ;
+case 'p':
+ if (strncmp(p, "pos:", 4)==0) return ; /* positional specials */
+ if (strncmp(p, "ps:", 3)==0) {
+ psflush() ; /* now anything can happen. */
+ if (p[3]==':') {
+ if (strncmp(p+4, "[begin]", 7) == 0) {
+ hvpos() ;
+ trytobreakout(&p[11]);
+ } else if (strncmp(p+4, "[end]", 5) == 0)
+ trytobreakout(&p[9]);
+ else trytobreakout(&p[4]);
+ } else if (strncmp(p+3, " plotfile ", 10) == 0) {
+ char *sfp ;
+ hvpos() ;
+ p += 13;
+ /*
+ * Fixed to allow popen input for plotfile
+ * TJD 10/20/91
+ */
+ while (*p == ' ') p++;
+ if (*p == '"') {
+ p++;
+ for (sfp = p; *sfp && *sfp != '"'; sfp++) ;
+ } else {
+ for (sfp = p; *sfp && *sfp != ' '; sfp++) ;
+ }
+ *sfp = '\0';
+ if (*p == '`')
+ figcopyfile(p+1, 1);
+ else
+ figcopyfile (p, 0);
+ /* End TJD changes */
+ } else {
+ hvpos() ;
+ trytobreakout(&p[3]);
+ psflush() ;
+ hvpos() ;
+ }
+ return;
+ }
+ if (strncmp(p, "papersize", 9) == 0)
+ return ;
+#ifdef TPIC
+ if (strncmp(p, "pn ", 3) == 0) {setPenSize(p+2); return;}
+ if (strncmp(p, "pa ", 3) == 0) {addPath(p+2); return;}
+#endif
+ break ;
+case 'l':
+ if (strncmp(p, "landscape", 9)==0) return ;
+ break ;
+case '!':
+ return ;
+case 'h':
+ if (strncmp(p, "header", 6)==0) return ;
+#ifdef HPS
+ if (strncmp(p, "html:", 5)==0) {
+ if (! HPS_FLAG) return;
+ p += 5;
+ while (isspace(*p))
+ p++;
+ if (*p == '<') {
+ char *sp = p;
+ char *str;
+ int ii=0;int len;int lower_len;
+
+ while ((*p) && (*p != '>')) {
+ ii++;
+ p++;
+ }
+ str = (char *)mymalloc(ii+2);
+ strncpy(str,sp+1,ii-1);
+ str[ii-1] = 0;len=strlen(str);
+ if(len>6) lower_len=6; else lower_len=len;
+ for(ii=0;ii<lower_len;ii++) str[ii]=tolower(str[ii]);
+ do_html(str);
+ free(str);
+ } else
+#ifdef KPATHSEA
+ if (!kpse_tex_hush ("special"))
+#endif
+ {
+
+ printf("Error in html special\n");
+ return;
+ }
+ return;
+ }
+#else
+ if (strncmp(p, "html:", 5)==0) return;
+#endif
+case 'w':
+case 'W':
+ if (strncmp(p+1, "arning", 6) == 0) {
+ static int maxwarns = 50 ;
+ if (maxwarns > 0) {
+ error(p) ;
+ maxwarns-- ;
+ } else if (maxwarns == 0) {
+ error(". . . rest of warnings suppressed") ;
+ maxwarns-- ;
+ }
+ return ;
+ }
+#ifdef TPIC
+ if (strcmp(p, "wh") == 0) {whitenLast(); return;}
+#endif
+ break ;
+case 'b':
+ if ( strncmp(p, "background", 10) == 0 )
+ return ; /* already handled in prescan */
+#ifdef TPIC
+ if (strcmp(p, "bk") == 0) {blackenLast(); return;}
+#endif
+ break ;
+case 'c':
+ if (strncmp(p, "color", 5) == 0) {
+ p += 5 ;
+ while ( *p && *p <= ' ' ) p++ ;
+ if (strncmp(p, "push", 4) == 0 ) {
+ p += 4 ;
+ while ( *p && *p <= ' ' ) p++ ;
+ pushcolor(p,1);
+ } else if (strncmp(p, "pop", 3) == 0 ) {
+ popcolor(1) ;
+ } else {
+ resetcolorstack(p,1) ;
+ }
+ return ;
+ } /* IBM: color - end changes*/
+ break ;
+case 'f':
+#ifdef TPIC
+ if (strcmp(p, "fp") == 0) {flushPath(0); return;}
+#endif
+ break ;
+case 'i':
+#ifdef TPIC
+ if (strcmp(p, "ip") == 0) {flushPath(1); return;} /* tpic 2.0 */
+ if (strncmp(p, "ia ", 3) == 0) {arc(p+2, 1); return;} /* tpic 2.0 */
+#endif
+ break ;
+case 'd':
+#ifdef TPIC
+ if (strncmp(p, "da ", 3) == 0) {flushDashed(p+2, 0); return;}
+ if (strncmp(p, "dt ", 3) == 0) {flushDashed(p+2, 1); return;}
+#endif
+ break ;
+case 's':
+ if (strncmp(p, "src:", 4) == 0) return; /* source specials */
+#ifdef TPIC
+ if (strcmp(p, "sp") == 0) {flushSpline(p+2); return;} /* tpic 2.0 */
+ if (strncmp(p, "sp ", 3) == 0) {flushSpline(p+3); return;} /* tpic 2.0 */
+ if (strcmp(p, "sh") == 0) {shadeLast(p+2); return;} /* tpic 2.0 */
+ if (strncmp(p, "sh ", 3) == 0) {shadeLast(p+3); return;} /* tpic 2.0 */
+#endif
+ break ;
+case 'a':
+#ifdef TPIC
+ if (strncmp(p, "ar ", 3) == 0) {arc(p+2, 0); return;} /* tpic 2.0 */
+#endif
+ break ;
+case 't':
+#ifdef TPIC
+ if (strncmp(p, "tx ", 3) == 0) {SetShade(p+3); return;}
+#endif
+ break ;
+case '"':
+ hvpos() ;
+ cmdout("@beginspecial") ;
+ cmdout("@setspecial") ;
+ trytobreakout(p+1) ;
+ cmdout("\n@endspecial") ;
+ return ;
+ break ;
+default:
+#if 0
+ {
+ /* Unknown special, must return */
+ sprintf(errbuf,"Unrecognized special (first 10 chars: %.10s)", p);
+ specerror(errbuf);
+ return;
+ }
+#endif
+ break ;
+ }
+/* At last we get to the key/value conventions */
+ psfile[0] = '\0';
+ hvpos();
+ cmdout("@beginspecial");
+
+ while( (p=GetKeyVal(p,&j)) != NULL )
+ switch (j) {
+ case -1: /* for compatability with old conventions, we allow a file name
+ * to be given without the 'psfile=' keyword */
+ if (!psfile[0] && maccess(KeyStr)==0) /* yes we can read it */
+ (void)strcpy(psfile,KeyStr) ;
+ else {
+ if (strlen(KeyStr) < 40) {
+ sprintf(errbuf,
+ "Unknown keyword (%s) in \\special will be ignored",
+ KeyStr) ;
+ } else {
+ sprintf(errbuf,
+ "Unknown keyword (%.40s...) in \\special will be ignored",
+ KeyStr) ;
+ }
+ specerror(errbuf) ;
+ }
+ break ;
+ case 0: case 1: case 2: /* psfile */
+ if (psfile[0]) {
+ sprintf(errbuf, "More than one \\special %s given; %s ignored",
+ "psfile", ValStr) ;
+ specerror(errbuf) ;
+ }
+ else (void)strcpy(psfile,ValStr) ;
+ task = tasks[j] ;
+ break ;
+ default: /* most keywords are output as PostScript procedure calls */
+ if (KeyTab[j].Type == Integer)
+ numout((integer)ValInt);
+ else if (KeyTab[j].Type == String)
+ for (q=ValStr; *q; q++)
+ scout(*q) ;
+ else if (KeyTab[j].Type == None) ;
+ else { /* Number or Dimension */
+ ValInt = (integer)(ValNum<0? ValNum-0.5 : ValNum+0.5) ;
+ if (ValInt-ValNum < 0.001 && ValInt-ValNum > -0.001)
+ numout((integer)ValInt) ;
+ else {
+ (void)sprintf(cmdbuf, "%f", ValNum) ;
+ cmdout(cmdbuf) ;
+ }
+ }
+ (void)sprintf(cmdbuf, "@%s", KeyStr);
+ cmdout(cmdbuf) ;
+ }
+
+ cmdout("@setspecial");
+
+ if(psfile[0]) {
+ if (task == 0) {
+ systemtype = (psfile[0]=='`') ;
+ figcopyfile(psfile+systemtype, systemtype);
+ } else {
+ fil2ps(task, psfile) ;
+ }
+ } else if (psfilewanted
+#ifdef KPATHSEA
+ && !kpse_tex_hush ("special")
+#endif
+ )
+ specerror("No \\special psfile was given; figure will be blank") ;
+
+ cmdout("@endspecial");
+}
+
+#ifdef KPATHSEA
+extern char *realnameoffile;
+#else
+extern char realnameoffile[] ;
+extern char *pictpath ;
+#endif
+void fil2ps P2C(char *, task, char *, iname)
+{
+ char cmd[400] ;
+ FILE *f ;
+ if (0 != (f=search(pictpath, iname, "r"))) {
+ close_file(f) ;
+ } else {
+ fprintf(stderr, " couldn't open %s\n", iname) ;
+ return ;
+ }
+ if (!quiet) {
+ fprintf(stderr, " [%s", realnameoffile) ;
+ fflush(stderr) ;
+ }
+ if (oname && oname[0] && oname[0] != '-') {
+ putc(10, bitfile) ;
+ close_file(bitfile) ;
+ sprintf(cmd, "%s -f %s %s", task, realnameoffile, oname) ;
+ system(cmd) ;
+ if ((bitfile=fopen(oname, FOPEN_ABIN_MODE))==NULL)
+ error_with_perror ("! couldn't reopen PostScript file", oname) ;
+ linepos = 0 ;
+ } else {
+ sprintf(cmd, "%s -f %s", task, realnameoffile) ;
+ system(cmd) ;
+ }
+ if (!quiet)
+ fprintf(stderr, "]") ;
+}
+
+/*
+ * Handles specials encountered during bounding box calculations.
+ * Currently we only deal with psfile's or PSfiles and only those
+ * that do not use rotations.
+ */
+static float rbbox[4] ;
+float *bbdospecial P1C(int, nbytes)
+{
+ char *p = nextstring ;
+ int i, j ;
+ char seen[NKEYS] ;
+ float valseen[NKEYS] ;
+
+ if (nextstring + nbytes > maxstring) {
+ p = nextstring = mymalloc(1000 + 2 * nbytes) ;
+ maxstring = nextstring + 2 * nbytes + 700 ;
+ }
+ if (nextstring + nbytes > maxstring)
+ error("! out of string space in bbdospecial") ;
+ for (i=nbytes; i>0; i--)
+#ifdef VMCMS /* IBM: VM/CMS */
+ *p++ = ascii2ebcdic[(char)dvibyte()] ;
+#else
+#ifdef MVSXA /* IBM: MVS/XA */
+ *p++ = ascii2ebcdic[(char)dvibyte()] ;
+#else
+ *p++ = (char)dvibyte() ;
+#endif /* IBM: VM/CMS */
+#endif
+ while (p[-1] <= ' ' && p > nextstring)
+ p-- ; /* trim trailing blanks */
+ if (p==nextstring) return NULL ; /* all blank is no-op */
+ *p = 0 ;
+ p = nextstring ;
+ while (*p && *p <= ' ')
+ p++ ;
+ if (strncmp(p, "psfile", 6)==0 || strncmp(p, "PSfile", 6)==0) {
+ float originx = 0, originy = 0, hscale = 1, vscale = 1,
+ hsize = 0, vsize = 0 ;
+ for (j=0; j<NKEYS; j++)
+ seen[j] = 0 ;
+ j = 0 ;
+ while ((p=GetKeyVal(p, &j))) {
+ if (j >= 0 && j < NKEYS && KeyTab[j].Type == Number) {
+ seen[j]++ ;
+ valseen[j] = ValNum ;
+ }
+ }
+ /*
+ * This code mimics what happens in @setspecial.
+ */
+ if (seen[3])
+ hsize = valseen[3] ;
+ if (seen[4])
+ vsize = valseen[4] ;
+ if (seen[5])
+ originx = valseen[5] ;
+ if (seen[6])
+ originy = valseen[6] ;
+ if (seen[7])
+ hscale = valseen[7] / 100.0 ;
+ if (seen[8])
+ vscale = valseen[8] / 100.0 ;
+ if (seen[10] && seen[12])
+ hsize = valseen[12] - valseen[10] ;
+ if (seen[11] && seen[13])
+ vsize = valseen[13] - valseen[11] ;
+ if (seen[14] || seen[15]) {
+ if (seen[14] && seen[15] == 0) {
+ hscale = vscale = valseen[14] / (10.0 * hsize) ;
+ } else if (seen[15] && seen[14] == 0) {
+ hscale = vscale = valseen[15] / (10.0 * vsize) ;
+ } else {
+ hscale = valseen[14] / (10.0 * hsize) ;
+ vscale = valseen[15] / (10.0 * vsize) ;
+ }
+ }
+ /* at this point, the bounding box in PostScript units relative to
+ the current dvi point is
+ originx originy originx+hsize*hscale originy+vsize*vscale
+ We'll let the bbox routine handle the remaining math.
+ */
+ rbbox[0] = originx ;
+ rbbox[1] = originy ;
+ rbbox[2] = originx+hsize*hscale ;
+ rbbox[3] = originy+vsize*vscale ;
+ return rbbox ;
+ }
+ return 0 ;
+}