|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 19530 (0x4c4a) Types: TextFile Names: »dospecial.c«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦8d3183c2b⟧ »utils/dvips541.tar.Z« └─⟦008d6ff64⟧ └─⟦this⟧ »./dvips/dospecial.c«
/* * This routine handles special commands; * predospecial() is for the prescan, dospecial() for the real thing. */ #include "structures.h" /* The copyright notice in that file is included too! */ #include <ctype.h> extern int atoi(); /* * These are the external routines called: */ /**/ #ifdef TPIC /* * Fri Mar 9 1990 jourdan@minos.inria.fr (MJ) * Upgraded to accommodate tpic release 2.0 extended output language. * Should prove upward compatible! */ extern void setPenSize(); extern void flushPath(); extern void flushDashed(); extern void flushDashed(); extern void addPath(); extern void arc(); extern void flushSpline(); extern void shadeLast(); extern void whitenLast(); extern void blackenLast(); extern void SetShade() ; #endif extern shalfword dvibyte() ; extern int add_header() ; extern void hvpos() ; extern void figcopyfile() ; extern char *malloc() ; extern void nlcmdout() ; extern void cmdout() ; extern void numout() ; extern void scout() ; extern void stringend() ; extern void error() ; extern void psflush() ; extern char errbuf[] ; extern shalfword linepos; extern Boolean usesspecial ; 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 ; #ifdef DEBUG extern integer debug_flag; #endif extern void scanfontcomments() ; struct bangspecial { struct bangspecial *next ; char actualstuff[1] ; /* more space will actually be allocated */ } *bangspecials = NULL ; #ifdef EMTEX /* subset of emtex specials */ #define EMMAX 1613 /* maximum number of emtex special points */ #define TRUE 1 #define FALSE 0 struct empt { shalfword point; integer x, y; }; struct empt *empoints = NULL; boolean emused = FALSE; /* true if em points used on this page */ integer emx, emy; struct emunit { char *unit; float factor; }; struct emunit emtable[] = { {"pt",72.27}, {"pc",72.27/12}, {"in",1.0}, {"bp",72.0}, {"cm",2.54}, {"mm",25.4}, {"dd",72.27/(1238/1157)}, {"cc",72.27/12/(1238/1157)}, {"sp",72.27*65536}, {"",0.0} }; /* clear the empoints array if necessary */ void emclear() { int i; if (emused && empoints) for (i=0; i<EMMAX; i++) empoints[i].point = 0; emused = FALSE ; } /* put an empoint into the empoints array */ struct empt *emptput(point, x, y) shalfword point; integer x, y; { int i, start; emused = TRUE; start = point % EMMAX; i = start; while ( empoints[i].point != 0 ) { if ( empoints[i].point == point ) break; i++; if (i >= EMMAX) i = 0; if (i == start) { sprintf(errbuf,"!Too many em: special points"); error(errbuf); } } empoints[i].point = point; empoints[i].x = x; empoints[i].y = y; return(&empoints[i]); } /* get an empoint from the empoints array */ struct empt *emptget(point) shalfword point; { int i, start; start = point % EMMAX; i = start; if (emused == TRUE) while ( empoints[i].point != 0 ) { if (empoints[i].point == point) return(&empoints[i]); i++; if (i >= EMMAX) i = 0; if (i == start) break; } sprintf(errbuf,"!em: point %d not defined",point); error(errbuf); return(NULL); /* never returns due to error */ } /* convert width into dpi units */ float emunits(width,unit) float width; char *unit; { struct emunit *p; for (p=emtable; *(p->unit)!='\0'; p++) { if (strcmp(p->unit,unit)==0) return( width * actualdpi / p->factor ); } return (-1.0); /* invalid unit */ } #endif /* EMTEX */ static void trytobreakout(p) register char *p ; { register int i ; register int instring = 0 ; int lastc = 0 ; i = 0 ; 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++ ; } } static void dobs(q) register struct bangspecial *q ; { if (q) { dobs(q->next) ; trytobreakout(q->actualstuff) ; } } void outbangspecials() { 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}}; #ifndef VMS /* * compare strings, ignore case */ char Tolower(c) register char c ; { if ('A' <= c && c <= 'Z') return(c+32) ; else return(c) ; } #endif int IsSame(a, b) char *a, *b; { for( ; *a != '\0'; ) if( Tolower(*a++) != Tolower(*b++) ) return( 0 ); 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(str,tno) /* returns NULL if none found, else next scan point */ char *str ; /* starting point for scan */ int *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 (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) ; error(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) ; error(errbuf) ; ValNum = 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. */ void predospecial(numbytes, scanning) integer numbytes ; Boolean scanning ; { register char *p = nextstring ; register int i = 0 ; int j ; if (nextstring + numbytes > maxstring) error("! out of string space in predospecial") ; for (i=numbytes; i>0; i--) *p++ = (char)dvibyte() ; 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. */ if (strncmp(p, "landscape", 9)==0) { landscape = 1 ; return ; } if (strncmp(p, "xtex:", 5)==0) return ; usesspecial = 1 ; /* now the special prolog will be sent */ if (strncmp(p, "header", 6)==0) { char *q ; p += 6 ; while ((*p <= ' ' || *p == '=' || *p == '(') && *p != 0) p++ ; 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) ; } else if (*p == '!') { register struct bangspecial *q ; p++ ; q = (struct bangspecial *)malloc((unsigned) (sizeof(struct bangspecial) + strlen(p))) ; if (q == NULL) error("! out of memory in predospecial") ; (void)strcpy(q->actualstuff, p) ; q->next = bangspecials ; bangspecials = q ; } else if (scanning && *p != '"' && (p=GetKeyVal(p, &j)) != NULL && j==0) scanfontcomments(ValStr) ; } void dospecial(numbytes) integer numbytes ; { register char *p = nextstring ; register int i = 0 ; int j, systemtype = 0 ; char psfile[100] ; char cmdbuf[100] ; register char *q ; Boolean psfilewanted = 1 ; extern int access() ; #ifdef EMTEX /* specials for emtex */ float emwidth; shalfword empoint1, empoint2; struct empt *empoint; char emunit[3]; char emstr[80]; char *emp; #endif /* EMTEX */ if (nextstring + i > maxstring) error("! out of string space in dospecial") ; for (i=numbytes; i>0; i--) *p++ = (char)dvibyte() ; 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 #ifdef EMTEX /* specials for emtex, added by rjl */ /* at present, * the line cut parameter is not supported (and is ignored) * em:graph is not supported */ if (strncmp(p, "em:", 3)==0) { hvpos() ; for (emp = p+3; *emp && isspace(*emp); emp++); /* skip blanks */ if (strncmp(emp, "linewidth", 9) == 0) { /* code for linewidth */ for (emp = emp+9; *emp && isspace(*emp); emp++); /* skip blanks */ sscanf(emp, "%f%2s", &emwidth, emunit); emwidth = emunits(emwidth,emunit); if (emwidth!=-1.0) { sprintf(emstr,"%.1f setlinewidth", emwidth); cmdout(emstr); #ifdef DEBUG if (dd(D_SPECIAL)) (void)fprintf(stderr, "em special: Linewidth set to %.1f dots\n", emwidth) ; #endif } else { sprintf(errbuf,"Unknown em: special width"); error(errbuf); } } else if (strncmp(emp, "moveto", 6) == 0) { #ifdef DEBUG if (dd(D_SPECIAL)) (void)fprintf(stderr, "em special: moveto %ld,%ld\n", hh, vv); #endif emx = hh; emy = vv; } else if (strncmp(emp, "lineto", 6) == 0) { #ifdef DEBUG if (dd(D_SPECIAL)) (void)fprintf(stderr, "em special: lineto %ld,%ld\n", hh, vv); #endif cmdout("np"); numout(emx); numout(emy); cmdout("a"); numout(hh); numout(vv); cmdout("li"); cmdout("st"); emx = hh; emy = vv; } else if (strncmp(emp, "point", 5) == 0) { if (empoints == NULL) { if (( empoints = (struct empt *)malloc(EMMAX * sizeof(struct empt)) ) == (struct empt *)NULL) error("! can't allocate em: points space") ; emused = TRUE; emclear(); } for (emp = emp+5; *emp && isspace(*emp); emp++); /* skip blanks */ empoint1 = (shalfword)atoi(emp); empoint = emptput(empoint1,hh,vv); #ifdef DEBUG if (dd(D_SPECIAL)) (void)fprintf(stderr, "em special: Point %d is %ld,%ld\n", empoint->point, empoint->x, empoint->y) ; #endif } else if (strncmp(emp, "line", 4) == 0) { for (emp = emp+4; *emp && isspace(*emp); emp++); /* skip blanks */ empoint1 = (shalfword)atoi(emp); for (; *emp && isdigit(*emp); emp++); /* skip point 1 */ if ( *emp && strchr("hvp",*emp)!=0 ) emp++; /* skip line cut */ for (; *emp && isspace(*emp); emp++); /* skip blanks */ if ( *emp && ispunct(*emp) ) emp++; /* skip comma separator */ for (; *emp && isspace(*emp); emp++); /* skip blanks */ empoint2 = (shalfword)atoi(emp); for (; *emp && isdigit(*emp); emp++); /* skip point 2 */ if ( *emp && strchr("hvp",*emp)!=0 ) emp++; /* skip line cut */ for (; *emp && isspace(*emp); emp++); /* skip blanks */ if ( *emp && ispunct(*emp) ) emp++; /* skip comma separator */ emwidth = -1.0; emunit[0]='\0'; sscanf(emp, "%f%2s", &emwidth, emunit); emwidth = emunits(emwidth,emunit); #ifdef DEBUG if (dd(D_SPECIAL)) (void)fprintf(stderr, "em special: Line from point %d to point %d\n", empoint1, empoint2) ; #endif cmdout("np"); if (emwidth!=-1.0) { #ifdef DEBUG if (dd(D_SPECIAL)) (void)fprintf(stderr,"em special: Linewidth temporarily set to %.1f dots\n", emwidth) ; #endif strcpy(emstr,"currentlinewidth"); cmdout(emstr); sprintf(emstr,"%.1f setlinewidth", emwidth); cmdout(emstr); } empoint = emptget(empoint1); numout(empoint->x); numout(empoint->y); cmdout("a"); empoint = emptget(empoint2); numout(empoint->x); numout(empoint->y); cmdout("li"); cmdout("st"); if (emwidth!=-1.0) { strcpy(emstr,"setlinewidth"); cmdout(emstr); } } else if (strncmp(emp, "message", 7) == 0) { (void)fprintf(stderr, "em message: %s\n", emp+7) ; } else { sprintf(errbuf, "Unknown em: command (%s) in \\special will be ignored", p); error(errbuf) ; } return; } #endif /* EMTEX */ if (strncmp(p, "ps:", 3)==0) { hvpos() ; psflush() ; /* now anything can happen. */ if (p[3]==':') { if (strncmp(p+4, "[begin]", 7) == 0) nlcmdout(&p[11]); else if (strncmp(p+4, "[end]", 5) == 0) nlcmdout(&p[9]); else nlcmdout(&p[4]); } else if (strncmp(p+3, " plotfile ", 10) == 0) { char *sfp ; p += 13; for (sfp = p; *sfp && *sfp != ' '; sfp++) ; *sfp = '\0'; figcopyfile (p, 0); } else nlcmdout(&p[3]); return; } if (strncmp(p, "landscape", 9)==0 || strncmp(p, "header", 6)==0 || *p=='!') return ; /* already handled in prescan */ #ifdef TPIC /* ordered as in tpic 2.0 documentation for ease of cross-referencing */ if (strncmp(p, "pn ", 3) == 0) {setPenSize(p+2); return;} if (strncmp(p, "pa ", 3) == 0) {addPath(p+2); return;} if (strcmp(p, "fp") == 0) {flushPath(0); return;} if (strcmp(p, "ip") == 0) {flushPath(1); return;} /* tpic 2.0 */ if (strncmp(p, "da ", 3) == 0) {flushDashed(p+2, 0); return;} if (strncmp(p, "dt ", 3) == 0) {flushDashed(p+2, 1); return;} 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 (strncmp(p, "ar ", 3) == 0) {arc(p+2, 0); return;} /* tpic 2.0 */ if (strncmp(p, "ia ", 3) == 0) {arc(p+2, 1); 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 */ if (strcmp(p, "wh") == 0) {whitenLast(); return;} if (strcmp(p, "bk") == 0) {blackenLast(); return;} if (strncmp(p, "tx ", 3) == 0) {SetShade(p+3); return;} #endif if (*p == '"') { hvpos(); cmdout("@beginspecial") ; cmdout("@setspecial\n") ; trytobreakout(p+1) ; cmdout("\n@endspecial") ; return ; } /* 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] && access(KeyStr,4)==0) /* yes we can read it */ (void)strcpy(psfile,KeyStr) ; else { sprintf(errbuf, "Unknown keyword (%s) in \\special will be ignored", KeyStr) ; error(errbuf) ; } break ; case 0: /* psfile */ if (psfile[0]) { sprintf(errbuf, "More than one \\special %s given; %s ignored", j ? "system" : "psfile", ValStr) ; error(errbuf) ; } else (void)strcpy(psfile,ValStr) ; break ; case 1: case 2: sprintf(errbuf, "Sorry, there's presently no \\special support for %s", KeyStr) ; error(errbuf) ; psfilewanted = 0 ; break ; default: /* most keywords are output as PostScript procedure calls */ if (KeyTab[j].Type == Integer) numout(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(ValInt) ; else { (void)sprintf(cmdbuf, "%f", ValNum) ; cmdout(cmdbuf) ; } } (void)sprintf(cmdbuf, "@%s", KeyStr); cmdout(cmdbuf) ; } cmdout("@setspecial"); if(psfile[0]) { systemtype = (psfile[0]=='`') ; figcopyfile(psfile+systemtype, systemtype); } else if (psfilewanted) error("No \\special psfile was given; figure will be blank") ; cmdout("@endspecial"); }