home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / text / tex / pastex / source / dvips / dospecial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-28  |  19.2 KB  |  763 lines

  1. /*
  2.  *   This routine handles special commands;
  3.  *   predospecial() is for the prescan, dospecial() for the real thing.
  4.  */
  5. #include "dvips.h" /* The copyright notice in that file is included too! */
  6. #ifdef AMIGA
  7. #include "dospecial_protos.h"
  8. #include "dvips_protos.h"
  9. #include "dviinput_protos.h"
  10. #include "papersiz_protos.h"
  11. #include "header_protos.h"
  12. #include "color_protos.h"
  13. #include "finclude_protos.h"
  14. #include "search_protos.h"
  15. #include "emspecial_protos.h"
  16. #include "output_protos.h"
  17. #include "drawPS_protos.h"
  18. static void trytobreakout(register char *);
  19. static void dobs(register struct bangspecial *);
  20. #endif
  21.  
  22. #include <ctype.h>
  23. extern int atoi();
  24. extern void fil2ps();
  25. extern FILE *search();
  26. extern int system();
  27. /*
  28.  *   These are the external routines called:
  29.  */
  30. /**/
  31. #ifdef TPIC
  32. /*
  33.  * Fri Mar  9 1990  jourdan@minos.inria.fr (MJ)
  34.  * Upgraded to accommodate tpic release 2.0 extended output language.
  35.  * Should prove upward compatible!
  36.  */
  37. extern void setPenSize();
  38. extern void flushPath();
  39. extern void flushDashed();
  40. extern void flushDashed();
  41. extern void addPath();
  42. extern void arc();
  43. extern void flushSpline();
  44. extern void shadeLast();
  45. extern void whitenLast();
  46. extern void blackenLast();
  47. extern void SetShade() ;
  48. #endif
  49. extern shalfword dvibyte() ;
  50. extern int add_header() ;
  51. extern void hvpos() ;
  52. extern void figcopyfile() ;
  53. extern void nlcmdout() ;
  54. extern void cmdout() ;
  55. extern void numout() ;
  56. extern void scout() ;
  57. extern void stringend() ;
  58. extern void error() ;
  59. extern void psflush() ;
  60. extern void emspecial() ;
  61. /* IBM: color - begin */
  62. extern void pushcolor() ;
  63. extern void popcolor() ;
  64. extern void resetcolorstack() ;
  65. extern void background() ;
  66. /* IBM: color - end */
  67. extern char errbuf[] ;
  68. extern shalfword linepos;
  69. extern Boolean usesspecial ;
  70. extern Boolean usescolor ;   /* IBM: color */
  71. extern int landscape ;
  72. extern char *paperfmt ;
  73. extern char *nextstring;
  74. extern char *maxstring;
  75. extern char *oname;
  76. extern FILE *bitfile;
  77. extern int quiet;
  78. extern fontdesctype *curfnt ;
  79. extern int actualdpi ;
  80. extern int vactualdpi ;
  81. extern integer hh, vv;
  82. extern int lastfont ;
  83. extern real conv ;
  84. extern real vconv ;
  85. extern integer hpapersize, vpapersize ;
  86. extern Boolean pprescan ;
  87. extern char *figpath ;
  88. extern int prettycolumn ;
  89. extern Boolean disablecomments ;
  90.  
  91. #ifdef DEBUG
  92. extern integer debug_flag;
  93. #endif
  94. extern void scanfontcomments() ;
  95. extern void handlepapersize() ;
  96.  
  97. static int specialerrors = 20 ;
  98.  
  99. struct bangspecial {
  100.    struct bangspecial *next ;
  101.    char actualstuff[1] ; /* more space will actually be allocated */
  102. } *bangspecials = NULL ;
  103.  
  104. void specerror(s)
  105. char *s ;
  106. {
  107.    if (specialerrors > 0) {
  108.       error(s) ;
  109.       specialerrors-- ;
  110.    } else if (specialerrors == 0) {
  111.       error("more errors in special, being ignored . . .") ;
  112.       specialerrors-- ;
  113.    }
  114. }
  115.  
  116. static void trytobreakout(p)
  117. register char *p ;
  118. {
  119.    register int i ;
  120.    register int instring = 0 ;
  121.    int lastc = 0 ;
  122.  
  123.    i = 0 ;
  124.    (void)putc('\n', bitfile) ;
  125.    while (*p) {
  126.       if (i > 65 && *p == ' ' && instring == 0) {
  127.          (void)putc('\n', bitfile) ;
  128.          i = 0 ;
  129.       } else {
  130.          (void)putc(*p, bitfile) ;
  131.          i++ ;
  132.       }
  133.       if (*p == '(' && lastc != '\\')
  134.          instring = 1 ;
  135.       else if (*p == ')' && lastc != '\\')
  136.          instring = 0 ;
  137.       lastc = *p ;
  138.       p++ ;
  139.    }
  140.    (void)putc('\n', bitfile) ;
  141. }
  142.  
  143. static void dobs(q)
  144. register struct bangspecial *q ;
  145. {
  146.    if (q) {
  147.       dobs(q->next) ;
  148.       trytobreakout(q->actualstuff) ;
  149.    }
  150. }
  151.  
  152. void
  153. outbangspecials() {
  154.    if (bangspecials) {
  155.       cmdout("TeXDict") ;
  156.       cmdout("begin") ;
  157.       cmdout("@defspecial\n") ;
  158.       dobs(bangspecials) ;
  159.       cmdout("\n@fedspecial") ;
  160.       cmdout("end") ;
  161.    }
  162. }
  163.  
  164. /* We recommend that new specials be handled by the following general
  165.  * (and extensible) scheme, in which the user specifies one or more
  166.  * `key=value' pairs separated by spaces.
  167.  * The known keys are given in KeyTab; they take values
  168.  * of one of the following types:
  169.  *
  170.  * None: no value, just a keyword (in which case the = sign is omitted)
  171.  * String: the value should be "<string without double-quotes"
  172.  *                          or '<string without single-quotes'
  173.  * Integer: the value should be a decimal integer (%d format)
  174.  * Number: the value should be a decimal integer or real (%f format)
  175.  * Dimension: like Number, but will be multiplied by the scaledsize
  176.  *       of the current font and converted to default PostScript units
  177.  * (Actually, strings are allowed in all cases; the delimiting quotes
  178.  *  are simply stripped off if present.)
  179.  *
  180.  */
  181.  
  182. typedef enum {None, String, Integer, Number, Dimension} ValTyp;
  183. typedef struct {
  184.    char    *Entry;
  185.    ValTyp  Type;
  186. } KeyDesc;
  187.  
  188. #define NKEYS    (sizeof(KeyTab)/sizeof(KeyTab[0]))
  189.  
  190. KeyDesc KeyTab[] = {{"psfile",  String}, /* j==0 in the routine below */
  191.                     {"ifffile", String}, /* j==1 */
  192.                     {"tekfile", String}, /* j==2 */
  193.                     {"hsize",   Number},
  194.                     {"vsize",   Number},
  195.                     {"hoffset", Number},
  196.                     {"voffset", Number},
  197.                     {"hscale",  Number},
  198.                     {"vscale",  Number},
  199. #ifdef AMIGA
  200.                     {"scale",  Number},
  201. #endif /* AMIGA */
  202.                     {"angle",   Number},
  203.                     {"llx", Number},
  204.                     {"lly", Number},
  205.                     {"urx", Number},
  206.                     {"ury", Number},
  207.                     {"rwi", Number},
  208.                     {"rhi", Number},
  209.                     {"clip", None}};
  210.  
  211. #ifdef VMS
  212. #ifndef __GNUC__    /* GNUC tolower is too simple */
  213. #define Tolower tolower
  214. #endif
  215. #else
  216. #ifdef VMCMS    /* IBM: VM/CMS */
  217. #define Tolower __tolower
  218. #else
  219. #ifdef MVSXA    /* IBM: MVS/XA */
  220. #define Tolower __tolower
  221. #else
  222. /*
  223.  * compare strings, ignore case
  224.  */
  225. char Tolower(c)
  226. register char c ;
  227. {
  228.    if ('A' <= c && c <= 'Z')
  229. #ifdef AMIGA
  230.       return(char)(c+32);
  231. #else
  232.       return(c+32) ;
  233. #endif
  234.    else
  235.       return(c) ;
  236. }
  237. #endif
  238. #endif  /* IBM: VM/CMS */
  239. #endif
  240. int IsSame(a, b)
  241. char *a, *b;
  242. {
  243.    for( ; *a != '\0'; ) {
  244.       if( Tolower(*a) != Tolower(*b) ) 
  245.          return( 0 );
  246.       a++ ;
  247.       b++ ;
  248.    }
  249.    return( *b == '\0' );
  250. }
  251.  
  252. char *KeyStr, *ValStr ; /* Key and String values found */
  253. long ValInt ; /* Integer value found */
  254. float ValNum ; /* Number or Dimension value found */
  255.  
  256. char  *GetKeyVal(str,tno) /* returns NULL if none found, else next scan point */
  257.    char *str ; /* starting point for scan */
  258.    int  *tno ; /* table entry number of keyword, or -1 if keyword not found */
  259. {
  260.    register char *s ;
  261.    register int i ;
  262.    register char t ;
  263.  
  264.    for (s=str; *s <= ' ' && *s; s++) ; /* skip over blanks */
  265.    if (*s == '\0')
  266.       return (NULL) ;
  267.    KeyStr = s ;
  268.    while (*s>' ' && *s!='=') s++ ;
  269.    if (0 != (t = *s))
  270.       *s++ = 0 ;
  271.  
  272.    for(i=0; i<NKEYS; i++)
  273.       if( IsSame(KeyStr, KeyTab[i].Entry) )
  274.          goto found ;
  275.    *tno = -1;
  276.    return (s) ;
  277.  
  278. found: *tno = i ;
  279.    if (KeyTab[i].Type == None)
  280.       return (s) ;
  281.  
  282.    if (t && t <= ' ') {
  283.       for (; *s <= ' ' && *s; s++) ; /* now look for the value part */
  284.       if ((t = *s)=='=')
  285.          s++ ;
  286.    }
  287.    ValStr = "" ;
  288.    if ( t == '=' ) {
  289.       while (*s <= ' ' && *s)
  290.          s++ ;
  291.       if (*s=='\'' || *s=='\"')
  292.          t = *s++ ;               /* get string delimiter */
  293.       else t = ' ' ;
  294.       ValStr = s ;
  295.       while (*s!=t && *s)
  296.          s++ ;
  297.       if (*s)
  298.          *s++ = 0 ;
  299.    }
  300.    switch (KeyTab[i].Type) {
  301.  case Integer:
  302.       if(sscanf(ValStr,"%ld",&ValInt)!=1) {
  303.           sprintf(errbuf,"Non-integer value (%s) given for keyword %s",
  304.               ValStr, KeyStr) ;
  305.           specerror(errbuf) ;
  306.           ValInt = 0 ;
  307.       }
  308.       break ;
  309.  case Number:
  310.  case Dimension:
  311. #if defined(AMIGA) && defined(FLTTODBL)
  312.       if(sscanf(ValStr,"%lf",&ValNum)!=1) {
  313. #else
  314.       if(sscanf(ValStr,"%f",&ValNum)!=1) {  
  315. #endif
  316.           sprintf(errbuf,"Non-numeric value (%s) given for keyword %s",
  317.               ValStr, KeyStr) ;
  318.           specerror(errbuf) ;
  319.           ValNum = 0.0 ;
  320.       }
  321.       if (KeyTab[i].Type==Dimension) {
  322.          if (curfnt==NULL)
  323.             error("! No font selected") ;
  324.          ValNum = ValNum * ((double)curfnt->scaledsize) * conv * 72 / DPI ;
  325.       }
  326.       break ;
  327.  default: break ;
  328.    }
  329.    return (s) ;
  330. }
  331.  
  332. /*
  333.  *   Now our routines.  We get the number of bytes specified and place them
  334.  *   into the string buffer, and then parse it. Numerous conventions are
  335.  *   supported here for historical reasons.
  336.  *
  337.  *   To support GNUplot's horribly long specials, we go ahead and malloc a
  338.  *   new string buffer if necessary.
  339.  */
  340.  
  341. void predospecial(numbytes, scanning)
  342. integer numbytes ;
  343. Boolean scanning ;
  344. {
  345.    register char *p = nextstring ;
  346.    register int i = 0 ;
  347.    int j ;
  348.  
  349.    if (nextstring + numbytes > maxstring) {
  350.       p = nextstring = mymalloc(1000 + 2 * numbytes) ;
  351.       maxstring = nextstring + 2 * numbytes + 700 ;
  352.    }
  353.    for (i=numbytes; i>0; i--)
  354. #ifdef VMCMS /* IBM: VM/CMS */
  355.       *p++ = ascii2ebcdic[(char)dvibyte()] ;
  356. #else
  357. #ifdef MVSXA /* IBM: MVS/XA */
  358.       *p++ = ascii2ebcdic[(char)dvibyte()] ;
  359. #else
  360.       *p++ = (char)dvibyte() ;
  361. #endif /* IBM: VM/CMS */
  362. #endif
  363.    if (pprescan)
  364.       return ;
  365.    while (p[-1] <= ' ' && p > nextstring)
  366.       p-- ; /* trim trailing blanks */
  367.    if (p==nextstring) return ; /* all blank is no-op */
  368.    *p = 0 ;
  369.    p = nextstring ;
  370.    while (*p <= ' ')
  371.       p++ ;
  372. #ifdef DEBUG
  373.    if (dd(D_SPECIAL))
  374.       (void)fprintf(stderr, "Preprocessing special: %s\n", p) ;
  375. #endif
  376.  
  377. /*
  378.  *   We use strncmp() here to also pass things like landscape()
  379.  *   or landscape: or such.
  380.  */
  381.  
  382.    switch (*p) {
  383. case 'l':
  384.    if (strncmp(p, "landscape", 9)==0) {
  385.       if (hpapersize || vpapersize)
  386.          error(
  387.              "both landscape and papersize specified:  ignoring landscape") ;
  388.       else
  389.          landscape = 1 ;
  390.       return ;
  391.    }
  392.    break ;
  393. case 'p':
  394.    if (strncmp(p, "papersize", 9)==0) {
  395.       p += 9 ;
  396.       while (*p == '=' || *p == ' ')
  397.          p++ ;
  398.       if (hpapersize == 0 || vpapersize == 0) {
  399.          if (landscape) {
  400.             error(
  401.              "both landscape and papersize specified:  ignoring landscape") ;
  402.             landscape = 0 ;
  403.          }
  404.          handlepapersize(p, &hpapersize, &vpapersize) ;
  405.       }
  406.       return ;
  407.    }
  408.    break ;
  409. case 'x':
  410.    if (strncmp(p, "xtex:", 5)==0) return ;
  411.    break ;
  412. case 'h':
  413.    if (strncmp(p, "header", 6)==0) {
  414.       char *q ;
  415.       p += 6 ;
  416.       while ((*p <= ' ' || *p == '=' || *p == '(') && *p != 0)
  417.          p++ ;
  418.       q = p ;  /* we will remove enclosing parentheses */
  419.       p = p + strlen(p) - 1 ;
  420.       while ((*p <= ' ' || *p == ')') && p >= q)
  421.          p-- ;
  422.       p[1] = 0 ;
  423.       if (p >= q)
  424.          (void)add_header(q) ;
  425.    }
  426.    break ;
  427. /* IBM: color - added section here for color header and color history */
  428. case 'b':
  429.    if (strncmp(p, "background", 10) == 0) {
  430.       usescolor = 1 ;
  431.       p +=11 ;
  432.       while ( *p <= ' ' ) p++ ;
  433.       background(p) ;
  434.       return ;
  435.    }
  436.    break ;
  437. case 'c':
  438.    if (strncmp(p, "color", 5) == 0) {
  439.       usescolor = 1 ;
  440.       p += 6 ;
  441.       while ( *p <= ' ' ) p++ ;
  442.       if (strncmp(p, "push", 4) == 0 ) {
  443.          p += 5 ;
  444.          while ( *p <= ' ' ) p++ ;
  445.          pushcolor(p, 0) ;
  446.       } else if (strncmp(p, "pop", 3) == 0 ) {
  447.          popcolor(0) ;
  448.       } else {
  449.          resetcolorstack(p,0) ;
  450.       }
  451.    }   /* IBM: color - end changes */
  452.    break ;
  453. case '!':
  454.    {
  455.       register struct bangspecial *q ;
  456.       p++ ;
  457.       q = (struct bangspecial *)mymalloc((integer)
  458.                          (sizeof(struct bangspecial) + strlen(p))) ;
  459.       (void)strcpy(q->actualstuff, p) ;
  460.       q->next = bangspecials ;
  461.       bangspecials = q ;
  462.       usesspecial = 1 ;
  463.       return ;
  464.    }
  465.    break ;
  466. default:
  467.    break ;
  468.    }
  469.    usesspecial = 1 ;  /* now the special prolog will be sent */
  470.    if (scanning && *p != '"' && (p=GetKeyVal(p, &j)) != NULL && j==0)
  471.       scanfontcomments(ValStr) ;
  472. }
  473.  
  474. int maccess(s)
  475. char *s ;
  476. {
  477.    FILE *f = search(figpath, s, "r") ;
  478.    if (f)
  479.       fclose(f) ;
  480.    return (f != 0) ;
  481. }
  482.  
  483. char *tasks[] = { 0, "iff2ps", "tek2ps" } ;
  484.  
  485. static char psfile[511] ; 
  486. void dospecial(numbytes)
  487. integer numbytes ;
  488. {
  489.    register char *p = nextstring ;
  490.    register int i = 0 ;
  491.    int j, systemtype = 0 ;
  492.    register char *q ;
  493.    Boolean psfilewanted = 1 ;
  494.    char *task = 0 ;
  495.    char cmdbuf[111] ; 
  496.  
  497.    if (nextstring + i > maxstring)
  498.       error("! out of string space in dospecial") ;
  499.    for (i=numbytes; i>0; i--)
  500. #ifdef VMCMS /* IBM: VM/CMS */
  501.       *p++ = ascii2ebcdic[(char)dvibyte()] ;
  502. #else
  503. #ifdef MVSXA /* IBM: MVS/XA */
  504.       *p++ = ascii2ebcdic[(char)dvibyte()] ;
  505. #else
  506.       *p++ = (char)dvibyte() ;
  507. #endif  /* IBM: VM/CMS */
  508. #endif
  509.    while (p[-1] <= ' ' && p > nextstring)
  510.       p-- ; /* trim trailing blanks */
  511.    if (p==nextstring) return ; /* all blank is no-op */
  512.    *p = 0 ;
  513.    p = nextstring ;
  514.    while (*p <= ' ')
  515.       p++ ;
  516. #ifdef DEBUG
  517.    if (dd(D_SPECIAL))
  518.       (void)fprintf(stderr, "Processing special: %s\n", p) ;
  519. #endif
  520.  
  521.    switch (*p) {
  522. case 'e':
  523.    if (strncmp(p, "em:", 3)==0) {    /* emTeX specials in emspecial.c */
  524.     emspecial(p);
  525.     return;
  526.    }
  527.    break ;
  528. case 'p':
  529.    if (strncmp(p, "ps:", 3)==0) {
  530.         psflush() ; /* now anything can happen. */
  531.         if (p[3]==':') {
  532.            if (strncmp(p+4, "[begin]", 7) == 0) {
  533.               hvpos() ;
  534.               trytobreakout(&p[11]);
  535.            } else if (strncmp(p+4, "[end]", 5) == 0)
  536.               trytobreakout(&p[9]);
  537.            else trytobreakout(&p[4]);
  538.         } else if (strncmp(p+3, " plotfile ", 10) == 0) {
  539.              char *sfp ;
  540.              hvpos() ;
  541.              p += 13;
  542.            /*
  543.             *  Fixed to allow popen input for plotfile
  544.             *  TJD 10/20/91
  545.             */
  546.            while (*p == ' ') p++;
  547.            if (*p == '"') {
  548.              p++;
  549.              for (sfp = p; *sfp && *sfp != '"'; sfp++) ;
  550.            } else {
  551.              for (sfp = p; *sfp && *sfp != ' '; sfp++) ;
  552.            }
  553.            *sfp = '\0';
  554.            if (*p == '`') 
  555.              figcopyfile(p+1, 1);
  556.            else
  557.              figcopyfile (p, 0);
  558.            /* End TJD changes */
  559.         } else {
  560.            hvpos() ;
  561.            trytobreakout(&p[3]);
  562.            psflush() ;
  563.            hvpos() ;
  564.         }
  565.         return;
  566.    }
  567.    if (strncmp(p, "papersize", 9) == 0)
  568.       return ;
  569. #ifdef TPIC
  570.    if (strncmp(p, "pn ", 3) == 0) {setPenSize(p+2); return;}
  571.    if (strncmp(p, "pa ", 3) == 0) {addPath(p+2); return;}
  572. #endif
  573.    break ;
  574. case 'l':
  575.    if (strncmp(p, "landscape", 9)==0) return ;
  576.    break ;
  577. case '!':
  578.    return ;
  579. case 'h':
  580.    if (strncmp(p, "header", 6)==0) return ;
  581.    if (strncmp(p, "html:", 5)==0) return ;
  582. case 'w':
  583. case 'W':
  584.    if (strncmp(p+1, "arning", 6) == 0) {
  585.       static int maxwarns = 50 ;
  586.       if (maxwarns > 0) {
  587.          error(p) ;
  588.          maxwarns-- ;
  589.       } else if (maxwarns == 0) {
  590.          error(". . . rest of warnings suppressed") ;
  591.          maxwarns-- ;
  592.       }
  593.       return ;
  594.    }
  595. #ifdef TPIC
  596.    if (strcmp(p, "wh") == 0) {whitenLast(); return;}
  597. #endif
  598.    break ;
  599. case 'b':
  600.    if ( strncmp(p, "background", 10) == 0 )
  601.       return ; /* already handled in prescan */
  602. #ifdef TPIC
  603.    if (strcmp(p, "bk") == 0) {blackenLast(); return;}
  604. #endif
  605.    break ;
  606. case 'c':
  607.    if (strncmp(p, "color", 5) == 0) {
  608.       p += 6 ;
  609.       while ( *p <= ' ' ) p++ ;
  610.       if (strncmp(p, "push", 4) == 0 ) {
  611.          p += 4 ;
  612.          while ( *p <= ' ' ) p++ ;
  613.          pushcolor(p,1);
  614.       } else if (strncmp(p, "pop", 3) == 0 ) {
  615.          popcolor(1) ;
  616.       } else {
  617.          resetcolorstack(p,1) ;
  618.       }
  619.       return ;
  620.    } /* IBM: color - end changes*/
  621.    break ;
  622. case 'f':
  623. #ifdef TPIC
  624.    if (strcmp(p, "fp") == 0) {flushPath(0); return;}
  625. #endif
  626.    break ;
  627. case 'i':
  628. #ifdef TPIC
  629.    if (strcmp(p, "ip") == 0) {flushPath(1); return;} /* tpic 2.0 */
  630.    if (strncmp(p, "ia ", 3) == 0) {arc(p+2, 1); return;} /* tpic 2.0 */
  631. #endif
  632.    break ;
  633. case 'd':
  634. #ifdef TPIC
  635.    if (strncmp(p, "da ", 3) == 0) {flushDashed(p+2, 0); return;}
  636.    if (strncmp(p, "dt ", 3) == 0) {flushDashed(p+2, 1); return;}
  637. #endif
  638.    break ;
  639. case 's':
  640. #ifdef TPIC
  641.    if (strcmp(p, "sp") == 0) {flushSpline(p+2); return;} /* tpic 2.0 */
  642.    if (strncmp(p, "sp ", 3) == 0) {flushSpline(p+3); return;} /* tpic 2.0 */
  643.    if (strcmp(p, "sh") == 0) {shadeLast(p+2); return;} /* tpic 2.0 */
  644.    if (strncmp(p, "sh ", 3) == 0) {shadeLast(p+3); return;} /* tpic 2.0 */
  645. #endif
  646.    break ;
  647. case 'a':
  648. #ifdef TPIC
  649.    if (strncmp(p, "ar ", 3) == 0) {arc(p+2, 0); return;} /* tpic 2.0 */
  650. #endif
  651.    break ;
  652. case 't':
  653. #ifdef TPIC
  654.    if (strncmp(p, "tx ", 3) == 0) {SetShade(p+3); return;}
  655. #endif
  656.    break ;
  657. case '"':
  658.    hvpos() ;
  659.    cmdout("@beginspecial") ;
  660.    cmdout("@setspecial") ;
  661.    trytobreakout(p+1) ;
  662.    cmdout("\n@endspecial") ;
  663.    return ;
  664.    break ;
  665. default:
  666.    break ;
  667.    }
  668. /* At last we get to the key/value conventions */
  669.    psfile[0] = '\0';
  670.    hvpos();
  671.    cmdout("@beginspecial");
  672.  
  673.    while( (p=GetKeyVal(p,&j)) != NULL )
  674.       switch (j) {
  675.  case -1: /* for compatability with old conventions, we allow a file name
  676.            * to be given without the 'psfile=' keyword */
  677.          if (!psfile[0] && maccess(KeyStr)==0) /* yes we can read it */
  678.              (void)strcpy(psfile,KeyStr) ;
  679.          else {
  680.            sprintf(errbuf, "Unknown keyword (%s) in \\special will be ignored",
  681.                               KeyStr) ;
  682.            specerror(errbuf) ;
  683.          }
  684.          break ;
  685.  case 0: case 1: case 2: /* psfile */
  686.          if (psfile[0]) {
  687.            sprintf(errbuf, "More than one \\special %s given; %s ignored", 
  688.                     "psfile",  ValStr) ;
  689.            specerror(errbuf) ;
  690.          }
  691.          else (void)strcpy(psfile,ValStr) ;
  692.          task = tasks[j] ;
  693.          break ;
  694.  default: /* most keywords are output as PostScript procedure calls */
  695.          if (KeyTab[j].Type == Integer)
  696.             numout((integer)ValInt);
  697.          else if (KeyTab[j].Type == String)
  698.             for (q=ValStr; *q; q++)
  699.                scout(*q) ;
  700.          else if (KeyTab[j].Type == None) ;
  701.          else { /* Number or Dimension */
  702.             ValInt = (integer)(ValNum<0? ValNum-0.5 : ValNum+0.5) ;
  703.             if (ValInt-ValNum < 0.001 && ValInt-ValNum > -0.001)
  704.                 numout((integer)ValInt) ;
  705.             else {
  706.                (void)sprintf(cmdbuf, "%f", ValNum) ;
  707.                cmdout(cmdbuf) ;
  708.             }
  709.          }
  710.       (void)sprintf(cmdbuf, "@%s", KeyStr);
  711.       cmdout(cmdbuf) ;
  712.       }
  713.  
  714.    cmdout("@setspecial");
  715.  
  716.    if(psfile[0]) {
  717.       if (task == 0) {
  718.          systemtype = (psfile[0]=='`') ;
  719.          figcopyfile(psfile+systemtype, systemtype);
  720.       } else {
  721.          fil2ps(task, psfile) ;
  722.       }
  723.    } else if (psfilewanted)
  724.       specerror("No \\special psfile was given; figure will be blank") ;
  725.  
  726.    cmdout("@endspecial");
  727. }
  728.  
  729. extern char realnameoffile[] ;
  730. extern char *pictpath ;
  731.  
  732. void fil2ps(task, iname)
  733. char *task, *iname ;
  734. {
  735.    char cmd[400] ;
  736.    FILE *f ;
  737.    if (0 != (f=search(pictpath, iname, "r"))) {
  738.       fclose(f) ;
  739.    } else {
  740.       fprintf(stderr, " couldn't open %s\n", iname) ;
  741.       return ;
  742.    }
  743.    if (!quiet) {
  744.       fprintf(stderr, " [%s", realnameoffile) ;
  745.       fflush(stderr) ;
  746.    }
  747.    if (oname && oname[0] && oname[0] != '-') {
  748.       putc(10, bitfile) ;
  749.       fclose(bitfile) ;
  750.       sprintf(cmd, "%s -f %s %s", task, realnameoffile, oname) ;
  751.       system(cmd) ;
  752.       if ((bitfile=fopen(oname, "a"))==NULL)
  753.          error("! couldn't reopen PostScript file") ;
  754.       linepos = 0 ;
  755.    } else {
  756.       sprintf(cmd, "%s -f %s", task, realnameoffile) ;
  757.       system(cmd) ;
  758.    }
  759.    if (!quiet)
  760.       fprintf(stderr, "]") ;
  761. }
  762.  
  763.