ftp.nice.ch/pub/next/text/tex/apps/TeXview-kp0.25.s.tar.gz#/TeXview-grey/dospecial.c

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 <kpathsea/tex-file.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 Boolean prescan;
extern void writeconsole() ;
extern Boolean firstpage ;
extern Boolean mocked ;
extern Boolean landscape, orientationset ;
extern int debugon ;
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.