about summary refs log tree commit diff
path: root/converter/ppm/sldtoppm.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/sldtoppm.c')
-rw-r--r--converter/ppm/sldtoppm.c220
1 files changed, 131 insertions, 89 deletions
diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c
index 550eed5b..2dc049f8 100644
--- a/converter/ppm/sldtoppm.c
+++ b/converter/ppm/sldtoppm.c
@@ -50,7 +50,7 @@ struct spoint {
 
 /* Screen polygon */
 
-struct spolygon { 
+struct spolygon {
     int npoints,              /* Number of points in polygon */
           fill;           /* Fill type */
     struct spoint pt[11];         /* Actual points */
@@ -130,7 +130,7 @@ sli(void) {
 
 /*  SLIB  --  Input byte from slide file  */
 
-static int 
+static int
 slib(void) {
     unsigned char ch;
 
@@ -154,85 +154,127 @@ vscale(int * const px,
 
 
 
+static void
+upcase(const char * const sname,
+       char *       const uname) {
+
+    unsigned int i;
+    const char * ip;
+
+    for (i = 0, ip = sname; i < 31; ++i) {
+        char const ch = *ip++;
+
+        if (ch != EOS)
+            uname[i] = islower(ch) ? toupper(ch) : ch;
+    }
+    uname[i] = EOS;
+}
+
+
+
+static void
+skipBytes(FILE *       const fileP,
+          unsigned int const count) {
+
+    unsigned int i;
+
+    for (i = 0; i < count; ++i)
+        getc(fileP);
+}
+
+
+
+static void
+scanDirectory(FILE *       const slFileP,
+              long         const dirPos,
+              bool         const dirOnly,
+              const char * const uname,
+              bool *       const foundP) {
+/*----------------------------------------------------------------------------
+   Scan the directory at the current position in *slFileP, either listing
+   the directory ('dirOnly' true) or searching for a slide named
+   'uname' ('dirOnly' false).
+
+   'dirPos' is the offset in the file of the directory, i.e. the current
+   position of *slFileP.
+
+   In the latter case, return as *foundP whether the slide name is there.
+-----------------------------------------------------------------------------*/
+    bool found;
+    bool eof;
+    long pos;
+    unsigned char libent[36];
+
+    for (found = false, eof = false, pos = dirPos; !found && !eof; ) {
+        size_t readCt;
+        readCt = fread(libent, 36, 1, slFileP);
+        if (readCt != 1)
+            eof = true;
+        else {
+            /* The directory entry is 32 bytes of NUL-terminated slide name
+               followed by 4 bytes of offset of the next directory entry.
+            */
+            const char * const slideName = (const char *)(&libent[0]);
+            if (pm_strnlen(slideName, 32) == 32)
+                pm_error("Invalid input: slide name field is not "
+                         "nul-terminated");
+            else {
+                if (strlen(slideName) == 0)
+                    eof = true;
+                else {
+                    pos += 36;
+                    if (dirOnly) {
+                        pm_message("  %s", slideName);
+                    } else if (streq(slideName, uname)) {
+                        long const dpos =
+                            (((((libent[35] << 8) | libent[34]) << 8) |
+                              libent[33]) << 8) | libent[32];
+
+                        if ((slFileP == stdin) ||
+                            (fseek(slFileP, dpos, 0) == -1)) {
+
+                            skipBytes(slFileP, dpos - pos);
+                        }
+                        found = true;
+                    }
+                }
+            }
+        }
+    }
+    *foundP = found;
+}
+
 /*  SLIDEFIND  --  Find  a  slide  in  a  library  or,  if  DIRONLY is
            nonzero, print a directory listing of the  library.
            If  UCASEN  is nonzero, the requested slide name is
            converted to upper case. */
 
 static void
-slidefind(const char * const sname,
-          bool         const dironly,
+slidefind(const char * const slideName,
+          bool         const dirOnly,
           bool         const ucasen) {
 
-    char uname[32];
-    unsigned char libent[36];
-    long pos;
+    char uname[32];  /* upper case translation of 'slideName' */
+    char header[32]; /* (supposed) header read from file */
     bool found;
-    bool eof;
 
-    if (dironly)
+    if (dirOnly)
         pm_message("Slides in library:");
     else {
-        unsigned int i;
-        const char * ip;
-        
-        ip = sname; /* initial value */
-        
-        for (i = 0; i < 31; ++i) {
-            char const ch = *ip++;
-            if (ch == EOS)
-                break;
-
-            {
-                char const upperCh =
-                    ucasen && islower(ch) ? toupper(ch) : ch;
-                
-                uname[i] = upperCh;
-            }
-        }
-        uname[i] = EOS;
+        upcase(slideName, uname);
     }
-    
+
     /* Read slide library header and verify. */
-    
-    if ((fread(libent, 32, 1, slfile) != 1) ||
-        (!strneq((char *)libent, "AutoCAD Slide Library 1.0\015\012\32", 32))) {
+
+    if ((fread(header, 32, 1, slfile) != 1) ||
+        (!STRSEQ(header, "AutoCAD Slide Library 1.0\r\n\32"))) {
         pm_error("not an AutoCAD slide library file.");
     }
-    pos = 32;
-    
-    /* Search for a slide with the requested name or list the directory */
-    
-    for (found = false, eof = false; !found && !eof; ) {
-        size_t readCt;
-        readCt = fread(libent, 36, 1, slfile);
-        if (readCt != 1)
-            eof = true;
-        else if (strnlen((char *)libent, 32) == 0)
-            eof = true;
 
-        if (!eof) {
-            pos += 36;
-            if (dironly) {
-                pm_message("  %s", libent);
-            } else if (strneq((char *)libent, uname, 32)) {
-                long dpos;
-
-                dpos = (((((libent[35] << 8) | libent[34]) << 8) |
-                         libent[33]) << 8) | libent[32];
-        
-                if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
-                    dpos -= pos;
-
-                    while (dpos-- > 0)
-                        getc(slfile);
-                }
-                found = true;
-            }
-        }
-    }
-    if (!found && !dironly)
-        pm_error("slide '%s' not in library.", sname);
+    scanDirectory(slfile, 32, dirOnly, ucasen ? uname : slideName, &found);
+
+    if (!found && !dirOnly)
+        pm_error("slide '%s' not in library.", slideName);
 }
 
 
@@ -295,14 +337,14 @@ flood(struct spolygon * const poly,
         assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols);
         assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows);
         ppmd_line(pixels, pixcols, pixrows, pixmaxval,
-                  poly->pt[i].x, iydots - poly->pt[i].y, 
+                  poly->pt[i].x, iydots - poly->pt[i].y,
                   poly->pt[(i + 1) % poly->npoints].x,
                   iydots - poly->pt[(i + 1) % poly->npoints].y,
                   ppmd_fill_drawproc, handle);
     }
     ppmd_fill(pixels, pixcols, pixrows, pixmaxval,
               handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor);
-    
+
     ppmd_fill_destroy(handle);
 }
 
@@ -333,11 +375,11 @@ slider(slvecfn   slvec,
     {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0};
     int curcolor = 7;             /* Current vector color */
     pixel rgbcolor;           /* Pixel used to clear pixmap */
-    
+
     lx = ly = 32000;
-    
+
     /* Process the header of the slide file.  */
-    
+
     sdrawkcab = false;            /* Initially guess byte order is OK */
     fread(slfrof.slh, 17, 1, slfile);
     fread(&slfrof.sntype, sizeof(char), 1, slfile);
@@ -361,12 +403,12 @@ slider(slvecfn   slvec,
         pm_error("incompatible slide file format");
 
     /* Build SDSAR value from long scaled version. */
-    
+
     ldsar = 0L;
     for (i = 3; i >= 0; --i)
         ldsar = (ldsar << 8) | ubfr[i];
     slfrof.sdsar = ((double) ldsar) / 1E7;
-    
+
     /* Examine the byte order test value.   If it's backwards, set the
        byte-reversal flag and correct all of the values we've read  in
        so far.
@@ -380,7 +422,7 @@ slider(slvecfn   slvec,
         rshort(slfrof.shwfill);
         #undef rshort
     }
-    
+
     /* Dump the header if we're blithering. */
 
     if (blither || info) {
@@ -455,29 +497,29 @@ slider(slvecfn   slvec,
         }
         iydots = sysize - 1;
     }
-    
+
     if (adjust) {
         pm_message(
             "Resized from %dx%d to %dx%d to correct pixel aspect ratio.",
             slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1);
     }
-    
+
     /* Allocate image buffer and clear it to black. */
-    
+
     pixels = ppm_allocarray(pixcols = ixdots + 1, pixrows = iydots + 1);
     PPM_ASSIGN(rgbcolor, 0, 0, 0);
     ppmd_filledrectangle(pixels, pixcols, pixrows, pixmaxval, 0, 0,
                          pixcols, pixrows, PPMD_NULLDRAWPROC,
                          (char *) &rgbcolor);
-    
+
     if ((rescale = slfrof.sxdots != ixdots ||
          slfrof.sydots != iydots ||
          slfrof.sdsar != dsar) != 0) {
-        
+
         /* Rescale all coords. so they'll look (more or less)
            right on this display.
         */
-        
+
         xfac = (ixdots + 1) * 0x10000L;
         xfac /= (long) (slfrof.sxdots + 1);
         yfac = (iydots + 1) * 0x10000L;
@@ -490,7 +532,7 @@ slider(slvecfn   slvec,
     }
 
     poly.npoints = 0;             /* No flood in progress. */
-    
+
     while ((cw = sli()) != 0xFC00) {
         switch (cw & 0xFF00) {
         case 0xFB00:          /*  Short vector compressed  */
@@ -508,10 +550,10 @@ slider(slvecfn   slvec,
             slx = vec.f.x;        /* Save scaled point */
             sly = vec.f.y;
             break;
-            
+
         case 0xFC00:          /*  End of file  */
             break;
-            
+
         case 0xFD00:          /*  Flood command  */
             vec.f.x = sli();
             vec.f.y = sli();
@@ -538,7 +580,7 @@ slider(slvecfn   slvec,
                 poly.npoints++;
             }
             break;
-            
+
         case 0xFE00:          /*  Common endpoint compressed  */
             vec.f.x = lx + extend(cw & 0xFF);
             vec.f.y = ly + slib();
@@ -553,7 +595,7 @@ slider(slvecfn   slvec,
             slx = vec.f.x;        /* Save scaled point */
             sly = vec.f.y;
             break;
-            
+
         case 0xFF00:          /*  Change color  */
             curcolor = cw & 0xFF;
             break;
@@ -661,7 +703,7 @@ main(int          argc,
     }
 
     /* If a file name is specified, open it.  Otherwise read from
-       standard input. 
+       standard input.
     */
 
     if (argn < argc) {
@@ -670,24 +712,24 @@ main(int          argc,
     } else {
         slfile = stdin;
     }
-    
+
     if (argn != argc) {           /* Extra bogus arguments ? */
         pm_usage(usage);
     }
-    
+
     /* If we're extracting an item from a slide library, position the
        input stream to the start of the chosen slide.
     */
- 
+
     if (dironly || slobber)
         slidefind(slobber, dironly, ucasen);
- 
+
     if (!dironly) {
         slider(draw, flood);
         ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, 0);
     }
     pm_close(slfile);
     pm_close(stdout);
-    
+
     return 0;
 }