This is dospecial.c in view mode; [Download] [Up]
/*
* This is dvips, a freely redistributable PostScript driver
* for dvi files. It is (C) Copyright 1987 by Tomas Rokicki.
* You may modify and use this program to your heart's content,
* so long as you send modifications to Tomas Rokicki. It can
* be included in any distribution, commercial or otherwise, so
* long as the banner string defined in structures.h is not
* modified (except for the version number) and this banner is
* printed on program invocation, or can be printed on program
* invocation with the -? option.
*/
#define COLOR
/*
* dospecial of dvisw package. (C) 1986 Radical Eye Software.
* This routine handles special commands. Currently the only
* special command handled is the landscape special.
*/
#include "structures.h"
#include <dpsclient/dpsclient.h>
#include "paths.h"
#include <string.h>
/*
* These are the external routines called:
*/
#ifdef TPIC
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();
#endif
#ifdef COLOR
extern void pushcolor() ;
extern void popcolor() ;
extern void resetcolorstack() ;
extern void background() ;
static Boolean usescolor ;
#endif
extern void pswrite(), error(), tolandscape(), add_header(), hvpos() ;
extern void copyfile(), figcopyfile() ;
extern void handlepapersize(), newpapersize() ;
extern int dvibyte() ;
extern char *malloc(), *newstring() ;
int GetKeyVal(), IsSame() ;
extern FILE *search() ;
extern void texflush() ;
extern char *inputspath ;
extern Boolean prescan;
extern void writeconsole() ;
extern Boolean firstpage ;
extern Boolean mocked ;
extern Boolean landscape, orientationset ;
extern int debugon ;
extern char *configpath, *headerpath ;
extern void TPSbop(), TPSeop() ;
char nextstring[8192] ;
extern char temperrorbuf[] ;
char *maxstring = nextstring + 8100 ;
static integer hpapersize, vpapersize ;
/*
* These definitions are used by the \special command.
*/
typedef enum {None, String, Integer, Number, Dimension} ValTyp;
typedef struct {
char *Key; /* the keyword string */
char *Val; /* the value string */
ValTyp vt; /* the value type */
union { /* the decoded value */
long i;
float n;
} v;
} KeyWord;
typedef struct {
char *Entry;
ValTyp Type;
} KeyDesc;
/*
* Now our routine. We get the number of bytes specified and place them
* into the string buffer, and then parse it for alpha. Interpret a
* \special command, made up of keyword=value pairs.
*/
#define NKEYS (sizeof(KeyTab)/sizeof(KeyTab[0]))
KeyDesc KeyTab[] = {{"psfile", String},
{"ifffile", String},
{"tekfile", String},
{"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}};
char *GetKeyStr();
void fil2ps();
char task[7] = "\0";
struct bangspecial {
struct bangspecial *next ;
char actualstuff[4] ;
} *bangspecials = NULL ;
#define spswrite trytobreakout
static void trytobreakout(p)
register char *p ;
{
pswrite(" ") ;
pswrite(p) ;
pswrite(" ") ;
}
static void dobs(q)
register struct bangspecial *q ;
{
if (q) {
dobs(q->next) ;
trytobreakout(q->actualstuff) ;
}
}
void special_header() {
static int sent = 0 ;
if (! sent) {
texflush() ;
#ifdef POPRESTORE
TPSeop() ;
#endif
add_header("special.pro") ;
#ifdef POPRESTORE
TPSbop() ;
#endif
hvpos() ;
sent = 1 ;
}
}
void outbangspecials() {
if (bangspecials) {
special_header() ;
pswrite(" @defspecial ") ;
dobs(bangspecials) ;
pswrite(" @fedspecial ") ;
}
}
#define TRUE (1)
#define FALSE (0)
void dospecial(numbytes)
integer numbytes ;
{
register char *p = nextstring ;
register int i = 0 ;
int j ;
Boolean ps = TRUE ;
char spbuf[400] ;
char fbuf[400] ;
char *sf = NULL ;
char *f = NULL ;
KeyWord k ;
temperrorbuf[0] = 0 ;
if (nextstring + i > maxstring)
error("! out of string space in dospecial") ;
for (i=numbytes; i>0; i--)
*p++ = dvibyte() ;
*p = 0 ;
p = nextstring ;
#ifdef DEBUG
if (debugon > 3) {
printf("{%s}[%d]", p, prescan) ;
fflush(stdout) ;
}
#endif
while (*p <= ' ' && *p)
p++ ;
if (strncmp(p, "landscape", 9)==0) {
if (prescan && firstpage)
tolandscape() ;
return ;
} else if (strncmp(p, "papersize", 9)==0) {
p += 9 ;
while (*p == '=' || *p == ' ')
p++ ;
handlepapersize(p, &hpapersize, &vpapersize) ;
if (prescan && firstpage)
newpapersize(hpapersize, vpapersize) ;
return ;
}
/* ignore this special for now */
if (strncmp(p, "hp:", 3)==0)
return ;
if (! prescan)
special_header() ;
if (strncmp(p, "header", 6)==0) {
if (prescan) {
char *q ;
p += 6 ;
while ((*p <= ' ' || *p == '=' || *p == ')') && *p != 0)
p++ ;
q = p ;
p = p + strlen(p) - 1 ;
if (*p == ')') {
p-- ;
while (*p <= ' ')
p-- ;
p[1] = 0 ;
}
add_header(q) ;
}
return ;
#ifdef COLOR
}
if (strncmp(p, "background", 10) == 0) {
if (usescolor == 0) {
add_header("color.pro") ;
usescolor = 1 ;
}
p +=11 ;
while ( *p <= ' ' ) p++ ;
background(p) ;
return ;
}
if (strncmp(p, "color", 5) == 0) {
if (usescolor == 0) {
add_header("color.pro") ;
usescolor = 1 ;
}
p += 6 ;
while ( *p <= ' ' ) p++ ;
if (strncmp(p, "push", 4) == 0 ) {
p += 4 ;
while (*p && *p <= ' ' ) p++ ;
pushcolor(p,!prescan) ;
} else if (strncmp(p, "pop", 3) == 0 ) {
popcolor(!prescan) ;
} else {
resetcolorstack(p,!prescan) ;
}
return ;
#endif
} else if (strncmp(p, "ps:", 3)==0) {
if (! prescan) {
hvpos() ;
texflush() ;
if (strncmp(p, "ps::[begin]", 11) == 0)
spswrite(&p[11]);
else if (strncmp(p, "ps::[end]", 9) == 0)
spswrite(&p[9]);
else if (strncmp(p, "ps: plotfile ", 13) == 0) {
char *sfp ;
p += 13;
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);
} else if (strncmp(p, "ps::", 4) == 0)
spswrite(&p[4]);
else
spswrite(&p[3]);
return;
}
}
#ifdef TPIC
else if (strncmp(p, "pn ", 3) == 0) {if (!prescan) setPenSize(p+2);}
else if (strncmp(p, "fp",2) == 0) {if (!prescan) flushPath();}
else if (strncmp(p, "da ", 3) == 0) {if (!prescan) flushDashed(p+2, 0);}
else if (strncmp(p, "dt ", 3) == 0) {if (!prescan) flushDashed(p+2, 1);}
else if (strncmp(p, "pa ", 3) == 0) {if (!prescan) addPath(p+2);}
else if (strncmp(p, "ar ", 3) == 0) {if (!prescan) arc(p+2);}
else if (strncmp(p, "sp", 2) == 0) {if (!prescan) flushSpline();}
else if (strncmp(p, "sh", 2) == 0) {if (!prescan) shadeLast();}
else if (strncmp(p, "wh", 2) == 0) {if (!prescan) whitenLast();}
else if (strncmp(p, "bk", 2) == 0) {if (!prescan) blackenLast();}
else if (strncmp(p, "tx ", 3) == 0)
{error("\\special texture command -- ignored");}
#endif
else {
if (prescan && *p == '!' && firstpage) {
struct bangspecial *q ;
void *mymalloc() ;
p++ ;
q = (struct bangspecial *)mymalloc(sizeof(struct bangspecial) + strlen(p)) ;
strcpy(q->actualstuff, p) ;
q->next = bangspecials ;
bangspecials = q ;
return ;
}
if (! prescan) {
if (*p == '"') {
hvpos();
pswrite(" @beginspecial @setspecial ") ;
trytobreakout(p+1) ;
pswrite(" @endspecial ") ;
return ;
} else if (*p == '!')
return ;
spbuf[0] = '\0';
hvpos();
pswrite(" @beginspecial ");
/* get all keyword-value pairs; for compatibility,
single words are taken as file names */
while( (p=GetKeyStr(p,&k)) != NULL ) {
if( GetKeyVal( &k, KeyTab, NKEYS, &j ) && j != -1 ) {
if( j >= 0 && j <= 2 ) {
if( sf ) {
fprintf(stderr, " more than one \\special file name given: %s ignored.", sf );
}
strcpy(fbuf, k.Key);
strcpy(spbuf, k.Val);
f = fbuf;
sf = spbuf;
if( j == 1 || j == 2)
ps = FALSE;
} else { /* keywords are output as PS procedure calls */
if(k.vt == Integer)
sprintf(temperrorbuf, "%ld @%s ", k.v.i, KeyTab[j].Entry);
else if (k.vt == None)
sprintf(temperrorbuf, " @%s ", KeyTab[j].Entry);
else
sprintf(temperrorbuf, "%f @%s ", k.v.n, KeyTab[j].Entry);
pswrite(temperrorbuf) ;
}
} else {
fprintf(stderr, " invalid keyword or value in \\special: \"%s\" ignored.", k.Key );
}
}
pswrite(" @setspecial ");
if( sf ) {
if (*sf == '`')
figcopyfile(sf+1, 1);
else
figcopyfile(sf, 0);
} else
fprintf(stderr, " no special file name provided.");
pswrite(" @endspecial ");
}
}
}
/*
* extract first keyword-value pair from string (value part may be null)
* return pointer to remainder of string return NULL if none found
*/
char KeyStr[500];
char ValStr[500];
char *GetKeyStr( str, kw )
char *str;
KeyWord *kw;
{
char *s, *k, *v, t;
if( !str )
return( NULL );
for( s=str; *s == ' '; s++ ) /* skip over blanks */
;
if( *s == '\0' )
return( NULL );
/* extract keyword portion */
for( k=KeyStr; *s != ' ' && *s != '\0' && *s != '='; *k++ = *s++ )
;
*k = '\0';
kw->Key = KeyStr;
kw->Val = v = NULL;
kw->vt = None;
for( ; *s && *s == ' '; s++ ) /* skip over blanks */
;
if( *s != '=' ) /* look for "=" */
return( s );
for( s++ ; *s && *s == ' '; s++ ) /* skip over blanks */
;
if( *s == '\'' || *s == '\"' ) /* get string delimiter */
t = *s++;
else
t = ' ';
/* copy value portion up to delimiter */
for( v=ValStr; *s != t && *s != '\0'; *v++ = *s++ )
;
if( t != ' ' && *s == t )
s++;
*v = '\0';
kw->Val = ValStr;
kw->vt = String;
return( s );
}
/*
* get next keyword-value pair decode value according to table entry
*/
int GetKeyVal( kw, tab, nt, tno)
KeyWord *kw;
KeyDesc tab[];
int nt;
int *tno;
{
int i;
char c = '\0';
*tno = -1;
for(i=0; i<nt; i++)
if( IsSame(kw->Key, tab[i].Entry) ) {
*tno = i;
switch( tab[i].Type ) {
case None:
if( kw->vt != None )
return( 0 );
break;
case String:
if( kw->vt != String )
return( 0 );
break;
case Integer:
if( kw->vt != String )
return( 0 );
if( sscanf(kw->Val,"%ld%c", &(kw->v.i), &c) != 1 || c != '\0' )
return( 0 );
break;
case Number:
case Dimension:
if( kw->vt != String )
return( 0 );
if( sscanf(kw->Val,"%f%c", &(kw->v.n), &c) != 1 || c != '\0' )
return( 0 );
break;
}
kw->vt = tab[i].Type;
return( 1 );
}
return( 1 );
}
/*
* compare strings, ignore case
*/
int Tolower(c)
register int c ;
{
if ('A' <= c && c <= 'Z')
return(c+32) ;
else
return(c) ;
}
int IsSame(a, b)
char *a, *b;
{
for( ; *a != '\0'; )
if( Tolower(*a++) != Tolower(*b++) )
return( 0 );
return( *a == *b ? 1 : 0 );
}
void pswrite(s)
char *s ;
{
DPSWritePostScript(DPSGetCurrentContext(), s, strlen(s)) ;
}
void qstatus() ;
/*
* This routine copies a file down the pipe. Search path uses the
* header path.
*
* We add code to handle the case of MS-DOS font files.
*
* Format: 80 {01,02} four byte length in littleendian order data
* repeated possibly multiple times.
*/
static char *hxdata = "0123456789ABCDEF" ;
static int infigure ;
void
copyfile(s)
char *s ;
{
FILE *f = NULL ;
int c, prevc = '\n' ;
long len ;
char nextstring[2000] ;
switch (infigure) {
case 1:
f = search(inputspath, s, "r") ;
(void)sprintf(temperrorbuf, "Couldn't open figure file %s", s) ;
break ;
default:
f = search(headerpath, s, "r") ;
(void)sprintf(temperrorbuf, "Couldn't open header file %s", s) ;
break ;
case 2:
#ifdef SECURE
(void)sprintf(temperrorbuf, "<%s>: Tick filename execution disabled", s) ;
#else
writeconsole(s) ;
f = popen(s, "r") ;
(void)sprintf(temperrorbuf, "Failure to execute %s; continuing", s) ;
#endif
break;
}
if (f==NULL) {
if (infigure == 1 || infigure == 2)
pswrite(" MockPic ") ;
/* error(temperrorbuf) ; can't do this; will crash window server to run
an alert here; no idea why. */
} else {
sprintf(temperrorbuf, "Inserting %s", s) ;
qstatus(temperrorbuf) ;
c = getc(f) ;
if (c == 0x80) {
while (1) {
char *p = nextstring ;
c = getc(f) ;
switch(c) {
case 1:
case 2:
len = getc(f) ;
len += getc(f) * 256L ;
len += getc(f) * 65536L ;
len += getc(f) * 256L * 65536 ;
if (c == 1) {
while (len > 0) {
c = getc(f) ;
if (c == EOF) {
error("premature EOF in MS-DOS font file") ;
len = 0 ;
} else if (c == 10 || c == 13) {
*p++ = 10 ;
*p++ = 0 ;
pswrite(nextstring) ;
p = nextstring ;
len-- ;
} else {
*p++ = c ;
len-- ;
}
}
} else {
if (p > nextstring) {
*p++ = 10 ;
*p++ = 0 ;
pswrite(nextstring) ;
p = nextstring ;
}
prevc = 0 ;
while (len > 0) {
c = getc(f) ;
if (c == EOF) {
error("premature EOF in MS-DOS font file") ;
len = 0 ;
} else {
*p++ = hxdata[c >> 4] ;
*p++ = hxdata[c & 15] ;
len-- ;
prevc += 2 ;
if (prevc >= 76) {
*p++ = 10 ;
*p = 0 ;
pswrite(nextstring) ;
p = nextstring ;
prevc = 0 ;
}
}
}
if (prevc) {
*p++ = 10 ;
*p = 0 ;
pswrite(nextstring) ;
p = nextstring ;
prevc = 0 ;
}
}
break ;
case 3:
goto msdosdone ;
default:
error("saw type other than 1, 2, or 3 in MS-DOS font file") ;
break ;
}
c = getc(f) ;
if (c == EOF)
break ;
if (c != 0x80) {
error("saw non-MSDOS header in MSDOS font file") ;
break ;
}
}
msdosdone: ;
} else {
ungetc(c, f) ;
while (fgets(nextstring, 1900, f))
pswrite(nextstring) ;
}
if (infigure == 2)
(void)pclose(f) ;
else
(void)fclose(f) ;
}
}
/*
* For included PostScript graphics, we use the above routine, but
* with no fatal error message.
*/
void figcopyfile(s, systemtype)
char *s ;
int systemtype ;
{
infigure = (systemtype ? 2 : 1) ;
if (mocked)
pswrite(" MockPic ");
else
copyfile(s) ;
infigure = 0 ;
}
void cleartheair() {
outbangspecials() ;
}
struct header_list {
char *name ;
struct header_list *next ;
} *header_head ;
/*
* The external routines we use.
*/
extern void copyfile() ;
#ifdef DEBUG
extern integer debug_flag ;
#endif
/*
* This more general routine adds a name to a list of unique
* names.
*/
int
add_name(s, what)
char *s ;
struct header_list **what ;
{
struct header_list *p, *q ;
for (p = *what ; p != NULL; p = p->next)
if (strcmp(p->name, s)==0)
return 0 ;
q = (struct header_list *)malloc((unsigned)sizeof(struct header_list)) ;
if (q==NULL)
error("! out of memory") ;
q->next = NULL ;
q->name = newstring(s) ;
if (*what == NULL)
*what = q ;
else {
for (p = *what; p->next != NULL; p = p->next) ;
p->next = q ;
}
return 1 ;
}
/*
* This routine is responsible for adding a header file.
*/
void add_header(s)
char *s ;
{
if (add_name(s, &header_head))
copyfile(s) ;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.