Back to index

tetex-bin  3.0
emspecial.c
Go to the documentation of this file.
00001 /*
00002  *   emspecial.c
00003  *   This routine handles the emTeX special commands.
00004  */
00005 #include "dvips.h" /* The copyright notice in that file is included too!*/
00006 
00007 #include <ctype.h>
00008 #include <stdlib.h>
00009 /*
00010  *   These are the external routines called:
00011  */
00012 #include "protos.h"
00013 
00014 extern char errbuf[] ;
00015 extern shalfword linepos;
00016 extern FILE *bitfile;
00017 extern int actualdpi ;
00018 extern int vactualdpi ;
00019 extern integer hh, vv;
00020 #ifndef KPATHSEA
00021 extern char *figpath ;
00022 #endif
00023 extern int prettycolumn ;
00024 extern int quiet;
00025 extern Boolean disablecomments ;
00026 
00027 #ifdef DEBUG
00028 extern integer debug_flag;
00029 #endif
00030 
00031 
00032 #ifdef EMTEX
00033 /* emtex specials, added by rjl */
00034 
00035 #ifndef TRUE
00036 #define TRUE 1
00037 #define FALSE 0
00038 #endif
00039 
00040 static long emmax = 161 ;
00041 
00042 /*
00043  *   We define these seek constants if they don't have their
00044  *   values already defined.
00045  */
00046 #ifndef SEEK_SET
00047 #define SEEK_SET (0)
00048 #endif
00049 #ifndef SEEK_END
00050 #define SEEK_END (2)
00051 #endif
00052 
00053 struct empt {
00054    struct empt *next ;
00055    shalfword point;
00056    integer x, y;
00057 };
00058 
00059 static struct empt **empoints = NULL ;
00060 boolean emused = FALSE;  /* true if em points used on this page */
00061 integer emx, emy;
00062 
00063 struct emunit {
00064    char *unit;
00065    float factor;
00066 };
00067 struct emunit emtable[] = {
00068   {"pt",72.27},
00069   {"pc",72.27/12},
00070   {"in",1.0},
00071   {"bp",72.0},
00072   {"cm",2.54},
00073   {"mm",25.4},
00074   {"dd",72.27/(1238.0/1157)},
00075   {"cc",72.27/12/(1238.0/1157)},
00076   {"sp",72.27*65536},
00077   {0,0.0}
00078 };
00079 
00080 
00081 /* clear the empoints array if necessary */
00082 void
00083 emclear P1H(void)
00084 {
00085    int i;
00086    if (emused && empoints)
00087       for (i=0; i<emmax; i++)
00088          empoints[i] = 0 ;
00089    emused = FALSE ;
00090 }
00091 
00092 /* put an empoint into the empoints array */
00093 struct empt *emptput P3C(shalfword, point, integer, x, integer, y)
00094 {
00095    struct empt *p ;
00096    int start ;
00097 
00098    emused = TRUE;
00099    start = point % emmax ;
00100    p = empoints[start] ;
00101    while ( p ) {
00102       if ( p->point == point )
00103          break;
00104       p = p->next ;
00105    }
00106    if (p == 0) {
00107       p = (struct empt *)mymalloc(sizeof(struct empt)) ;
00108       p->next = empoints[start] ;
00109       empoints[start] = p ;
00110    }
00111    p->point = point;
00112    p->x = x;
00113    p->y = y;
00114    return(p) ;
00115 }
00116 
00117 /* get an empoint from the empoints array */
00118 struct empt *emptget P1C(shalfword, point)
00119 {
00120    struct empt *p ;
00121    int start;
00122 
00123    start = point % emmax;
00124    if (emused == TRUE) {
00125       p = empoints[start] ;
00126       while (p) {
00127         if (p->point == point)
00128            return p ;
00129         p = p->next ;
00130       }
00131    }
00132    sprintf(errbuf,"!em: point %d not defined",point);
00133    specerror(errbuf);
00134    return(NULL); /* never returns due to error */
00135 }
00136 
00137 
00138 /* convert width into dpi units */
00139 float emunits P2C(float, width, char *, unit)
00140 {
00141 struct emunit *p;
00142        for (p=emtable; p->unit; p++) {
00143           if (strcmp(p->unit,unit)==0)
00144               return( width * actualdpi / p->factor );
00145        }
00146        return (-1.0); /* invalid unit */
00147 }
00148 
00149 /* The main routine for \special{em:graph ...} called from dospecial.c */
00150 /* the line cut parameter is not supported (and is ignored) */
00151 
00152 void emspecial P1C(char *, p)
00153 {
00154 float emwidth, emheight;
00155 shalfword empoint1, empoint2;
00156 struct empt *empoint;
00157 char emunit[3];
00158 char emstr[80];
00159 char *emp;
00160 #ifndef KPATHSEA
00161 void emgraph();
00162 #endif
00163 
00164         hvpos() ;
00165        for (emp = p+3; *emp && isspace(*emp); emp++); /* skip blanks */
00166        if (strncmp(emp, "linewidth", 9) == 0) {
00167           /* code for linewidth */
00168           for (emp = emp+9; *emp && isspace(*emp); emp++); /* skip blanks */
00169           sscanf(emp, "%f%2s", &emwidth, emunit);
00170           emwidth = emunits(emwidth,emunit);
00171           if (emwidth!=-1.0) {
00172              sprintf(emstr,"%.1f setlinewidth", emwidth);
00173              cmdout(emstr);
00174 #ifdef DEBUG
00175    if (dd(D_SPECIAL))
00176       (void)fprintf(stderr, "em special: Linewidth set to %.1f dots\n", 
00177               emwidth) ;
00178 #endif
00179           } else {
00180              sprintf(errbuf,"Unknown em: special width");
00181              specerror(errbuf);
00182           }
00183        }
00184         else if (strncmp(emp, "moveto", 6) == 0) {
00185 #ifdef DEBUG
00186    if (dd(D_SPECIAL))
00187 #ifdef SHORTINT
00188       (void)fprintf(stderr, "em special: moveto %ld,%ld\n", hh, vv);
00189 #else
00190       (void)fprintf(stderr, "em special: moveto %d,%d\n", hh, vv);
00191 #endif
00192 #endif
00193            emx = hh;
00194            emy = vv;
00195         }
00196         else if (strncmp(emp, "lineto", 6) == 0) {
00197 #ifdef DEBUG
00198    if (dd(D_SPECIAL))
00199 #ifdef SHORTINT
00200       (void)fprintf(stderr, "em special: lineto %ld,%ld\n", hh, vv);
00201 #else
00202       (void)fprintf(stderr, "em special: lineto %d,%d\n", hh, vv);
00203 #endif
00204 #endif
00205           cmdout("np");
00206           numout(emx);
00207           numout(emy);
00208           cmdout("a");
00209           numout(hh);
00210           numout(vv);
00211           cmdout("li");
00212           cmdout("st");
00213            emx = hh;
00214            emy = vv;
00215         }
00216        else if (strncmp(emp, "point", 5) == 0) {
00217            if (empoints == NULL) {
00218               empoints = 
00219               (struct empt **)mymalloc((integer)emmax * sizeof(struct empt *)) ;
00220               emused = TRUE;
00221               emclear();
00222            }
00223           for (emp = emp+5; *emp && isspace(*emp); emp++); /* skip blanks */
00224            empoint1 = (shalfword)atoi(emp);
00225            empoint = emptput(empoint1,hh,vv);
00226 #ifdef DEBUG
00227    if (dd(D_SPECIAL))
00228 #ifdef SHORTINT
00229       (void)fprintf(stderr, "em special: Point %d is %ld,%ld\n",
00230 #else
00231       (void)fprintf(stderr, "em special: Point %d is %d,%d\n",
00232 #endif
00233               empoint->point, empoint->x, empoint->y) ;
00234 #endif
00235        }
00236        else if (strncmp(emp, "line", 4) == 0) {
00237           for (emp = emp+4; *emp && isspace(*emp); emp++); /* skip blanks */
00238            empoint1 = (shalfword)atoi(emp);
00239           for (; *emp && isdigit(*emp); emp++); /* skip point 1 */
00240           if ( *emp && strchr("hvp",*emp)!=0 )
00241              emp++;  /* skip line cut */
00242           for (; *emp && isspace(*emp); emp++); /* skip blanks */
00243           if ( *emp && (*emp==',') )
00244              emp++; /*  skip comma separator */
00245           for (; *emp && isspace(*emp); emp++); /* skip blanks */
00246            empoint2 = (shalfword)atoi(emp);
00247           for (; *emp && isdigit(*emp); emp++); /* skip point 2 */
00248           if ( *emp && strchr("hvp",*emp)!=0 )
00249              emp++;  /* skip line cut */
00250           for (; *emp && isspace(*emp); emp++); /* skip blanks */
00251           if ( *emp && (*emp==',') )
00252              emp++; /*  skip comma separator */
00253           emwidth = -1.0;
00254           emunit[0]='\0';
00255           sscanf(emp, "%f%2s", &emwidth, emunit);
00256           emwidth = emunits(emwidth,emunit);
00257 #ifdef DEBUG
00258    if (dd(D_SPECIAL))
00259       (void)fprintf(stderr, "em special: Line from point %d to point %d\n",
00260               empoint1, empoint2) ;
00261 #endif
00262           cmdout("np");
00263           if (emwidth!=-1.0) {
00264 #ifdef DEBUG
00265    if (dd(D_SPECIAL))
00266    (void)fprintf(stderr,"em special: Linewidth temporarily set to %.1f dots\n", 
00267               emwidth) ;
00268 #endif
00269               strcpy(emstr,"currentlinewidth");
00270               cmdout(emstr);
00271                sprintf(emstr,"%.1f setlinewidth", emwidth);
00272                cmdout(emstr);
00273           }
00274            empoint = emptget(empoint1);
00275           numout(empoint->x);
00276           numout(empoint->y);
00277           cmdout("a");
00278            empoint = emptget(empoint2);
00279           numout(empoint->x);
00280           numout(empoint->y);
00281           cmdout("li");
00282           cmdout("st");
00283           if (emwidth!=-1.0) {
00284               strcpy(emstr,"setlinewidth");
00285               cmdout(emstr);
00286           }
00287        }
00288        else if (strncmp(emp, "message", 7) == 0) {
00289            (void)fprintf(stderr, "em message: %s\n", emp+7) ;
00290        }
00291        else if (strncmp(emp, "graph", 5) == 0) {
00292           int i;
00293           for (emp = emp+5; *emp && isspace(*emp); emp++); /* skip blanks */
00294           for (i=0; *emp && !isspace(*emp) && !(*emp==',') ; emp++)
00295              emstr[i++] = *emp; /* copy filename */
00296           emstr[i] = '\0';
00297           /* now get optional width and height */
00298           emwidth = emheight = -1.0;      /* no dimension is <= 0 */
00299           for (; *emp && ( isspace(*emp) || (*emp==',') ); emp++)
00300              ;  /* skip blanks and comma */
00301           if (*emp) {
00302              sscanf(emp, "%f%2s", &emwidth, emunit); /* read width */
00303              emwidth = emunits(emwidth,emunit); /* convert to pixels */
00304              for (; *emp && (*emp=='.'||isdigit(*emp)||isalpha(*emp)); emp++)
00305                 ; /* skip width dimension */
00306              for (; *emp && ( isspace(*emp) || (*emp==',') ); emp++)
00307                 ;  /* skip blanks and comma */
00308              if (*emp) {
00309                 sscanf(emp, "%f%2s", &emheight, emunit); /* read height */
00310                 emheight = emunits(emheight,emunit)*vactualdpi/actualdpi;
00311              }
00312           }
00313           if (emstr[0]) {
00314              emgraph(emstr,emwidth,emheight);
00315           }
00316           else {
00317               (void)fprintf(stderr, "em:graph: no file given\n") ;
00318           }
00319        }
00320        else {
00321            sprintf(errbuf, 
00322              "Unknown em: command (%s) in \\special will be ignored", p);
00323            specerror(errbuf) ;
00324        }
00325        return;
00326    }
00327 
00328 
00329 /* em:graph routines */
00330 
00331 /* The graphics routines currently decode 3 types of IBM-PC based graphics   */
00332 /* files: .pcx, .bmp, .msp. The information on the formats has occasionally  */
00333 /* been sketchy, and subject to interpretation. I have attempted to implement*/
00334 /* these routines to correctly decode the graphics file types mentioned.     */
00335 /* The compressed .bmp file type has not been tested fully due to a lack of  */
00336 /* test files.                                                               */
00337 /*                                                                           */
00338 /* The method of reading in the headers of the binary files is ungainly, but */
00339 /* portable. Failure to use a byte by byte read and convert method will      */
00340 /* result in portability problems. Specifically there is no requirement that */
00341 /* elements of a C structure be contiguous, only that they have an ascending */
00342 /* order of addresses.                                                       */
00343 /*                                                                           */
00344 /* The current implementations of the graphics format to postscript          */
00345 /* conversion are not the most efficient possible. Specifically: color       */
00346 /* formats are converted to RGB ratios prior to using a simple thresholding  */
00347 /* method to determine if the postscript bit is to be set. The thresholding  */
00348 /* method is compabible with that used in emtex's drivers.                   */
00349 /*                                                                           */
00350 /* Please send bug reports relating to the em:graph routines to:             */
00351 /*                maurice@bruce.cs.monash.edu.au                             */
00352 /*                                                                           */
00353 /* My thanks to Russell Lang for his assistance with the implementation of   */
00354 /* these routines in a manner compatible with dvips and for the optimization */
00355 /* of some routines.                                                         */
00356 /*                                                                           */
00357 /*                                                   Maurice Castro          */
00358 /*                                                   8 Oct 92                */
00359 
00360 /* Routines to read binary numbers from IBM PC file types */
00361 integer readinteger P1C(FILE *, f)
00362 {
00363    integer i;
00364    int r;
00365 
00366    i = 0;
00367    for (r = 0; r < 4; r++)
00368    {
00369       i = i |  ( ((integer) fgetc(f)) << (8*r) );
00370    }
00371    return(i);
00372 }
00373 
00374 halfword readhalfword P1C(FILE *, f)
00375 {
00376    halfword i;
00377    int r;
00378  
00379    i = 0;
00380    for (r = 0; r < 2; r++)
00381    {
00382      i = i |  ( ((halfword) fgetc(f)) << (8*r) );
00383    }
00384    return(i);
00385 }
00386 
00387 #define readquarterword(f) ((unsigned char)fgetc(f))
00388 #define tobyte(x) ((x/8) + (x%8 ? 1 : 0))
00389 
00390 /* These routines will decode PCX files produced by Microsoft 
00391  * Windows Paint.  Other programs may not produce files which
00392  * will be successfully decoded, most notably version 1.xx of
00393  * PC Paint. */
00394 
00395 /*
00396  *   Type declarations.  integer must be a 32-bit signed; shalfword must
00397  *   be a sixteen-bit signed; halfword must be a sixteen-bit unsigned;
00398  *   quarterword must be an eight-bit unsigned.
00399  */
00400 typedef struct 
00401 {
00402        quarterword man;
00403        quarterword ver;
00404        quarterword enc;
00405        quarterword bitperpix;
00406        halfword xmin;
00407        halfword ymin;
00408        halfword xmax;
00409        halfword ymax;
00410        halfword hres;
00411        halfword vres;
00412        quarterword pal[48];
00413        quarterword reserved;
00414        quarterword colorplanes;
00415        halfword byteperline;
00416        halfword paltype;
00417        quarterword fill[58];
00418 } PCXHEAD; 
00419 
00420 int PCXreadhead P2C(FILE *, pcxf, PCXHEAD *, pcxh)
00421 {
00422        pcxh->man = readquarterword(pcxf);
00423        pcxh->ver = readquarterword(pcxf);
00424        pcxh->enc = readquarterword(pcxf);
00425        pcxh->bitperpix = readquarterword(pcxf);
00426        pcxh->xmin = readhalfword(pcxf);
00427        pcxh->ymin = readhalfword(pcxf);
00428        pcxh->xmax = readhalfword(pcxf);
00429        pcxh->ymax = readhalfword(pcxf);
00430        pcxh->hres = readhalfword(pcxf);
00431        pcxh->vres = readhalfword(pcxf);
00432        fread(pcxh->pal, 1, 48, pcxf);
00433        pcxh->reserved = readquarterword(pcxf);
00434        pcxh->colorplanes = readquarterword(pcxf);
00435        pcxh->byteperline = readhalfword(pcxf);
00436        pcxh->paltype = readhalfword(pcxf);
00437        fread(pcxh->fill, 1, 58, pcxf);
00438 
00439        if (feof(pcxf))
00440               return(0);                         /* fail */
00441        if (pcxh->man != 0x0a)
00442               return(0);                         /* fail */
00443        if (pcxh->enc != 0x1)
00444               return(0);                         /* fail */
00445        return(1);                                /* success */
00446        }
00447 
00448 int PCXreadline P3C(FILE *, pcxf, 
00449                   unsigned char *, pcxbuf,
00450                   unsigned int, byteperline)
00451 {
00452        int n;
00453        int c;
00454        int i;
00455 
00456        n = 0;
00457        memset(pcxbuf,0,byteperline);
00458        do {
00459               c = fgetc(pcxf);
00460               if ((c & 0xc0) == 0xc0) {
00461                      i = c & 0x3f;
00462                      c = fgetc(pcxf) & 0xff;
00463                      while ((i--) && (n < byteperline)) pcxbuf[n++] = c;
00464               }
00465               else {
00466                      pcxbuf[n++] = c & 0xff;
00467               }
00468        } while (n < byteperline);
00469        if (c==EOF) n=0;
00470        return(n);
00471 }
00472 
00473 void PCXgetpalette P5C( FILE *, pcxf, PCXHEAD *, pcxh, 
00474                      unsigned char *, r,
00475                      unsigned char *, g,
00476                      unsigned char *, b)
00477 {
00478        int i;
00479 
00480        /* clear palette */
00481        for (i=0; i < 256; i++) {
00482               r[i] = 0;
00483               g[i] = 0;
00484               b[i] = 0;
00485        }
00486 
00487        switch (pcxh->ver) {
00488               case 0:
00489                      /* version 2.5 of PC Paint Brush */
00490                      for (i=0; i < 16; i++) {
00491                             r[i] = pcxh->pal[i*3];
00492                             g[i] = pcxh->pal[i*3+1];
00493                             b[i] = pcxh->pal[i*3+2];
00494                      }
00495                      break;
00496               case 2:
00497                      if (pcxh->colorplanes != 1) {
00498                          /* version 2.8 of PC Paint Brush with valid Palette */
00499                      for (i=0; i < 16; i++) {
00500                             r[i] = pcxh->pal[i*3];
00501                             g[i] = pcxh->pal[i*3+1];
00502                             b[i] = pcxh->pal[i*3+2];
00503                          }
00504                      }
00505                      else { /* not sure if this is correct - rjl */
00506                             /* mono palette */
00507                             r[0] = 0x00; g[0] = 0x00; b[0] = 0x00;
00508                             r[1] = 0xff; g[1] = 0xff; b[1] = 0xff;
00509                      }
00510                      break;
00511               case 3:
00512                      /* version 2.8 of PC Paint Brush with no valid Palette */
00513                      /* either mono or default */
00514 
00515                      if (pcxh->colorplanes != 1) {
00516                             /* Color default palette - should be checked */
00517                             r[0] = 0x00;         g[0] = 0x00;         b[0] = 0x00;
00518                             r[1] = 0x80;         g[1] = 0x00;         b[1] = 0x00;
00519                             r[2] = 0x00;         g[2] = 0x80;         b[2] = 0x00;
00520                             r[3] = 0x80;         g[3] = 0x80;         b[3] = 0x00;
00521                             r[4] = 0x00;         g[4] = 0x00;         b[4] = 0x80;
00522                             r[5] = 0x80;         g[5] = 0x00;         b[5] = 0x80;
00523                             r[6] = 0x00;         g[6] = 0x80;         b[6] = 0x80;
00524                             r[7] = 0x80;         g[7] = 0x80;         b[7] = 0x80;
00525                             r[8] = 0xc0;         g[8] = 0xc0;         b[8] = 0xc0;
00526                             r[9] = 0xff;         g[9] = 0x00;         b[9] = 0x00;
00527                             r[10] = 0x00;               g[10] = 0xff;               b[10] = 0x00;
00528                             r[11] = 0xff;               g[11] = 0xff;               b[11] = 0x00;
00529                             r[12] = 0x00;               g[12] = 0x00;               b[12] = 0xff;
00530                             r[13] = 0xff;               g[13] = 0x00;               b[13] = 0xff;
00531                             r[14] = 0x00;               g[14] = 0xff;               b[14] = 0xff;
00532                             r[15] = 0xff;               g[15] = 0xff;               b[15] = 0xff;
00533                      }
00534                      else {
00535                             /* mono palette */
00536                             r[0] = 0x00;         g[0] = 0x00;         b[0] = 0x00;
00537                             r[1] = 0xff;         g[1] = 0xff;         b[1] = 0xff;
00538                      }
00539                      break;
00540               case 5:
00541               default:
00542                      /* version 3.0 of PC Paint Brush or Better */
00543                      fseek(pcxf, -769L, SEEK_END);
00544                      /* if signature byte is correct then read the palette */
00545                      /* otherwise copy the existing palette */
00546                      if (fgetc(pcxf) == 12) {
00547                             for (i=0; i < 256; i++) {
00548                                    r[i] = fgetc(pcxf);
00549                                    g[i] = fgetc(pcxf);
00550                                    b[i] = fgetc(pcxf);
00551                             }
00552                      }
00553                      else {
00554                             for (i=0; i < 16; i++) {
00555                                    r[i] = pcxh->pal[i*3];
00556                                    g[i] = pcxh->pal[i*3+1];
00557                                    b[i] = pcxh->pal[i*3+2];
00558                             }
00559                      }
00560                      break;
00561        }
00562 }
00563 
00564 void PCXshowpicture P9C(FILE *, pcxf, int, wide, int, high, int, bytes,
00565                      int, cp, int, bp, unsigned char *, r, 
00566                      unsigned char *, g, unsigned char *, b)
00567 {
00568        int x;
00569        int y;
00570        int c;
00571        unsigned char *rowa[4];                          /* row array */
00572        unsigned char *row;
00573        int p;
00574        unsigned char *pshexa;
00575        int xdiv, xmod, xbit;
00576        int width;
00577        int bytewidth;
00578 
00579        bytewidth = tobyte(wide);
00580        width = bytewidth * 8;
00581 
00582        /* output the postscript image size preamble */
00583        cmdout("/picstr ");
00584        numout((integer)tobyte(wide));
00585        cmdout("string def");
00586 
00587        numout((integer)width);
00588        numout((integer)high);
00589        numout((integer)1);
00590        newline();
00591 
00592        cmdout("[");
00593        numout((integer)width);
00594        numout((integer)0);
00595        numout((integer)0);
00596        numout((integer)-high);
00597        numout((integer)0);
00598        numout((integer)0);
00599        cmdout("]");
00600 
00601        nlcmdout("{currentfile picstr readhexstring pop} image");
00602 
00603        /* allocate the postscript hex output array */
00604        pshexa = (unsigned char *) mymalloc((integer)bytewidth);
00605 
00606        /* make sure that you start at the right point in the file */
00607        fseek(pcxf, (long) sizeof(PCXHEAD), SEEK_SET);
00608 
00609        /* malloc the lines */
00610        row = (unsigned char *) mymalloc((integer)bytes * cp);
00611        for (c = 0; c < cp; c++)
00612               rowa[c] = row + bytes*c;
00613 
00614        for (y = 0; y < high; y++) {
00615               /* clear the postscript hex array */
00616               memset(pshexa,0xff,bytewidth);
00617 
00618               /* read in all the color planes for a row of pixels */
00619               PCXreadline(pcxf, rowa[0], bytes*cp);
00620 
00621               /* process each pixel */
00622               for (x = 0; x < wide; x++) {
00623                      /* build up the pixel value from color plane entries */
00624                      p = 0;
00625                      xdiv = x>>3;
00626                      xmod = 7 - (x&7);
00627                      xbit = 1 << xmod;
00628                      switch(bp) {
00629                             case 1: 
00630                                    for (c = 0; c < cp; c++) {
00631                                           row = rowa[c];
00632                                           p |= ( (unsigned)(row[xdiv] & xbit) >> xmod ) << c;
00633                                    }
00634                                    break;
00635                             case 4:  /* untested - most programs use 1 bit/pixel, 4 planes */
00636                                    row = rowa[0]; /* assume single plane */
00637                                    p = ( x & 1 ? row[xdiv] : row[xdiv]>>4 ) & 0x0f;
00638                                    break;
00639                             case 8:
00640                                    row = rowa[0]; /* assume single plane */
00641                                    p = (unsigned) (row[x]);
00642                                    break;
00643                             default: 
00644                                    fprintf(stderr, "em:graph: Unable to Decode this PCX file\n");
00645                                    return;
00646                      }
00647                      if ((r[p] < 0xff) || (g[p] < 0xff) || (b[p] < 0xff))
00648                             pshexa[xdiv] &= (~xbit);
00649                      else
00650                             pshexa[xdiv] |= xbit;
00651               }
00652               newline();
00653               mhexout(pshexa,(long)bytewidth);
00654        }
00655        free(pshexa);
00656        free(rowa[0]);
00657 }
00658 
00659 void imagehead P5C(char *, filename, int, wide, int, high, 
00660                  float, emwidth, float, emheight)
00661 {
00662        if (!quiet) {
00663            if (strlen(filename) + prettycolumn > STDOUTSIZE) {
00664               fprintf(stderr,"\n");
00665               prettycolumn = 0;
00666            }
00667            (void)fprintf(stderr,"<%s",filename);
00668            (void)fflush(stderr);
00669            prettycolumn += 2+strlen(filename);
00670        }
00671        hvpos();
00672        nlcmdout("@beginspecial @setspecial") ;
00673        if (!disablecomments) {
00674               cmdout("%%BeginDocument: em:graph");
00675               cmdout(filename);
00676               newline();
00677        }
00678        /* set the image size */
00679        if (emwidth <= 0.0)  emwidth = (float)wide;
00680        if (emheight <= 0.0)  emheight = (float)high;
00681        floatout(emwidth*72/actualdpi);
00682        floatout(emheight*72/vactualdpi);
00683        newline();
00684        cmdout("scale");
00685 #ifdef DEBUG
00686        if (dd(D_SPECIAL)) {
00687          (void)fprintf(stderr, 
00688            "\nem:graph: %s width  %d pixels scaled to %.1f pixels\n",
00689            filename, wide, emwidth);
00690          (void)fprintf(stderr, 
00691            "em:graph: %s height %d pixels scaled to %.1f pixels\n",
00692            filename, high, emheight);
00693        }
00694 #endif
00695 }
00696 
00697 void imagetail P1H(void)
00698 {
00699        if (!disablecomments) {
00700            (void)fprintf(bitfile, "\n%%%%EndDocument\n") ;
00701            linepos = 0;
00702        }
00703        nlcmdout("@endspecial") ;
00704        if (!quiet) {
00705            (void)fprintf(stderr,">");
00706            (void)fflush(stderr);
00707        }
00708 }
00709 
00710 void pcxgraph P4C(FILE *, pcxf, char *, filename,
00711                 float, emwidth, float, emheight /* dimension in pixels */ )
00712 {
00713        PCXHEAD pcxh;
00714        unsigned char red[256];
00715        unsigned char green[256];
00716        unsigned char blue[256];
00717        int wide;
00718        int high;
00719        int bytes;
00720        int cp;
00721        int bpp;
00722 
00723        if (!PCXreadhead(pcxf, &pcxh)) {
00724               sprintf(errbuf,"em:graph: Unable to Read Valid PCX Header");
00725               specerror(errbuf);
00726        }
00727        PCXgetpalette(pcxf, &pcxh, red, green, blue);
00728 
00729        /* picture size calculation */
00730        wide = (pcxh.xmax - pcxh.xmin) + 1;
00731        high = (pcxh.ymax - pcxh.ymin) + 1;
00732        bytes = pcxh.byteperline;
00733        cp = pcxh.colorplanes;
00734        bpp = pcxh.bitperpix;
00735 
00736        imagehead(filename,wide,high,emwidth,emheight);
00737        PCXshowpicture(pcxf, wide, high, bytes, cp, bpp, red, green, blue);
00738        imagetail();
00739 }
00740 
00741 /* Microsoft Paint routines */
00742 struct wpnt_1 {
00743        quarterword id[4];
00744        halfword width;
00745        halfword high;
00746        halfword x_asp;
00747        halfword y_asp;
00748        halfword x_asp_prn;
00749        halfword y_asp_prn;
00750        halfword width_prn;
00751        halfword high_prn;
00752        integer chk_sum;
00753        halfword chk_head;
00754 };
00755 
00756 #define WPAINT_1 1
00757 #define WPAINT_2 2
00758 
00759 void MSP_2_ps P3C(FILE *, f, int,  wide, int, high)
00760 {
00761        char *line;
00762        char *l;
00763        int i;
00764        int j;
00765        unsigned char a, b, c;
00766        int d;
00767        int width;
00768        halfword *linelen;
00769 
00770        /* an undocumented format - based on a type of run length encoding    */
00771        /* the format is made up of a list of line lengths, followed by a set */
00772        /* of lines. Each line is made up of 2 types of entries:              */
00773        /*     1) A 3 term entry (0 a b): the byte b is repeated a times     */
00774        /*     2) A variable length entry (a xxxx....xxxx): a bytes are read */
00775        /*        from the file.                                             */
00776        /* These entries are combined to build up a line                      */
00777 
00778        width = tobyte(wide)*8;
00779 
00780        /* output the postscript image size preamble */
00781        cmdout("/picstr");
00782        numout((integer)tobyte(wide));
00783        cmdout("string def");
00784 
00785        numout((integer)width);
00786        numout((integer)high);
00787        numout((integer)1);
00788 
00789        cmdout("[");
00790        numout((integer)width);
00791        numout((integer)0);
00792        numout((integer)0);
00793        numout((integer)-high);
00794        numout((integer)0);
00795        numout((integer)0);
00796        cmdout("]");
00797 
00798        nlcmdout("{currentfile picstr readhexstring pop} image");
00799 
00800        fseek(f, 32, SEEK_SET);
00801 
00802        /* read in the table of line lengths */   
00803        linelen = (halfword *) mymalloc((integer)sizeof(halfword) * high);
00804        for (i = 0; i < high; i++) {
00805               linelen[i] = readhalfword(f);
00806               if (feof(f))
00807                      return;
00808        }
00809 
00810        line = (char *) mymalloc((integer)tobyte(wide));
00811        for (i = 0; i < high; i++) {
00812               memset(line, 0xff, tobyte(wide));
00813               l = line;
00814               if (linelen[i] != 0) {
00815                      d = linelen[i];
00816                      while (d) {
00817                             a = fgetc(f);
00818                             d--;
00819                             if (a == 0) {
00820                                    b = fgetc(f);
00821                                    c = fgetc(f);
00822                                    d -= 2;
00823                                    for (j = 0; j < b; j++)
00824                                           *l++ = c;
00825                             }
00826                             else {
00827                                    for (j = 0; j < a; j++)
00828                                           *l++ = fgetc(f);
00829                                    d -= j;
00830                             }
00831                      }
00832               }
00833               newline();
00834               mhexout((unsigned char *) line,(long)tobyte(wide));
00835        }
00836        free(linelen);
00837        free(line);
00838 }
00839 
00840 void MSP_1_ps P3C(FILE *, f, int, wide, int, high)
00841 {
00842        char *line;
00843        int i;
00844        int width;
00845 
00846        width = tobyte(wide)*8;
00847        /* an partly documented format - see The PC Sourcebook                */
00848        /* the format is made up of a simple bitmap.                          */
00849 
00850        /* output the postscript image size preamble */
00851        cmdout("/picstr");
00852        numout((integer)tobyte(wide));
00853        cmdout("string def");
00854 
00855        numout((integer)width);
00856        numout((integer)high);
00857        numout((integer)1);
00858 
00859        cmdout("[");
00860        numout((integer)width);
00861        numout((integer)0);
00862        numout((integer)0);
00863        numout((integer)-high);
00864        numout((integer)0);
00865        numout((integer)0);
00866        cmdout("]");
00867 
00868        nlcmdout("{currentfile picstr readhexstring pop} image");
00869 
00870        fseek(f, 32, SEEK_SET);
00871 
00872        line = (char *) mymalloc((integer)tobyte(wide));
00873        for (i = 0; i < high; i++) {
00874               fread(line, 1, tobyte(wide), f);
00875               newline();
00876               mhexout((unsigned char *) line,(long)tobyte(wide));
00877        }
00878        free(line);
00879 }
00880 
00881 
00882 void mspgraph P4C(FILE *, f, char *, filename, float, emwidth, float, emheight)
00883 {
00884        struct wpnt_1 head;
00885        int paint_type = 0;
00886 
00887         /* read the header of the file and figure out what it is */
00888        fread(head.id, 1, 4, f);
00889        head.width = readhalfword(f); 
00890        head.high = readhalfword(f); 
00891        head.x_asp = readhalfword(f); 
00892        head.y_asp = readhalfword(f); 
00893        head.x_asp_prn = readhalfword(f); 
00894        head.y_asp_prn = readhalfword(f); 
00895        head.width_prn = readhalfword(f); 
00896        head.high_prn = readhalfword(f); 
00897        head.chk_sum = readinteger(f); 
00898        head.chk_head = readhalfword(f); 
00899 
00900        if (feof(f)) {
00901               fprintf(stderr, "em:graph: Unable to Read Valid MSP Header\n");
00902               return;
00903        }
00904               
00905         /* check the id bytes */
00906        if (!memcmp(head.id, "DanM", 4))
00907               paint_type = WPAINT_1;
00908        if (!memcmp(head.id, "LinS", 4))
00909               paint_type = WPAINT_2;
00910 
00911 
00912        imagehead(filename,head.width,head.high,emwidth,emheight);
00913        switch (paint_type) {
00914               case WPAINT_1:
00915                      MSP_1_ps(f, head.width, head.high);
00916                      break;
00917                 case WPAINT_2:
00918                      MSP_2_ps(f, head.width, head.high);
00919                      break;
00920               default:
00921                      sprintf(errbuf, "em:graph: Unknown MSP File Type");
00922                      specerror(errbuf);
00923        }
00924        imagetail() ;
00925 }
00926 
00927 /* ------------------------------------------------------------------------ */
00928 /* .BMP file structures */
00929 struct rgbquad {
00930        char blue;
00931        char green;
00932        char red;
00933        char res;
00934 };
00935 
00936 struct bitmapinfoheader {
00937        integer size;
00938        integer width;
00939        integer height;
00940        halfword planes;                   /* must be set to 1 */
00941        halfword bitcount;                 /* 1, 4, 8 or 24 */
00942        integer compression;
00943        integer sizeimage;
00944        integer xpelspermeter;
00945        integer ypelspermeter;
00946        integer clrused;
00947        integer clrimportant;
00948 };
00949 
00950 #ifdef WIN32
00951 #undef RGB
00952 #endif
00953 
00954 /* constants for the compression field */
00955 #define RGB 0L
00956 #define RLE8 1L
00957 #define RLE4 2L
00958 
00959 struct bitmapfileheader {
00960        char type[2];
00961        integer size;
00962        halfword reserved1;
00963        halfword reserved2;
00964        integer offbits;
00965 };
00966 
00967 void rgbread P4C(FILE *, f, int, w, int, b, char *, s)
00968 {
00969        int i;
00970 
00971        /* set the line to white */
00972        memset(s, 0xff, ((w*b)/8)+1); 
00973 
00974        /* read in all the full bytes */
00975        for (i = 0; i < (w * b) / 8; i++)
00976               *s++ = fgetc(f);
00977 
00978        /* read in a partly filled byte */
00979        if ((w * b) % 8) {
00980               i++;
00981               *s++ = fgetc(f);
00982        }
00983 
00984        /* check that we are on a 32 bit boundary; otherwise align */
00985        while (i % 4 != 0) {
00986               fgetc(f);
00987               i++;
00988        }
00989 }
00990 
00991 unsigned rle_dx = 0; /* delta command horizontal offset */
00992 unsigned rle_dy = 0; /* delta command vertical offset */
00993 
00994 /* checked against output from Borland Resource Workshop */
00995 void rle4read P4C(FILE *, f, int, w, int, b, char *, s)
00996 {
00997        int i;
00998        int limit;
00999        int ch;
01000        unsigned cnt;
01001        int hi;
01002 
01003        limit = (w*b)/8;
01004        i = 0;
01005        hi = TRUE;
01006        /* set the line to white */
01007        memset(s, 0xff, limit+1); 
01008 
01009        if (rle_dy) {
01010            rle_dy--;
01011            return;
01012        }
01013 
01014        if (rle_dx) {
01015            for ( ; rle_dx>1; rle_dx-=2) {
01016               s++;
01017               i++;
01018            }
01019            if (rle_dx)
01020               hi = FALSE;
01021        }
01022 
01023        while (i<=limit) {
01024            cnt = fgetc(f);
01025            ch  = fgetc(f);
01026            if (cnt == 0) { /* special operation */
01027               switch(ch) {
01028                   case 0:   /* EOL */
01029                      return;       /* this is our way out */
01030                   case 1:   /* End of Bitmap */
01031                      return;
01032                   case 2:   /* Delta */  /* untested */
01033                      rle_dx = fgetc(f) + i*2 + (hi ? 1 : 0);
01034                      rle_dy = fgetc(f);
01035                      return;
01036                   default:  /* next cnt bytes are absolute */
01037                      /* must be aligned on word boundary */
01038                      if (!hi)
01039                             fprintf(stderr,"em:graph: RLE4 absolute is not byte aligned\n");
01040                      for (cnt = ch; cnt>0 && i<=limit; cnt-=2) {
01041                          i++;
01042                          *s++ = fgetc(f);
01043                      }
01044                      if (ch % 4)   /* word align file */
01045                          (void)fgetc(f);
01046               }
01047            }
01048            else {   /* cnt is repeat count */
01049               if (!hi) {   /* we are about to place the low 4 bits */
01050                   ch = ((ch>>4)&0x0f) | ((ch<<4)&0xf0); /* swap order */
01051                   i++;
01052                   *s = (*s & 0xf0) | (ch & 0x0f);
01053                     s++ ;
01054                   hi = TRUE;
01055                   cnt--;
01056               }
01057               /* we are about to place the high 4 bits */
01058               for ( ; cnt>1 && i<=limit ; cnt-=2) { /* place the whole bytes */
01059                   i++;
01060                   *s++ = ch;
01061                }
01062               if (cnt) { /* place the partial byte */
01063                   *s = (*s & 0x0f) | (ch & 0xf0);
01064                   hi = FALSE;
01065               }
01066            }
01067        }
01068 }
01069   
01070 /* untested */
01071 void rle8read P4C(FILE *, f, int, w, int, b, char *, s)
01072 {
01073        int i;
01074        int limit;
01075        int ch;
01076        unsigned cnt;
01077 
01078        limit = (w*b)/8;
01079        i = 0;
01080        /* set the line to white */
01081        memset(s, 0xff, limit+1); 
01082 
01083        if (rle_dy) {
01084            rle_dy--;
01085            return;
01086        }
01087 
01088        if (rle_dx) {
01089            for ( ; rle_dx > 0; rle_dx--) {
01090               s++;
01091               i++;
01092            }
01093        }
01094 
01095        while (i<=limit) {
01096            cnt = fgetc(f);
01097            ch  = fgetc(f);
01098            if (cnt == 0) { /* special operation */
01099               switch(ch) {
01100                   case 0:   /* EOL */
01101                      return;       /* this is our way out */
01102                   case 1:   /* End of Bitmap */
01103                      return;
01104                   case 2:   /* Delta */  /* untested */
01105                      rle_dx = fgetc(f) + i;
01106                      rle_dy = fgetc(f);
01107                      return;
01108                   default:  /* next cnt bytes are absolute */
01109                      for (cnt = ch; cnt>0 && i<=limit; cnt--) {
01110                          i++;
01111                          *s++ = fgetc(f);
01112                       }
01113                      if (ch % 2)   /* word align file */
01114                          (void)fgetc(f);
01115               }
01116            }
01117            else { /* cnt is repeat count */
01118               for ( ; cnt>0 && i<=limit; cnt--) {
01119                   i++;
01120                   *s++ = ch;
01121               }
01122            }
01123        }
01124 }
01125 
01126 void bmpgraph P4C(FILE *, f, char *, filename, float, emwidth, float, emheight)
01127 {
01128        struct bitmapfileheader bmfh;
01129        struct bitmapinfoheader bmih;
01130 
01131        unsigned char isblack[256];
01132        unsigned char rr;
01133        unsigned char gg;
01134        unsigned char bb;
01135        unsigned char c = 0;
01136 
01137        char *line;
01138        char *pshexa;
01139 
01140        int clrtablesize;
01141        int i;
01142        int j;
01143 
01144        unsigned char omask;
01145        int oroll;
01146 
01147        unsigned char emask = 0;
01148        integer ewidth = 0;
01149        int isOS2;
01150 
01151         /* read the header of the file */
01152        fread(bmfh.type, 1, 2, f);
01153        bmfh.size = readinteger(f);
01154        bmfh.reserved1 = readhalfword(f);
01155        bmfh.reserved2 = readhalfword(f);
01156        bmfh.offbits = readinteger(f);
01157        if (feof(f)) {
01158               sprintf(errbuf, "em:graph: Unable to Read Valid BMP Header\n");
01159               specerror(errbuf);
01160               return;
01161        }
01162 
01163        bmih.size = readinteger(f);
01164        if (bmih.size == 12) { /* OS2 bitmap */
01165               isOS2 = TRUE; 
01166               bmih.width = readhalfword(f);
01167               bmih.height = readhalfword(f);
01168               bmih.planes = readhalfword(f);
01169               bmih.bitcount = readhalfword(f);
01170               /* the following don't exist in OS2 format so fill with 0's */
01171               bmih.compression = RGB;
01172               bmih.sizeimage = 0;
01173               bmih.xpelspermeter = 0;
01174               bmih.ypelspermeter = 0;
01175               bmih.clrused = 0;
01176               bmih.clrimportant = 0;
01177        }
01178        else { /* Windows bitmap */
01179               isOS2 = FALSE;       
01180               bmih.width = readinteger(f);
01181               bmih.height = readinteger(f);
01182               bmih.planes = readhalfword(f);
01183               bmih.bitcount = readhalfword(f);
01184               bmih.compression = readinteger(f);
01185               bmih.sizeimage = readinteger(f);
01186               bmih.xpelspermeter = readinteger(f);
01187               bmih.ypelspermeter = readinteger(f);
01188               bmih.clrused = readinteger(f);
01189               bmih.clrimportant = readinteger(f);
01190        }
01191 
01192        if (feof(f)) {
01193               sprintf(errbuf, "em:graph: Unable to Read Valid BMP Info");
01194               specerror(errbuf);
01195               return;
01196        }
01197 
01198        if (memcmp(bmfh.type, "BM", 2)) {
01199               sprintf(errbuf, "em:graph: Unknown BMP File Type");
01200               specerror(errbuf);
01201               return;
01202        }
01203 
01204        if ((bmih.compression == RLE4) && (bmih.bitcount != 4)) {
01205               sprintf(errbuf, "em:graph: Can't do BMP RLE4 with %d bits per pixel",
01206                      bmih.bitcount);
01207               specerror(errbuf);
01208               return;
01209        }
01210 
01211        if ((bmih.compression == RLE8) && (bmih.bitcount != 8)) {
01212               sprintf(errbuf, "em:graph: Can't do BMP RLE8 with %d bits per pixel\n",
01213                      bmih.bitcount);
01214               specerror(errbuf);
01215               return;
01216        }
01217 
01218        imagehead(filename,(int)bmih.width,(int)bmih.height,emwidth,emheight);
01219 
01220        /* determine the size of the color table to read */
01221        clrtablesize = 0;
01222        if (bmih.clrused == 0) {
01223               switch (bmih.bitcount) {
01224                      case 1:
01225                             clrtablesize = 2;
01226                             break;
01227                      case 4:
01228                             clrtablesize = 16;
01229                             break;
01230                      case 8:
01231                             clrtablesize = 256;
01232                             break;
01233                      case 24:
01234                             break;
01235               }
01236        }
01237         else
01238               clrtablesize = bmih.clrused;
01239 
01240        /* read in the color table */
01241        for (i = 0; i < clrtablesize; i++) {
01242               bb = fgetc(f);
01243               gg = fgetc(f);
01244               rr = fgetc(f);
01245               isblack[i] = (rr < 0xff) || (gg < 0xff) || (bb < 0xff);
01246               if (!isOS2)
01247                      (void) fgetc(f);
01248        }
01249 
01250        line = (char *) mymalloc((integer)((bmih.width * bmih.bitcount) / 8) + 1);
01251        pshexa = (char *) mymalloc((integer)tobyte(bmih.width));
01252 
01253        /* output the postscript image size preamble */
01254        cmdout("/picstr");
01255        numout((integer)tobyte(bmih.width));
01256        cmdout("string def");
01257 
01258        numout((integer)bmih.width);
01259        numout((integer)bmih.height);
01260        numout((integer)1);
01261 
01262        cmdout("[");
01263        numout((integer)bmih.width);
01264        numout((integer)0);
01265        numout((integer)0);
01266        numout((integer)bmih.height);
01267        numout((integer)0);
01268        numout((integer)bmih.height);
01269        cmdout("]");
01270 
01271        nlcmdout("{currentfile picstr readhexstring pop} image");
01272 
01273        if (bmih.bitcount == 1) {
01274               if (bmih.width%8)
01275                      emask = (1<<(8-(bmih.width%8)))-1; /* mask for edge of bitmap */
01276               else
01277                      emask = 0;
01278               ewidth = tobyte(bmih.width);
01279        }
01280 
01281        /* read in all the lines of the file */
01282        for (i = 0; i < bmih.height; i++) {
01283               memset(pshexa,0xff,tobyte(bmih.width));
01284               switch (bmih.compression) {
01285                   case RGB:
01286                      rgbread(f, (int) bmih.width, (int) bmih.bitcount, line);
01287                      break;
01288                   case RLE4:
01289                      rle4read(f, (int) bmih.width, (int) bmih.bitcount, line);
01290                      break;
01291                   case RLE8:
01292                      rle8read(f, (int) bmih.width, (int) bmih.bitcount, line);
01293                      break;
01294                   default:
01295                      sprintf(errbuf,"em:graph: Unknown BMP compression\n");
01296                      specerror(errbuf);
01297                      return;
01298               }
01299 
01300               omask = 0x80;
01301               oroll = 7;
01302 
01303               if (bmih.bitcount == 1) {
01304                   if (isblack[0])
01305                      for (j = 0; j < ewidth ; j++)
01306                             pshexa[j] = line[j];
01307                   else
01308                      for (j = 0; j < ewidth ; j++)
01309                             pshexa[j] = ~line[j];
01310                   pshexa[ewidth-1] |= emask;
01311               }
01312               else {
01313                   for (j = 0; j < bmih.width; j++) {
01314                      switch (bmih.bitcount) {
01315                             case 4:
01316                                    c = line[j>>1];
01317                                    if (!(j&1))
01318                                           c >>= 4;
01319                                    c = isblack[ c & 0x0f ];
01320                                    break;
01321                             case 8:
01322                                    c = isblack[ (int)(line[j]) ];
01323                                    break;
01324                             case 24:
01325                                    rr = line[j*3];
01326                                    gg = line[j*3+1];
01327                                    bb = line[j*3+2];
01328                                    c = (rr < 0xff) || (gg < 0xff) || (bb < 0xff);
01329                                    break;
01330                      }
01331                      if (c) 
01332                          pshexa[j/8] &= ~omask;
01333                      else
01334                          pshexa[j/8] |= omask;
01335                      oroll--;
01336                      omask >>= 1;
01337                      if (oroll < 0) {
01338                          omask = 0x80;
01339                          oroll = 7;
01340                      }
01341                   }
01342               }
01343               newline();
01344               mhexout((unsigned char *) pshexa,(long)tobyte(bmih.width));
01345        }
01346        imagetail() ;
01347        free(pshexa);
01348        free(line);
01349 }
01350 /* ------------------------------------------------------------------------ */
01351 
01352 #define PCX 0
01353 #define MSP 1
01354 #define BMP 2
01355 char *extarr[]=
01356 { ".pcx", ".msp", ".bmp", NULL };
01357 
01358 void emgraph P3C(char *, filename, float, emwidth, float, emheight)
01359 {
01360        char fname[80];
01361        int filetype;
01362        FILE *f;
01363        char *env;
01364        char id[4];
01365        int i;
01366 
01367        strcpy(fname, filename);
01368 
01369        /* find the file */
01370        f = search(figpath, fname, READBIN);
01371        if (f == (FILE *)NULL) {
01372            if ( (env = getenv("DVIDRVGRAPH")) != NULL )
01373 #ifdef KPATHSEA
01374               f = search((kpse_file_format_type)env,filename,READBIN);
01375 #else
01376               f = search(env,filename,READBIN);
01377 #endif
01378        }
01379        /* if still haven't found it try adding extensions */
01380        if (f == (FILE *)NULL) {
01381            i = 0;
01382            while (extarr[i] != NULL) {
01383               strcpy(fname, filename);
01384               strcat(fname, extarr[i]);
01385               f = search(figpath, fname, READBIN);
01386               if (f == (FILE *)NULL) {
01387                   if ( (env = getenv("DVIDRVGRAPH")) != NULL )
01388 #ifdef KPATHSEA
01389                      f = search((kpse_file_format_type)env,filename,READBIN);
01390 #else
01391                      f = search(env,filename,READBIN);
01392 #endif
01393               }
01394               if (f != (FILE *)NULL)
01395                   break;
01396               i++;
01397            }
01398        }
01399 
01400        filetype = -1;
01401        if (f != (FILE *)NULL) {
01402            for (i=0; i<4; i++) {
01403               id[i] = readquarterword(f);
01404            }
01405            if ( (id[0] == 0x0a) && (id[2] == 0x01) )
01406               filetype = PCX;
01407            if (!memcmp(id, "DanM", 4))
01408               filetype = MSP;
01409            if (!memcmp(id, "LinS", 4))
01410               filetype = MSP;
01411            if (!memcmp(id, "BM", 2))
01412               filetype = BMP;
01413            fseek(f, 0L, SEEK_SET);
01414        }
01415 
01416        switch (filetype) {
01417               case PCX:
01418                      pcxgraph(f, fname, emwidth, emheight);
01419                      break;
01420               case MSP:
01421                      mspgraph(f, fname, emwidth, emheight);
01422                      break;
01423               case BMP:
01424                      bmpgraph(f, fname, emwidth, emheight);
01425                      break;
01426               default:
01427                      sprintf(fname,"em:graph: %s: File not found", filename);
01428                      error(fname);
01429        }
01430        if (f != (FILE *)NULL)
01431            close_file(f);
01432 }
01433 
01434 #else
01435 void emspecial P1C(char *, p)
01436 {
01437        sprintf(errbuf,"emTeX specials not compiled in this version");
01438        specerror(errbuf);
01439 }
01440 #endif /* EMTEX */