home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / texmf / source / dvips / emspecial.c < prev    next >
C/C++ Source or Header  |  1994-09-28  |  36KB  |  1,521 lines

  1. /*
  2.  *   emspecial.c
  3.  *   This routine handles the emTeX special commands.
  4.  */
  5. #include "dvips.h" /* The copyright notice in that file is included too!*/
  6.  
  7. #include <ctype.h>
  8. #ifdef AMIGA
  9. #include <stdlib.h>
  10. #include "search_protos.h"
  11. #else
  12. extern int atoi();
  13. extern FILE *search();
  14. extern char *getenv();
  15. #endif
  16. /*
  17.  *   These are the external routines called:
  18.  */
  19. /**/
  20. #ifdef AMIGA
  21. #include "output_protos.h"
  22. #include "dvips_protos.h"
  23. #include "dospecial_protos.h"
  24. #else
  25. extern void hvpos() ;
  26. extern void cmdout() ;
  27. extern void mhexout() ;
  28. extern void nlcmdout() ;
  29. extern void newline() ;
  30. extern void floatout() ;
  31. extern void numout() ;
  32. extern void error() ;
  33. extern void specerror() ;
  34. #endif /* AMIGA */
  35. extern char errbuf[] ;
  36. extern shalfword linepos;
  37. extern FILE *bitfile;
  38. extern int actualdpi ;
  39. extern int vactualdpi ;
  40. extern integer hh, vv;
  41. extern char *figpath ;
  42. extern int prettycolumn ;
  43. extern int quiet;
  44. extern Boolean disablecomments ;
  45.  
  46. #ifdef DEBUG
  47. extern integer debug_flag;
  48. #endif
  49.  
  50.  
  51. #ifdef EMTEX
  52. /* emtex specials, added by rjl */
  53.  
  54. #define TRUE 1
  55. #define FALSE 0
  56.  
  57. #ifdef AMIGA
  58. static long emmax = 1613 ;
  59. #else
  60. static long emmax = 161 ;
  61. #endif /* AMIGA */
  62.  
  63. /*
  64.  *   We define these seek constants if they don't have their
  65.  *   values already defined.
  66.  */
  67. #ifndef SEEK_SET
  68. #define SEEK_SET (0)
  69. #endif
  70. #ifndef SEEK_END
  71. #define SEEK_END (2)
  72. #endif
  73.  
  74. struct empt {
  75.    struct empt *next ;
  76.    shalfword point;
  77.    integer x, y;
  78. };
  79.  
  80. static struct empt **empoints = NULL ;
  81. boolean emused = FALSE;  /* true if em points used on this page */
  82. integer emx, emy;
  83.  
  84. struct emunit {
  85.    char *unit;
  86.    float factor;
  87. };
  88. struct emunit emtable[] = {
  89.   {"pt",72.27},
  90.   {"pc",72.27/12},
  91.   {"in",1.0},
  92.   {"bp",72.0},
  93.   {"cm",2.54},
  94.   {"mm",25.4},
  95.   {"dd",72.27/(1238.0/1157)},
  96.   {"cc",72.27/12/(1238.0/1157)},
  97.   {"sp",72.27*65536},
  98.   {0,0.0}
  99. };
  100.  
  101.  
  102. /* clear the empoints array if necessary */
  103. #ifdef AMIGA
  104. #include "emspecial_protos.h"
  105. #endif
  106. void
  107. emclear()
  108. {
  109.    int i;
  110.    if (emused && empoints)
  111.       for (i=0; i<emmax; i++)
  112.          empoints[i] = 0 ;
  113.    emused = FALSE ;
  114. }
  115.  
  116. /* put an empoint into the empoints array */
  117. struct empt *emptput(point, x, y)
  118. shalfword point;
  119. integer x, y;
  120. {
  121.    struct empt *p ;
  122.    int start ;
  123.  
  124.    emused = TRUE;
  125.    start = point % emmax ;
  126.    p = empoints[start] ;
  127.    while ( p ) {
  128.       if ( p->point == point )
  129.          break;
  130.       p = p->next ;
  131.    }
  132.    if (p == 0) {
  133.       p = (struct empt *)mymalloc(sizeof(struct empt)) ;
  134.       p->next = empoints[start] ;
  135.       empoints[start] = p ;
  136.    }
  137.    p->point = point;
  138.    p->x = x;
  139.    p->y = y;
  140.    return(p) ;
  141. }
  142.  
  143. /* get an empoint from the empoints array */
  144. struct empt *emptget(point)
  145. shalfword point;
  146. {
  147.    struct empt *p ;
  148.    int start;
  149.  
  150.    start = point % emmax;
  151.    if (emused == TRUE) {
  152.       p = empoints[start] ;
  153.       while (p) {
  154.      if (p->point == point)
  155.         return p ;
  156.      p = p->next ;
  157.       }
  158.    }
  159.    sprintf(errbuf,"!em: point %d not defined",point);
  160.    specerror(errbuf);
  161.    return(NULL); /* never returns due to error */
  162. }
  163.  
  164.  
  165. /* convert width into dpi units */
  166. float emunits(width,unit)
  167. float width;
  168. char *unit;
  169. {
  170. struct emunit *p;
  171.     for (p=emtable; p->unit; p++) {
  172.        if (strcmp(p->unit,unit)==0)
  173.         return( width * actualdpi / p->factor );
  174.     }
  175.     return (-1.0); /* invalid unit */
  176. }
  177.  
  178. /* The main routine for \special{em:graph ...} called from dospecial.c */
  179. /* the line cut parameter is not supported (and is ignored) */
  180.  
  181. void emspecial(p)
  182. char *p ;
  183. {
  184. float emwidth, emheight;
  185. shalfword empoint1, empoint2;
  186. struct empt *empoint;
  187. char emunit[3];
  188. char emstr[80];
  189. char *emp;
  190. void emgraph();
  191.  
  192.         hvpos() ;
  193.     for (emp = p+3; *emp && isspace(*emp); emp++); /* skip blanks */
  194.     if (strncmp(emp, "linewidth", 9) == 0) {
  195.        /* code for linewidth */
  196.        for (emp = emp+9; *emp && isspace(*emp); emp++); /* skip blanks */
  197. #if defined(AMIGA) && defined(FLTTODBL)
  198.        sscanf(emp, "%lf%2s", &emwidth, emunit);
  199. #else
  200.        sscanf(emp, "%f%2s", &emwidth, emunit);
  201. #endif
  202.        emwidth = emunits(emwidth,emunit);
  203.        if (emwidth!=-1.0) {
  204.           sprintf(emstr,"%.1f setlinewidth", emwidth);
  205.           cmdout(emstr);
  206. #ifdef DEBUG
  207.    if (dd(D_SPECIAL))
  208.       (void)fprintf(stderr, "em special: Linewidth set to %.1f dots\n", 
  209.         emwidth) ;
  210. #endif
  211.        } else {
  212.           sprintf(errbuf,"Unknown em: special width");
  213.           specerror(errbuf);
  214.        }
  215.     }
  216.         else if (strncmp(emp, "moveto", 6) == 0) {
  217. #ifdef DEBUG
  218.    if (dd(D_SPECIAL))
  219. #ifdef SHORTINT
  220.       (void)fprintf(stderr, "em special: moveto %ld,%ld\n", hh, vv);
  221. #else
  222.       (void)fprintf(stderr, "em special: moveto %d,%d\n", hh, vv);
  223. #endif
  224. #endif
  225.            emx = hh;
  226.            emy = vv;
  227.         }
  228.         else if (strncmp(emp, "lineto", 6) == 0) {
  229. #ifdef DEBUG
  230.    if (dd(D_SPECIAL))
  231. #ifdef SHORTINT
  232.       (void)fprintf(stderr, "em special: lineto %ld,%ld\n", hh, vv);
  233. #else
  234.       (void)fprintf(stderr, "em special: lineto %d,%d\n", hh, vv);
  235. #endif
  236. #endif
  237.        cmdout("np");
  238.        numout(emx);
  239.        numout(emy);
  240.        cmdout("a");
  241.        numout(hh);
  242.        numout(vv);
  243.        cmdout("li");
  244.        cmdout("st");
  245.            emx = hh;
  246.            emy = vv;
  247.         }
  248.     else if (strncmp(emp, "point", 5) == 0) {
  249.            if (empoints == NULL) {
  250.               empoints = 
  251.               (struct empt **)mymalloc((integer)emmax * sizeof(struct empt *)) ;
  252.               emused = TRUE;
  253.               emclear();
  254.            }
  255.        for (emp = emp+5; *emp && isspace(*emp); emp++); /* skip blanks */
  256.            empoint1 = (shalfword)atoi(emp);
  257.            empoint = emptput(empoint1,hh,vv);
  258. #ifdef DEBUG
  259.    if (dd(D_SPECIAL))
  260. #ifdef SHORTINT
  261.       (void)fprintf(stderr, "em special: Point %d is %ld,%ld\n",
  262. #else
  263.       (void)fprintf(stderr, "em special: Point %d is %d,%d\n",
  264. #endif
  265.         empoint->point, empoint->x, empoint->y) ;
  266. #endif
  267.     }
  268.     else if (strncmp(emp, "line", 4) == 0) {
  269.        for (emp = emp+4; *emp && isspace(*emp); emp++); /* skip blanks */
  270.            empoint1 = (shalfword)atoi(emp);
  271.        for (; *emp && isdigit(*emp); emp++); /* skip point 1 */
  272.        if ( *emp && strchr("hvp",*emp)!=0 )
  273.           emp++;  /* skip line cut */
  274.        for (; *emp && isspace(*emp); emp++); /* skip blanks */
  275.        if ( *emp && (*emp==',') )
  276.           emp++; /*  skip comma separator */
  277.        for (; *emp && isspace(*emp); emp++); /* skip blanks */
  278.            empoint2 = (shalfword)atoi(emp);
  279.        for (; *emp && isdigit(*emp); emp++); /* skip point 2 */
  280.        if ( *emp && strchr("hvp",*emp)!=0 )
  281.           emp++;  /* skip line cut */
  282.        for (; *emp && isspace(*emp); emp++); /* skip blanks */
  283.        if ( *emp && (*emp==',') )
  284.           emp++; /*  skip comma separator */
  285.        emwidth = -1.0;
  286.        emunit[0]='\0';
  287. #if defined(AMIGA) && defined(FLTTODBL)
  288.        sscanf(emp, "%lf%2s", &emwidth, emunit);
  289. #else
  290.        sscanf(emp, "%f%2s", &emwidth, emunit);
  291. #endif
  292.        emwidth = emunits(emwidth,emunit);
  293. #ifdef DEBUG
  294.    if (dd(D_SPECIAL))
  295.       (void)fprintf(stderr, "em special: Line from point %d to point %d\n",
  296.         empoint1, empoint2) ;
  297. #endif
  298.        cmdout("np");
  299.        if (emwidth!=-1.0) {
  300. #ifdef DEBUG
  301.    if (dd(D_SPECIAL))
  302.    (void)fprintf(stderr,"em special: Linewidth temporarily set to %.1f dots\n", 
  303.         emwidth) ;
  304. #endif
  305.            strcpy(emstr,"currentlinewidth");
  306.            cmdout(emstr);
  307.             sprintf(emstr,"%.1f setlinewidth", emwidth);
  308.             cmdout(emstr);
  309.        }
  310.            empoint = emptget(empoint1);
  311.        numout(empoint->x);
  312.        numout(empoint->y);
  313.        cmdout("a");
  314.            empoint = emptget(empoint2);
  315.        numout(empoint->x);
  316.        numout(empoint->y);
  317.        cmdout("li");
  318.        cmdout("st");
  319.        if (emwidth!=-1.0) {
  320.            strcpy(emstr,"setlinewidth");
  321.            cmdout(emstr);
  322.        }
  323.     }
  324.     else if (strncmp(emp, "message", 7) == 0) {
  325.            (void)fprintf(stderr, "em message: %s\n", emp+7) ;
  326.     }
  327.     else if (strncmp(emp, "graph", 5) == 0) {
  328.        int i;
  329.        for (emp = emp+5; *emp && isspace(*emp); emp++); /* skip blanks */
  330.        for (i=0; *emp && !isspace(*emp) && !(*emp==',') ; emp++)
  331.           emstr[i++] = *emp; /* copy filename */
  332.        emstr[i] = '\0';
  333.        /* now get optional width and height */
  334.        emwidth = emheight = -1.0;    /* no dimension is <= 0 */
  335.        for (; *emp && ( isspace(*emp) || (*emp==',') ); emp++)
  336.           ;  /* skip blanks and comma */
  337.        if (*emp) {
  338. #if defined(AMIGA) && defined(FLTTODBL)
  339.           sscanf(emp, "%lf%2s", &emwidth, emunit); /* read width */
  340. #else
  341.           sscanf(emp, "%f%2s", &emwidth, emunit); /* read width */
  342. #endif
  343.           emwidth = emunits(emwidth,emunit); /* convert to pixels */
  344.           for (; *emp && (*emp=='.'||isdigit(*emp)||isalpha(*emp)); emp++)
  345.              ; /* skip width dimension */
  346.           for (; *emp && ( isspace(*emp) || (*emp==',') ); emp++)
  347.              ;  /* skip blanks and comma */
  348.           if (*emp) {
  349. #if defined(AMIGA) && defined(FLTTODBL)
  350.              sscanf(emp, "%lf%2s", &emheight, emunit); /* read height */
  351. #else
  352.              sscanf(emp, "%f%2s", &emheight, emunit); /* read height */
  353. #endif
  354.              emheight = emunits(emheight,emunit)*vactualdpi/actualdpi;
  355.           }
  356.        }
  357.        if (emstr[0]) {
  358.           emgraph(emstr,emwidth,emheight);
  359.        }
  360.        else {
  361.               (void)fprintf(stderr, "em:graph: no file given\n") ;
  362.        }
  363.     }
  364.     else {
  365.            sprintf(errbuf, 
  366.           "Unknown em: command (%s) in \\special will be ignored", p);
  367.            specerror(errbuf) ;
  368.     }
  369.     return;
  370.    }
  371.  
  372.  
  373. /* em:graph routines */
  374.  
  375. /* The graphics routines currently decode 3 types of IBM-PC based graphics   */
  376. /* files: .pcx, .bmp, .msp. The information on the formats has occasionally  */
  377. /* been sketchy, and subject to interpretation. I have attempted to implement*/
  378. /* these routines to correctly decode the graphics file types mentioned.     */
  379. /* The compressed .bmp file type has not been tested fully due to a lack of  */
  380. /* test files.                                                               */
  381. /*                                                                           */
  382. /* The method of reading in the headers of the binary files is ungainly, but */
  383. /* portable. Failure to use a byte by byte read and convert method will      */
  384. /* result in portability problems. Specifically there is no requirement that */
  385. /* elements of a C structure be contiguous, only that they have an ascending */
  386. /* order of addresses.                                                       */
  387. /*                                                                           */
  388. /* The current implementations of the graphics format to postscript          */
  389. /* conversion are not the most efficient possible. Specifically: color       */
  390. /* formats are converted to RGB ratios prior to using a simple thresholding  */
  391. /* method to determine if the postscript bit is to be set. The thresholding  */
  392. /* method is compabible with that used in emtex's drivers.                   */
  393. /*                                                                           */
  394. /* Please send bug reports relating to the em:graph routines to:             */
  395. /*                maurice@bruce.cs.monash.edu.au                             */
  396. /*                                                                           */
  397. /* My thanks to Russell Lang for his assistance with the implementation of   */
  398. /* these routines in a manner compatible with dvips and for the optimization */
  399. /* of some routines.                                                         */
  400. /*                                                                           */
  401. /*                                                   Maurice Castro          */
  402. /*                                                   8 Oct 92                */
  403.  
  404. /* Routines to read binary numbers from IBM PC file types */
  405. integer readinteger(f)
  406. FILE *f;
  407. {
  408.    integer i;
  409.    int r;
  410.  
  411.    i = 0;
  412.    for (r = 0; r < 4; r++)
  413.    {
  414.       i = i |  ( ((integer) fgetc(f)) << (8*r) );
  415.    }
  416.    return(i);
  417. }
  418.  
  419. halfword readhalfword(f)
  420. FILE *f;
  421. {
  422.    halfword i;
  423.    int r;
  424.  
  425.    i = 0;
  426.    for (r = 0; r < 2; r++)
  427.    {
  428.      i = i |  ( ((halfword) fgetc(f)) << (8*r) );
  429.    }
  430.    return(i);
  431. }
  432.  
  433. #define readquarterword(f) ((unsigned char)fgetc(f))
  434. #define tobyte(x) ((x/8) + (x%8 ? 1 : 0))
  435.  
  436. /* These routines will decode PCX files produced by Microsoft 
  437.  * Windows Paint.  Other programs may not produce files which
  438.  * will be successfully decoded, most notably version 1.xx of
  439.  * PC Paint. */
  440.  
  441. /*
  442.  *   Type declarations.  integer must be a 32-bit signed; shalfword must
  443.  *   be a sixteen-bit signed; halfword must be a sixteen-bit unsigned;
  444.  *   quarterword must be an eight-bit unsigned.
  445.  */
  446. #ifndef AMIGA /* already defined in "emspecial_protos.h" */
  447. typedef struct 
  448. {
  449.     quarterword man;
  450.     quarterword ver;
  451.     quarterword enc;
  452.     quarterword bitperpix;
  453.     halfword xmin;
  454.     halfword ymin;
  455.     halfword xmax;
  456.     halfword ymax;
  457.     halfword hres;
  458.     halfword vres;
  459.     quarterword pal[48];
  460.     quarterword reserved;
  461.     quarterword colorplanes;
  462.     halfword byteperline;
  463.     halfword paltype;
  464.     quarterword fill[58];
  465. } PCXHEAD; 
  466. #endif /* AMIGA */
  467.  
  468. int PCXreadhead(pcxf, pcxh)
  469. FILE *pcxf;
  470. PCXHEAD *pcxh;
  471. {
  472.     pcxh->man = readquarterword(pcxf);
  473.     pcxh->ver = readquarterword(pcxf);
  474.     pcxh->enc = readquarterword(pcxf);
  475.     pcxh->bitperpix = readquarterword(pcxf);
  476.     pcxh->xmin = readhalfword(pcxf);
  477.     pcxh->ymin = readhalfword(pcxf);
  478.     pcxh->xmax = readhalfword(pcxf);
  479.     pcxh->ymax = readhalfword(pcxf);
  480.     pcxh->hres = readhalfword(pcxf);
  481.     pcxh->vres = readhalfword(pcxf);
  482.     fread(pcxh->pal, 1, 48, pcxf);
  483.     pcxh->reserved = readquarterword(pcxf);
  484.     pcxh->colorplanes = readquarterword(pcxf);
  485.     pcxh->byteperline = readhalfword(pcxf);
  486.     pcxh->paltype = readhalfword(pcxf);
  487.     fread(pcxh->fill, 1, 58, pcxf);
  488.  
  489.     if (feof(pcxf))
  490.         return(0);                /* fail */
  491.     if (pcxh->man != 0x0a)
  492.         return(0);                /* fail */
  493.     if (pcxh->enc != 0x1)
  494.         return(0);                /* fail */
  495.     return(1);                    /* success */
  496.     }
  497.  
  498. int PCXreadline(pcxf, pcxbuf, byteperline)
  499. FILE *pcxf;
  500. unsigned char *pcxbuf;
  501. unsigned int byteperline;
  502. {
  503.     int n;
  504.     int c;
  505.     int i;
  506.  
  507.     n = 0;
  508.     memset(pcxbuf,0,byteperline);
  509.     do {
  510.         c = fgetc(pcxf);
  511.         if ((c & 0xc0) == 0xc0) {
  512.             i = c & 0x3f;
  513.             c = fgetc(pcxf) & 0xff;
  514.             while ((i--) && (n < byteperline)) pcxbuf[n++] = c;
  515.         }
  516.         else {
  517.             pcxbuf[n++] = c & 0xff;
  518.         }
  519.     } while (n < byteperline);
  520.     if (c==EOF) n=0;
  521.     return(n);
  522. }
  523.  
  524. void PCXgetpalette(pcxf, pcxh, r, g, b)
  525. FILE *pcxf;
  526. PCXHEAD *pcxh;
  527. unsigned char r[256];
  528. unsigned char g[256];
  529. unsigned char b[256];
  530. {
  531.     int i;
  532.  
  533.     /* clear palette */
  534.     for (i=0; i < 256; i++) {
  535.         r[i] = 0;
  536.         g[i] = 0;
  537.         b[i] = 0;
  538.     }
  539.  
  540.     switch (pcxh->ver) {
  541.         case 0:
  542.             /* version 2.5 of PC Paint Brush */
  543.             for (i=0; i < 16; i++) {
  544.                 r[i] = pcxh->pal[i*3];
  545.                 g[i] = pcxh->pal[i*3+1];
  546.                 b[i] = pcxh->pal[i*3+2];
  547.             }
  548.             break;
  549.         case 2:
  550.             if (pcxh->colorplanes != 1) {
  551.                 /* version 2.8 of PC Paint Brush with valid Palette */
  552.             for (i=0; i < 16; i++) {
  553.                 r[i] = pcxh->pal[i*3];
  554.                 g[i] = pcxh->pal[i*3+1];
  555.                 b[i] = pcxh->pal[i*3+2];
  556.                 }
  557.             }
  558.             else {    /* not sure if this is correct - rjl */
  559.                 /* mono palette */
  560.                 r[0] = 0x00; g[0] = 0x00; b[0] = 0x00;
  561.                 r[1] = 0xff; g[1] = 0xff; b[1] = 0xff;
  562.             }
  563.             break;
  564.         case 3:
  565.             /* version 2.8 of PC Paint Brush with no valid Palette */
  566.             /* either mono or default */
  567.  
  568.             if (pcxh->colorplanes != 1) {
  569.                 /* Color default palette - should be checked */
  570.                 r[0] = 0x00;        g[0] = 0x00;        b[0] = 0x00;
  571.                 r[1] = 0x80;        g[1] = 0x00;         b[1] = 0x00;
  572.                 r[2] = 0x00;         g[2] = 0x80;         b[2] = 0x00;
  573.                 r[3] = 0x80;        g[3] = 0x80;         b[3] = 0x00;
  574.                 r[4] = 0x00;        g[4] = 0x00;         b[4] = 0x80;
  575.                 r[5] = 0x80;        g[5] = 0x00;         b[5] = 0x80;
  576.                 r[6] = 0x00;        g[6] = 0x80;         b[6] = 0x80;
  577.                 r[7] = 0x80;        g[7] = 0x80;         b[7] = 0x80;
  578.                 r[8] = 0xc0;        g[8] = 0xc0;        b[8] = 0xc0;
  579.                 r[9] = 0xff;        g[9] = 0x00;         b[9] = 0x00;
  580.                 r[10] = 0x00;         g[10] = 0xff;         b[10] = 0x00;
  581.                 r[11] = 0xff;         g[11] = 0xff;         b[11] = 0x00;
  582.                 r[12] = 0x00;         g[12] = 0x00;         b[12] = 0xff;
  583.                 r[13] = 0xff;         g[13] = 0x00;         b[13] = 0xff;
  584.                 r[14] = 0x00;         g[14] = 0xff;         b[14] = 0xff;
  585.                 r[15] = 0xff;         g[15] = 0xff;         b[15] = 0xff;
  586.             }
  587.             else {
  588.                 /* mono palette */
  589.                 r[0] = 0x00;        g[0] = 0x00;        b[0] = 0x00;
  590.                 r[1] = 0xff;        g[1] = 0xff;         b[1] = 0xff;
  591.             }
  592.             break;
  593.         case 5:
  594.         default:
  595.             /* version 3.0 of PC Paint Brush or Better */
  596.             fseek(pcxf, -769L, SEEK_END);
  597.             /* if signature byte is correct then read the palette */
  598.             /* otherwise copy the existing palette */
  599.             if (fgetc(pcxf) == 12) {
  600.                 for (i=0; i < 256; i++) {
  601.                     r[i] = fgetc(pcxf);
  602.                     g[i] = fgetc(pcxf);
  603.                     b[i] = fgetc(pcxf);
  604.                 }
  605.             }
  606.             else {
  607.                 for (i=0; i < 16; i++) {
  608.                     r[i] = pcxh->pal[i*3];
  609.                     g[i] = pcxh->pal[i*3+1];
  610.                     b[i] = pcxh->pal[i*3+2];
  611.                 }
  612.             }
  613.             break;
  614.     }
  615. }
  616.  
  617. extern void mhexout() ;
  618.  
  619. void PCXshowpicture(pcxf, wide, high, bytes, cp, bp, r, g, b)
  620. FILE *pcxf;
  621. int wide;
  622. int high;
  623. int bytes;
  624. int cp;
  625. int bp;
  626. unsigned char r[256];
  627. unsigned char g[256];
  628. unsigned char b[256];
  629. {
  630.     int x;
  631.     int y;
  632.     int c;
  633.     unsigned char *rowa[4];                /* row array */
  634.     unsigned char *row;
  635.     int p;
  636.     unsigned char *pshexa;
  637.     int xdiv, xmod, xbit;
  638.     int width;
  639.     int bytewidth;
  640.  
  641.     bytewidth = tobyte(wide);
  642.     width = bytewidth * 8;
  643.  
  644.     /* output the postscript image size preamble */
  645.     cmdout("/picstr ");
  646.     numout((integer)tobyte(wide));
  647.     cmdout("string def");
  648.  
  649.     numout((integer)width);
  650.     numout((integer)high);
  651.     numout((integer)1);
  652.     newline();
  653.  
  654.     cmdout("[");
  655.     numout((integer)width);
  656.     numout((integer)0);
  657.     numout((integer)0);
  658.     numout((integer)-high);
  659.     numout((integer)0);
  660.     numout((integer)0);
  661.     cmdout("]");
  662.  
  663.     nlcmdout("{currentfile picstr readhexstring pop} image");
  664.  
  665.     /* allocate the postscript hex output array */
  666.     pshexa = (unsigned char *) mymalloc((integer)bytewidth);
  667.  
  668.     /* make sure that you start at the right point in the file */
  669.     fseek(pcxf, (long) sizeof(PCXHEAD), SEEK_SET);
  670.  
  671.     /* malloc the lines */
  672.     row = (unsigned char *) mymalloc((integer)bytes * cp);
  673.     for (c = 0; c < cp; c++)
  674.         rowa[c] = row + bytes*c;
  675.  
  676.     for (y = 0; y < high; y++) {
  677.         /* clear the postscript hex array */
  678.         memset(pshexa,0xff,bytewidth);
  679.  
  680.         /* read in all the color planes for a row of pixels */
  681.         PCXreadline(pcxf, rowa[0], bytes*cp);
  682.  
  683.         /* process each pixel */
  684.         for (x = 0; x < wide; x++) {
  685.             /* build up the pixel value from color plane entries */
  686.             p = 0;
  687.             xdiv = x>>3;
  688.             xmod = 7 - (x&7);
  689.             xbit = 1 << xmod;
  690.             switch(bp) {
  691.                 case 1: 
  692.                     for (c = 0; c < cp; c++) {
  693.                         row = rowa[c];
  694.                         p |= ( (unsigned)(row[xdiv] & xbit) >> xmod ) << c;
  695.                     }
  696.                     break;
  697.                 case 4:  /* untested - most programs use 1 bit/pixel, 4 planes */
  698.                     row = rowa[0]; /* assume single plane */
  699.                     p = ( x & 1 ? row[xdiv] : row[xdiv]>>4 ) & 0x0f;
  700.                     break;
  701.                 case 8:
  702.                     row = rowa[0]; /* assume single plane */
  703.                     p = (unsigned) (row[x]);
  704.                     break;
  705.                 default: 
  706.                     fprintf(stderr, "em:graph: Unable to Decode this PCX file\n");
  707.                     return;
  708.             }
  709.             if ((r[p] < 0xff) || (g[p] < 0xff) || (b[p] < 0xff))
  710.                 pshexa[xdiv] &= (~xbit);
  711.             else
  712.                 pshexa[xdiv] |= xbit;
  713.         }
  714.         newline();
  715.         mhexout(pshexa,(long)bytewidth);
  716.     }
  717.     free(pshexa);
  718.     free(rowa[0]);
  719. }
  720.  
  721. void imagehead(filename,wide,high,emwidth,emheight)
  722. char filename[];
  723. int wide, high;
  724. float emwidth, emheight;    /* dimension in pixels */
  725. {
  726.     if (!quiet) {
  727.         if (strlen(filename) + prettycolumn > STDOUTSIZE) {
  728.         fprintf(stderr,"\n");
  729.         prettycolumn = 0;
  730.         }
  731.         (void)fprintf(stderr,"<%s",filename);
  732.         (void)fflush(stderr);
  733.         prettycolumn += 2+strlen(filename);
  734.     }
  735.     hvpos();
  736.     nlcmdout("@beginspecial @setspecial") ;
  737.     if (!disablecomments) {
  738.         cmdout("%%BeginDocument: em:graph");
  739.         cmdout(filename);
  740.         newline();
  741.     }
  742.     /* set the image size */
  743.     if (emwidth <= 0.0)  emwidth = (float)wide;
  744.     if (emheight <= 0.0)  emheight = (float)high;
  745.     floatout(emwidth*72/actualdpi);
  746.     floatout(emheight*72/vactualdpi);
  747.     newline();
  748.     cmdout("scale");
  749. #ifdef DEBUG
  750.     if (dd(D_SPECIAL)) {
  751.       (void)fprintf(stderr, 
  752.         "\nem:graph: %s width  %d pixels scaled to %.1f pixels\n",
  753.         filename, wide, emwidth);
  754.       (void)fprintf(stderr, 
  755.         "em:graph: %s height %d pixels scaled to %.1f pixels\n",
  756.         filename, high, emheight);
  757.        }
  758. #endif
  759. }
  760.  
  761. void imagetail()
  762. {
  763.     if (!disablecomments) {
  764.         (void)fprintf(bitfile, "\n%%%%EndDocument\n") ;
  765.         linepos = 0;
  766.     }
  767.     nlcmdout("@endspecial") ;
  768.     if (!quiet) {
  769.         (void)fprintf(stderr,">");
  770.         (void)fflush(stderr);
  771.     }
  772. }
  773.  
  774. void pcxgraph(pcxf,filename,emwidth,emheight)
  775. FILE *pcxf;
  776. char filename[];
  777. float emwidth, emheight;    /* dimension in pixels */
  778. {
  779.     PCXHEAD pcxh;
  780.     unsigned char red[256];
  781.     unsigned char green[256];
  782.     unsigned char blue[256];
  783.     int wide;
  784.     int high;
  785.     int bytes;
  786.     int cp;
  787.     int bpp;
  788.  
  789.     if (!PCXreadhead(pcxf, &pcxh)) {
  790.         sprintf(errbuf,"em:graph: Unable to Read Valid PCX Header");
  791.         specerror(errbuf);
  792.     }
  793.     PCXgetpalette(pcxf, &pcxh, red, green, blue);
  794.  
  795.     /* picture size calculation */
  796.     wide = (pcxh.xmax - pcxh.xmin) + 1;
  797.     high = (pcxh.ymax - pcxh.ymin) + 1;
  798.     bytes = pcxh.byteperline;
  799.     cp = pcxh.colorplanes;
  800.     bpp = pcxh.bitperpix;
  801.  
  802.     imagehead(filename,wide,high,emwidth,emheight);
  803.     PCXshowpicture(pcxf, wide, high, bytes, cp, bpp, red, green, blue);
  804.     imagetail();
  805. }
  806.  
  807. /* Microsoft Paint routines */
  808. struct wpnt_1 {
  809.     quarterword id[4];
  810.     halfword width;
  811.     halfword high;
  812.     halfword x_asp;
  813.     halfword y_asp;
  814.     halfword x_asp_prn;
  815.     halfword y_asp_prn;
  816.     halfword width_prn;
  817.     halfword high_prn;
  818.     integer chk_sum;
  819.     halfword chk_head;
  820. };
  821.  
  822. #define WPAINT_1 1
  823. #define WPAINT_2 2
  824.  
  825. void MSP_2_ps(f, wide, high)
  826. FILE *f;
  827. int wide;
  828. int high;
  829. {
  830.     char *line;
  831.     char *l;
  832.     int i;
  833.     int j;
  834.     unsigned char a, b, c;
  835.     int d;
  836.     int width;
  837.     halfword *linelen;
  838.  
  839.     /* an undocumented format - based on a type of run length encoding    */
  840.     /* the format is made up of a list of line lengths, followed by a set */
  841.     /* of lines. Each line is made up of 2 types of entries:              */
  842.     /*     1) A 3 term entry (0 a b): the byte b is repeated a times     */
  843.     /*    2) A variable length entry (a xxxx....xxxx): a bytes are read */
  844.     /*       from the file.                                             */
  845.     /* These entries are combined to build up a line                      */
  846.  
  847.     width = tobyte(wide)*8;
  848.  
  849.     /* output the postscript image size preamble */
  850.     cmdout("/picstr");
  851.     numout((integer)tobyte(wide));
  852.     cmdout("string def");
  853.  
  854.     numout((integer)width);
  855.     numout((integer)high);
  856.     numout((integer)1);
  857.  
  858.     cmdout("[");
  859.     numout((integer)width);
  860.     numout((integer)0);
  861.     numout((integer)0);
  862.     numout((integer)-high);
  863.     numout((integer)0);
  864.     numout((integer)0);
  865.     cmdout("]");
  866.  
  867.     nlcmdout("{currentfile picstr readhexstring pop} image");
  868.  
  869.     fseek(f, 32, SEEK_SET);
  870.  
  871.     /* read in the table of line lengths */    
  872.     linelen = (halfword *) mymalloc((integer)sizeof(halfword) * high);
  873.     for (i = 0; i < high; i++) {
  874.         linelen[i] = readhalfword(f);
  875.         if (feof(f))
  876.             return;
  877.     }
  878.  
  879.     line = (char *) mymalloc((integer)tobyte(wide));
  880.     for (i = 0; i < high; i++) {
  881.         memset(line, 0xff, tobyte(wide));
  882.         l = line;
  883.         if (linelen[i] != 0) {
  884.             d = linelen[i];
  885.             while (d) {
  886.                 a = fgetc(f);
  887.                 d--;
  888.                 if (a == 0) {
  889.                     b = fgetc(f);
  890.                     c = fgetc(f);
  891.                     d -= 2;
  892.                     for (j = 0; j < b; j++)
  893.                         *l++ = c;
  894.                 }
  895.                 else {
  896.                     for (j = 0; j < a; j++)
  897.                         *l++ = fgetc(f);
  898.                     d -= j;
  899.                 }
  900.             }
  901.         }
  902.         newline();
  903.         mhexout(line,(long)tobyte(wide));
  904.     }
  905.     free(linelen);
  906.     free(line);
  907. }
  908.  
  909. void MSP_1_ps(f, wide, high)
  910. FILE *f;
  911. int wide;
  912. int high;
  913. {
  914.     char *line;
  915.     int i;
  916.     int width;
  917.  
  918.     width = tobyte(wide)*8;
  919.     /* an partly documented format - see The PC Sourcebook                */
  920.     /* the format is made up of a simple bitmap.                          */
  921.  
  922.     /* output the postscript image size preamble */
  923.     cmdout("/picstr");
  924.     numout((integer)tobyte(wide));
  925.     cmdout("string def");
  926.  
  927.     numout((integer)width);
  928.     numout((integer)high);
  929.     numout((integer)1);
  930.  
  931.     cmdout("[");
  932.     numout((integer)width);
  933.     numout((integer)0);
  934.     numout((integer)0);
  935.     numout((integer)-high);
  936.     numout((integer)0);
  937.     numout((integer)0);
  938.     cmdout("]");
  939.  
  940.     nlcmdout("{currentfile picstr readhexstring pop} image");
  941.  
  942.     fseek(f, 32, SEEK_SET);
  943.  
  944.     line = (char *) mymalloc((integer)tobyte(wide));
  945.     for (i = 0; i < high; i++) {
  946.         fread(line, 1, tobyte(wide), f);
  947.         newline();
  948.         mhexout(line,(long)tobyte(wide));
  949.     }
  950.     free(line);
  951. }
  952.  
  953.  
  954. void mspgraph(f,filename,emwidth,emheight)
  955. FILE *f;
  956. char filename[];
  957. float emwidth, emheight;    /* dimension in pixels */
  958. {
  959.     struct wpnt_1 head;
  960.     int paint_type = 0;
  961.  
  962.         /* read the header of the file and figure out what it is */
  963.     fread(head.id, 1, 4, f);
  964.     head.width = readhalfword(f); 
  965.     head.high = readhalfword(f); 
  966.     head.x_asp = readhalfword(f); 
  967.     head.y_asp = readhalfword(f); 
  968.     head.x_asp_prn = readhalfword(f); 
  969.     head.y_asp_prn = readhalfword(f); 
  970.     head.width_prn = readhalfword(f); 
  971.     head.high_prn = readhalfword(f); 
  972.     head.chk_sum = readinteger(f); 
  973.     head.chk_head = readhalfword(f); 
  974.  
  975.     if (feof(f)) {
  976.         fprintf(stderr, "em:graph: Unable to Read Valid MSP Header\n");
  977.         return;
  978.     }
  979.         
  980.         /* check the id bytes */
  981.     if (!memcmp(head.id, "DanM", 4))
  982.             paint_type = WPAINT_1;
  983.     if (!memcmp(head.id, "LinS", 4))
  984.         paint_type = WPAINT_2;
  985.  
  986.  
  987.     imagehead(filename,head.width,head.high,emwidth,emheight);
  988.     switch (paint_type) {
  989.         case WPAINT_1:
  990.                     MSP_1_ps(f, head.width, head.high);
  991.             break;
  992.                 case WPAINT_2:
  993.                     MSP_2_ps(f, head.width, head.high);
  994.             break;
  995.         default:
  996.             sprintf(errbuf, "em:graph: Unknown MSP File Type");
  997.             specerror(errbuf);
  998.     }
  999.     imagetail() ;
  1000. }
  1001.  
  1002. /* ------------------------------------------------------------------------ */
  1003. /* .BMP file structures */
  1004. struct rgbquad {
  1005.     char blue;
  1006.     char green;
  1007.     char red;
  1008.     char res;
  1009. };
  1010.  
  1011. struct bitmapinfoheader {
  1012.     integer size;
  1013.     integer width;
  1014.     integer height;
  1015.     halfword planes;            /* must be set to 1 */
  1016.     halfword bitcount;            /* 1, 4, 8 or 24 */
  1017.     integer compression;
  1018.     integer sizeimage;
  1019.     integer xpelspermeter;
  1020.     integer ypelspermeter;
  1021.     integer clrused;
  1022.     integer clrimportant;
  1023. };
  1024.  
  1025. /* constants for the compression field */
  1026. #define RGB 0L
  1027. #define RLE8 1L
  1028. #define RLE4 2L
  1029.  
  1030. struct bitmapfileheader {
  1031.     char type[2];
  1032.     integer size;
  1033.     halfword reserved1;
  1034.     halfword reserved2;
  1035.     integer offbits;
  1036. };
  1037.  
  1038. void rgbread(f, w, b, s)
  1039. FILE *f;
  1040. int b;
  1041. int w;
  1042. char *s;
  1043. {
  1044.     int i;
  1045.  
  1046.     /* set the line to white */
  1047.     memset(s, 0xff, ((w*b)/8)+1); 
  1048.  
  1049.     /* read in all the full bytes */
  1050.     for (i = 0; i < (w * b) / 8; i++)
  1051.         *s++ = fgetc(f);
  1052.  
  1053.     /* read in a partly filled byte */
  1054.     if ((w * b) % 8) {
  1055.         i++;
  1056.         *s++ = fgetc(f);
  1057.     }
  1058.  
  1059.     /* check that we are on a 32 bit boundary; otherwise align */
  1060.     while (i % 4 != 0) {
  1061.         fgetc(f);
  1062.         i++;
  1063.     }
  1064. }
  1065.  
  1066. unsigned rle_dx = 0;    /* delta command horizontal offset */
  1067. unsigned rle_dy = 0;    /* delta command vertical offset */
  1068.  
  1069. /* checked against output from Borland Resource Workshop */
  1070. void rle4read(f, w, b, s)
  1071. FILE *f;
  1072. int b;
  1073. int w;
  1074. char *s;
  1075. {
  1076.     int i;
  1077.     int limit;
  1078.     int ch;
  1079.     unsigned cnt;
  1080.     int hi;
  1081.  
  1082.     limit = (w*b)/8;
  1083.     i = 0;
  1084.     hi = TRUE;
  1085.     /* set the line to white */
  1086.     memset(s, 0xff, limit+1); 
  1087.  
  1088.     if (rle_dy) {
  1089.         rle_dy--;
  1090.         return;
  1091.     }
  1092.  
  1093.     if (rle_dx) {
  1094.         for ( ; rle_dx>1; rle_dx-=2) {
  1095.         s++;
  1096.         i++;
  1097.         }
  1098.         if (rle_dx)
  1099.             hi = FALSE;
  1100.     }
  1101.  
  1102.     while (i<=limit) {
  1103.         cnt = fgetc(f);
  1104.         ch  = fgetc(f);
  1105.         if (cnt == 0) { /* special operation */
  1106.         switch(ch) {
  1107.             case 0:    /* EOL */
  1108.             return;    /* this is our way out */
  1109.             case 1:    /* End of Bitmap */
  1110.                 return;
  1111.             case 2:    /* Delta */  /* untested */
  1112.             rle_dx = fgetc(f) + i*2 + (hi ? 1 : 0);
  1113.             rle_dy = fgetc(f);
  1114.             return;
  1115.             default:    /* next cnt bytes are absolute */
  1116.                 /* must be aligned on word boundary */
  1117.             if (!hi)
  1118.                 fprintf(stderr,"em:graph: RLE4 absolute is not byte aligned\n");
  1119.             for (cnt = ch; cnt>0 && i<=limit; cnt-=2) {
  1120.                     i++;
  1121.                 *s++ = fgetc(f);
  1122.             }
  1123.             if (ch % 4)    /* word align file */
  1124.                 (void)fgetc(f);
  1125.           }
  1126.         }
  1127.         else {   /* cnt is repeat count */
  1128.         if (!hi) {   /* we are about to place the low 4 bits */
  1129.             ch = ((ch>>4)&0x0f) | ((ch<<4)&0xf0); /* swap order */
  1130.             i++;
  1131.             *s++ = (*s & 0xf0) | (ch & 0x0f);
  1132.             hi = TRUE;
  1133.             cnt--;
  1134.         }
  1135.         /* we are about to place the high 4 bits */
  1136.         for ( ; cnt>1 && i<=limit ; cnt-=2) { /* place the whole bytes */
  1137.             i++;
  1138.             *s++ = ch;
  1139.             }
  1140.         if (cnt) { /* place the partial byte */
  1141.             *s = (*s & 0x0f) | (ch & 0xf0);
  1142.             hi = FALSE;
  1143.         }
  1144.         }
  1145.       }
  1146. }
  1147.   
  1148. /* untested */
  1149. void rle8read(f, w, b, s)
  1150. FILE *f;
  1151. int b;
  1152. int w;
  1153. char *s;
  1154. {
  1155.     int i;
  1156.     int limit;
  1157.     int ch;
  1158.     unsigned cnt;
  1159.  
  1160.     limit = (w*b)/8;
  1161.     i = 0;
  1162.     /* set the line to white */
  1163.     memset(s, 0xff, limit+1); 
  1164.  
  1165.     if (rle_dy) {
  1166.         rle_dy--;
  1167.         return;
  1168.     }
  1169.  
  1170.     if (rle_dx) {
  1171.         for ( ; rle_dx > 0; rle_dx--) {
  1172.         s++;
  1173.         i++;
  1174.         }
  1175.     }
  1176.  
  1177.     while (i<=limit) {
  1178.         cnt = fgetc(f);
  1179.         ch  = fgetc(f);
  1180.         if (cnt == 0) { /* special operation */
  1181.         switch(ch) {
  1182.             case 0:    /* EOL */
  1183.             return;    /* this is our way out */
  1184.             case 1:    /* End of Bitmap */
  1185.             return;
  1186.             case 2:    /* Delta */  /* untested */
  1187.             rle_dx = fgetc(f) + i;
  1188.             rle_dy = fgetc(f);
  1189.             return;
  1190.             default:    /* next cnt bytes are absolute */
  1191.             for (cnt = ch; cnt>0 && i<=limit; cnt--) {
  1192.                     i++;
  1193.                 *s++ = fgetc(f);
  1194.                 }
  1195.             if (ch % 2)    /* word align file */
  1196.                 (void)fgetc(f);
  1197.         }
  1198.         }
  1199.         else { /* cnt is repeat count */
  1200.         for ( ; cnt>0 && i<=limit; cnt--) {
  1201.             i++;
  1202.             *s++ = ch;
  1203.         }
  1204.         }
  1205.     }
  1206. }
  1207.  
  1208. void bmpgraph(f,filename,emwidth,emheight)
  1209. FILE *f;
  1210. char filename[];
  1211. float emwidth, emheight;    /* dimension in pixels */
  1212. {
  1213.     struct bitmapfileheader bmfh;
  1214.     struct bitmapinfoheader bmih;
  1215.  
  1216.     unsigned char isblack[256];
  1217.     unsigned char rr;
  1218.     unsigned char gg;
  1219.     unsigned char bb;
  1220.     unsigned char c = 0;
  1221.  
  1222.     char *line;
  1223.     char *pshexa;
  1224.  
  1225.     int clrtablesize;
  1226.     int i;
  1227.     int j;
  1228.  
  1229.     unsigned char omask;
  1230.     int oroll;
  1231.  
  1232.     unsigned char emask = 0;
  1233.     integer ewidth = 0;
  1234.     int isOS2;
  1235.  
  1236.         /* read the header of the file */
  1237.     fread(bmfh.type, 1, 2, f);
  1238.     bmfh.size = readinteger(f);
  1239.     bmfh.reserved1 = readhalfword(f);
  1240.     bmfh.reserved2 = readhalfword(f);
  1241.     bmfh.offbits = readinteger(f);
  1242.     if (feof(f)) {
  1243.         sprintf(errbuf, "em:graph: Unable to Read Valid BMP Header\n");
  1244.         specerror(errbuf);
  1245.         return;
  1246.     }
  1247.  
  1248.     bmih.size = readinteger(f);
  1249.     if (bmih.size == 12) { /* OS2 bitmap */
  1250.         isOS2 = TRUE;    
  1251.         bmih.width = readhalfword(f);
  1252.         bmih.height = readhalfword(f);
  1253.         bmih.planes = readhalfword(f);
  1254.         bmih.bitcount = readhalfword(f);
  1255.         /* the following don't exist in OS2 format so fill with 0's */
  1256.         bmih.compression = RGB;
  1257.         bmih.sizeimage = 0;
  1258.         bmih.xpelspermeter = 0;
  1259.         bmih.ypelspermeter = 0;
  1260.         bmih.clrused = 0;
  1261.         bmih.clrimportant = 0;
  1262.     }
  1263.     else { /* Windows bitmap */
  1264.         isOS2 = FALSE;    
  1265.         bmih.width = readinteger(f);
  1266.         bmih.height = readinteger(f);
  1267.         bmih.planes = readhalfword(f);
  1268.         bmih.bitcount = readhalfword(f);
  1269.         bmih.compression = readinteger(f);
  1270.         bmih.sizeimage = readinteger(f);
  1271.         bmih.xpelspermeter = readinteger(f);
  1272.         bmih.ypelspermeter = readinteger(f);
  1273.         bmih.clrused = readinteger(f);
  1274.         bmih.clrimportant = readinteger(f);
  1275.     }
  1276.  
  1277.     if (feof(f)) {
  1278.         sprintf(errbuf, "em:graph: Unable to Read Valid BMP Info");
  1279.         specerror(errbuf);
  1280.         return;
  1281.     }
  1282.  
  1283.     if (memcmp(bmfh.type, "BM", 2)) {
  1284.         sprintf(errbuf, "em:graph: Unknown BMP File Type");
  1285.         specerror(errbuf);
  1286.         return;
  1287.     }
  1288.  
  1289.     if ((bmih.compression == RLE4) && (bmih.bitcount != 4)) {
  1290.         sprintf(errbuf, "em:graph: Can't do BMP RLE4 with %d bits per pixel",
  1291.             bmih.bitcount);
  1292.         specerror(errbuf);
  1293.         return;
  1294.     }
  1295.  
  1296.     if ((bmih.compression == RLE8) && (bmih.bitcount != 8)) {
  1297.         sprintf(errbuf, "em:graph: Can't do BMP RLE8 with %d bits per pixel\n",
  1298.             bmih.bitcount);
  1299.         specerror(errbuf);
  1300.         return;
  1301.     }
  1302.  
  1303.     imagehead(filename,(int)bmih.width,(int)bmih.height,emwidth,emheight);
  1304.  
  1305.     /* determine the size of the color table to read */
  1306.     clrtablesize = 0;
  1307.     if (bmih.clrused == 0) {
  1308.         switch (bmih.bitcount) {
  1309.             case 1:
  1310.                 clrtablesize = 2;
  1311.                 break;
  1312.             case 4:
  1313.                 clrtablesize = 16;
  1314.                 break;
  1315.             case 8:
  1316.                 clrtablesize = 256;
  1317.                 break;
  1318.             case 24:
  1319.                 break;
  1320.         }
  1321.     }
  1322.         else
  1323.         clrtablesize = bmih.clrused;
  1324.  
  1325.     /* read in the color table */
  1326.     for (i = 0; i < clrtablesize; i++) {
  1327.         bb = fgetc(f);
  1328.         gg = fgetc(f);
  1329.         rr = fgetc(f);
  1330.         isblack[i] = (rr < 0xff) || (gg < 0xff) || (bb < 0xff);
  1331.         if (!isOS2)
  1332.             (void) fgetc(f);
  1333.     }
  1334.  
  1335.     line = (char *) mymalloc((integer)((bmih.width * bmih.bitcount) / 8) + 1);
  1336.     pshexa = (char *) mymalloc((integer)tobyte(bmih.width));
  1337.  
  1338.     /* output the postscript image size preamble */
  1339.     cmdout("/picstr");
  1340.     numout((integer)tobyte(bmih.width));
  1341.     cmdout("string def");
  1342.  
  1343.     numout((integer)bmih.width);
  1344.     numout((integer)bmih.height);
  1345.     numout((integer)1);
  1346.  
  1347.     cmdout("[");
  1348.     numout((integer)bmih.width);
  1349.     numout((integer)0);
  1350.     numout((integer)0);
  1351.     numout((integer)bmih.height);
  1352.     numout((integer)0);
  1353.     numout((integer)bmih.height);
  1354.     cmdout("]");
  1355.  
  1356.     nlcmdout("{currentfile picstr readhexstring pop} image");
  1357.  
  1358.     if (bmih.bitcount == 1) {
  1359.         if (bmih.width%8)
  1360.             emask = (1<<(8-(bmih.width%8)))-1;    /* mask for edge of bitmap */
  1361.         else
  1362.             emask = 0;
  1363.         ewidth = tobyte(bmih.width);
  1364.     }
  1365.  
  1366.     /* read in all the lines of the file */
  1367.     for (i = 0; i < bmih.height; i++) {
  1368.         memset(pshexa,0xff,tobyte(bmih.width));
  1369.         switch (bmih.compression) {
  1370.             case RGB:
  1371.             rgbread(f, (int) bmih.width, (int) bmih.bitcount, line);
  1372.             break;
  1373.             case RLE4:
  1374.             rle4read(f, (int) bmih.width, (int) bmih.bitcount, line);
  1375.             break;
  1376.             case RLE8:
  1377.             rle8read(f, (int) bmih.width, (int) bmih.bitcount, line);
  1378.             break;
  1379.             default:
  1380.             sprintf(errbuf,"em:graph: Unknown BMP compression\n");
  1381.             specerror(errbuf);
  1382.             return;
  1383.         }
  1384.  
  1385.         omask = 0x80;
  1386.         oroll = 7;
  1387.  
  1388.         if (bmih.bitcount == 1) {
  1389.             if (isblack[0])
  1390.             for (j = 0; j < ewidth ; j++)
  1391.                 pshexa[j] = line[j];
  1392.             else
  1393.             for (j = 0; j < ewidth ; j++)
  1394.                 pshexa[j] = ~line[j];
  1395.             pshexa[ewidth-1] |= emask;
  1396.         }
  1397.         else {
  1398.             for (j = 0; j < bmih.width; j++) {
  1399.             switch (bmih.bitcount) {
  1400.                 case 4:
  1401.                     c = line[j>>1];
  1402.                     if (!(j&1))
  1403.                         c >>= 4;
  1404.                     c = isblack[ c & 0x0f ];
  1405.                     break;
  1406.                 case 8:
  1407.                     c = isblack[ (int)(line[j]) ];
  1408.                     break;
  1409.                 case 24:
  1410.                     rr = line[j*3];
  1411.                     gg = line[j*3+1];
  1412.                     bb = line[j*3+2];
  1413.                     c = (rr < 0xff) || (gg < 0xff) || (bb < 0xff);
  1414.                     break;
  1415.             }
  1416.             if (c) 
  1417.                 pshexa[j/8] &= ~omask;
  1418.             else
  1419.                 pshexa[j/8] |= omask;
  1420.             oroll--;
  1421.             omask >>= 1;
  1422.             if (oroll < 0) {
  1423.                 omask = 0x80;
  1424.                 oroll = 7;
  1425.             }
  1426.             }
  1427.         }
  1428.         newline();
  1429.         mhexout(pshexa,(long)tobyte(bmih.width));
  1430.     }
  1431.     imagetail() ;
  1432.     free(pshexa);
  1433.     free(line);
  1434. }
  1435. /* ------------------------------------------------------------------------ */
  1436.  
  1437. #define PCX 0
  1438. #define MSP 1
  1439. #define BMP 2
  1440. char *extarr[]=
  1441. { ".pcx", ".msp", ".bmp", NULL };
  1442.  
  1443. void emgraph(filename,emwidth,emheight)
  1444. char filename[];
  1445. float emwidth, emheight;    /* dimension in pixels */
  1446. {
  1447.     char fname[80];
  1448.     int filetype;
  1449.     FILE *f;
  1450.     char *env;
  1451.     char id[4];
  1452.     int i;
  1453.  
  1454.     strcpy(fname, filename);
  1455.  
  1456.     /* find the file */
  1457.     f = search(figpath, fname, READBIN);
  1458.     if (f == (FILE *)NULL) {
  1459.            if ( (env = getenv("DVIDRVGRAPH")) != NULL )
  1460.         f = search(env,filename,READBIN);
  1461.     }
  1462.     /* if still haven't found it try adding extensions */
  1463.     if (f == (FILE *)NULL) {
  1464.         i = 0;
  1465.         while (extarr[i] != NULL) {
  1466.         strcpy(fname, filename);
  1467.         strcat(fname, extarr[i]);
  1468.         f = search(figpath, fname, READBIN);
  1469.         if (f == (FILE *)NULL) {
  1470.                 if ( (env = getenv("DVIDRVGRAPH")) != NULL )
  1471.             f = search(env,filename,READBIN);
  1472.         }
  1473.         if (f != (FILE *)NULL)
  1474.             break;
  1475.         i++;
  1476.         }
  1477.     }
  1478.  
  1479.     filetype = -1;
  1480.     if (f != (FILE *)NULL) {
  1481.         for (i=0; i<4; i++) {
  1482.         id[i] = readquarterword(f);
  1483.         }
  1484.         if ( (id[0] == 0x0a) && (id[2] == 0x01) )
  1485.         filetype = PCX;
  1486.         if (!memcmp(id, "DanM", 4))
  1487.         filetype = MSP;
  1488.         if (!memcmp(id, "LinS", 4))
  1489.         filetype = MSP;
  1490.         if (!memcmp(id, "BM", 2))
  1491.         filetype = BMP;
  1492.         fseek(f, 0L, SEEK_SET);
  1493.     }
  1494.  
  1495.     switch (filetype) {
  1496.         case PCX:
  1497.             pcxgraph(f, fname, emwidth, emheight);
  1498.             break;
  1499.         case MSP:
  1500.             mspgraph(f, fname, emwidth, emheight);
  1501.             break;
  1502.         case BMP:
  1503.             bmpgraph(f, fname, emwidth, emheight);
  1504.             break;
  1505.         default:
  1506.             sprintf(fname,"em:graph: %s: File not found", filename);
  1507.             error(fname);
  1508.     }
  1509.     if (f != (FILE *)NULL)
  1510.         fclose(f);
  1511. }
  1512.  
  1513. #else
  1514. void emspecial(p)
  1515. char *p ;
  1516. {
  1517.     sprintf(errbuf,"emTeX specials not compiled in this version");
  1518.     specerror(errbuf);
  1519. }
  1520. #endif /* EMTEX */
  1521.