about summary refs log tree commit diff
path: root/converter/ppm/ppmtowinicon.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtowinicon.c')
-rw-r--r--converter/ppm/ppmtowinicon.c1092
1 files changed, 556 insertions, 536 deletions
diff --git a/converter/ppm/ppmtowinicon.c b/converter/ppm/ppmtowinicon.c
index c673798f..2d8ddaf7 100644
--- a/converter/ppm/ppmtowinicon.c
+++ b/converter/ppm/ppmtowinicon.c
@@ -1,4 +1,4 @@
-/* ppmtowinicon.c - read portable pixmap file(s) and write a MS Windows .ico
+/* ppmtowinicon.c - read PPM images and write a MS Windows .ico
 **
 ** Copyright (C) 2000 by Lee Benfield - lee@benf.org
 **
@@ -10,6 +10,8 @@
 ** implied warranty.
 */
 
+#include <stdbool.h>
+#include <assert.h>
 #include <math.h>
 #include <string.h>
 
@@ -25,31 +27,30 @@
 
 #define MAXCOLORS 256
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    unsigned int iconCount;
-    const char **inputFilespec;  /* '-' if stdin; malloc'ed array */
-    const char **andpgmFilespec;    /* NULL if unspecified; malloc'ed array */
-    const char *output;     /* '-' if unspecified */
-    unsigned int truetransparent;
-    unsigned int verbose;
+    unsigned int  iconCount;
+    const char ** inputFileNm;  /* '-' if stdin; malloc'ed array */
+    const char ** andpgmFileNm;    /* NULL if unspecified; malloc'ed array */
+    const char *  output;     /* '-' if unspecified */
+    unsigned int  truetransparent;
+    unsigned int  verbose;
 };
 
 
 static bool verbose;
 
-static int      file_offset = 0; /* not actually used, but useful for debug. */
-static FILE *   ofp;
+static int      fileOffset = 0; /* not actually used, but useful for debug. */
 
 static void
-parseCommandLine(int                 argc, 
-                 char **             argv,
-                 struct cmdlineInfo *cmdlineP ) {
+parseCommandLine(int                  argc,
+                 const char **        argv,
+                 struct CmdlineInfo * cmdlineP) {
 /*----------------------------------------------------------------------------
    Parse program command line described in Unix standard form by argc
-   and argv.  Return the information in the options as *cmdlineP.  
+   and argv.  Return the information in the options as *cmdlineP.
 
    If command line is internally inconsistent (invalid options, etc.),
    issue error message to stderr and abort program.
@@ -57,9 +58,7 @@ parseCommandLine(int                 argc,
    Note that the strings we return are stored in the storage that
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
-    optEntry *option_def;
-        /* Instructions to pm_optParseOptions3 on how to parse our options.
-         */
+    optEntry * option_def;
     optStruct3 opt;
 
     unsigned int option_def_index;
@@ -79,34 +78,33 @@ parseCommandLine(int                 argc,
             &cmdlineP->verbose,            0);
 
     opt.opt_table = option_def;
-    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
-    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+    opt.short_allowed = false;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = false;  /* We have no parms that are negative numbers */
 
-    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions4(&argc, argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (!outputSpec)
         cmdlineP->output = "-";
 
-
     if (!andpgms) {
         if (argc-1 == 0) {
             cmdlineP->iconCount = 1;
-            MALLOCARRAY_NOFAIL(cmdlineP->inputFilespec, cmdlineP->iconCount);
-            cmdlineP->inputFilespec[0] = "-";
+            MALLOCARRAY_NOFAIL(cmdlineP->inputFileNm, cmdlineP->iconCount);
+            cmdlineP->inputFileNm[0] = "-";
         } else {
             unsigned int iconIndex;
 
             cmdlineP->iconCount = argc-1;
-            MALLOCARRAY_NOFAIL(cmdlineP->inputFilespec, cmdlineP->iconCount);
+            MALLOCARRAY_NOFAIL(cmdlineP->inputFileNm, cmdlineP->iconCount);
             for (iconIndex = 0; iconIndex < cmdlineP->iconCount; ++iconIndex)
-                cmdlineP->inputFilespec[iconIndex] = argv[iconIndex+1];
+                cmdlineP->inputFileNm[iconIndex] = argv[iconIndex+1];
         }
         {
             unsigned int iconIndex;
-            MALLOCARRAY_NOFAIL(cmdlineP->andpgmFilespec, cmdlineP->iconCount);
+            MALLOCARRAY_NOFAIL(cmdlineP->andpgmFileNm, cmdlineP->iconCount);
             for (iconIndex = 0; iconIndex < cmdlineP->iconCount; ++iconIndex)
-                cmdlineP->andpgmFilespec[iconIndex] = NULL;
+                cmdlineP->andpgmFileNm[iconIndex] = NULL;
         }
     } else {
         if (argc-1 < 2)
@@ -119,11 +117,11 @@ parseCommandLine(int                 argc,
         else {
             unsigned int iconIndex;
             cmdlineP->iconCount = (argc-1)/2;
-            MALLOCARRAY_NOFAIL(cmdlineP->inputFilespec, cmdlineP->iconCount);
-            MALLOCARRAY_NOFAIL(cmdlineP->andpgmFilespec, cmdlineP->iconCount);
+            MALLOCARRAY_NOFAIL(cmdlineP->inputFileNm, cmdlineP->iconCount);
+            MALLOCARRAY_NOFAIL(cmdlineP->andpgmFileNm, cmdlineP->iconCount);
             for (iconIndex = 0; iconIndex < cmdlineP->iconCount; ++iconIndex) {
-                cmdlineP->inputFilespec[iconIndex] = argv[1 + iconIndex*2];
-                cmdlineP->andpgmFilespec[iconIndex] = argv[2 + iconIndex*2];
+                cmdlineP->inputFileNm[iconIndex] = argv[1 + iconIndex*2];
+                cmdlineP->andpgmFileNm[iconIndex] = argv[2 + iconIndex*2];
             }
         }
     }
@@ -132,429 +130,430 @@ parseCommandLine(int                 argc,
 
 
 
-static void 
-PutByte(int const v) {
-   
-   if (putc(v, ofp) == EOF)
-       pm_error("Unable to write byte to output file.");
+static void
+freeCmdline(struct CmdlineInfo const cmdline) {
+
+    free(cmdline.inputFileNm);
+    free(cmdline.andpgmFileNm);
 }
-   
 
 
-static void 
-PutShort(short const v) {
-   
-   if (pm_writelittleshort(ofp, v) == -1)
-       pm_error("Unable to write short integer to output file");
-}
-   
 
+static void
+writeU1(FILE * const ofP,
+        u1     const v) {
 
-static void 
-PutLong(long const v) {
-   
-   if (pm_writelittlelong(ofp, v) == -1)
-       pm_error("Unable to write long integer to output file");
+    ++fileOffset;
+    pm_writechar(ofP, v);
 }
 
 
-   
-/*
- * These have no purpose but to wrapper the Byte, Short & Long 
- * functions.
- */
-static void 
-writeU1 (u1 const v) {
-   file_offset++;
-   PutByte(v);
-}
 
-static  void 
-writeU2 (u2 const v) {
-   file_offset +=2;
-   PutShort(v);
-}
+static  void
+writeU2(FILE * const ofP,
+        u2     const v) {
 
-static void 
-writeU4 (u4 const v) {
-   file_offset += 4;
-   PutLong(v);
+    fileOffset +=2;
+    pm_writelittleshort(ofP, v);
 }
 
-static MS_Ico 
-createIconFile (void) {
-   MS_Ico MSIconData;
-   
-   MALLOCVAR_NOFAIL(MSIconData);
-
-   MSIconData->reserved     = 0;
-   MSIconData->type         = 1;
-   MSIconData->count        = 0;
-   MSIconData->entries      = NULL;
-   return MSIconData;
+
+
+static void
+writeU4(FILE * const ofP,
+        u4     const v) {
+
+    fileOffset += 4;
+    pm_writelittlelong(ofP, v);
 }
 
 
-/* create andBitmap from pgm */
 
-static ICON_bmp 
-createAndBitmap (gray ** const ba, int const cols, int const rows,
-                 gray const maxval) {
-   /*
-    * How wide should the u1 string for each row be?
-    * each byte is 8 pixels, but must be a multiple of 4 bytes.
-    */
-   unsigned int const xBytes = ROUNDUP(cols, 32)/8;
-   ICON_bmp icBitmap;
-   int y,x;
-   u1 ** rowData;
-
-   MALLOCVAR_NOFAIL(icBitmap);
-
-   MALLOCARRAY_NOFAIL(rowData, rows);
-   icBitmap->xBytes = xBytes;
-   icBitmap->data   = rowData;
-   icBitmap->size   = xBytes * rows;
-   for (y=0;y<rows;y++) {
-      u1 * row;
-      int byteOn = 0;
-      int bitOn = 128;
-
-      MALLOCARRAY_NOFAIL(row, xBytes);
-
-      memset (row, 0, xBytes);
-      rowData[rows-y-1] = row;
-      /* 
-       * Check there's a bit array, otherwise we're just faking this...
-       */
-      if (ba) {
-     for (x=0;x<cols;x++) {
-            /* Black (bit clear) is transparent in PGM alpha maps,
-             * in ICO bit *set* is transparent.
-             */
-            if (ba[y][x] <= maxval/2) row[byteOn] |= bitOn;
-
-        if (bitOn == 1) {
-           byteOn++;
-           bitOn = 128;
-        } else {
-           bitOn >>= 1;
-        }
-     }
-      }
-   }
-   return icBitmap;
+static MS_Ico *
+newIconFile(void) {
+
+   MS_Ico * MSIconDataP;
+
+   MALLOCVAR_NOFAIL(MSIconDataP);
+
+   MSIconDataP->reserved     = 0;
+   MSIconDataP->type         = 1;
+   MSIconDataP->count        = 0;
+   MSIconDataP->entries      = NULL;
+
+   return MSIconDataP;
 }
 
 
-/*
- * Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the 
- * encoding mechanism is different.
- * 
- * I didn't re-use the code from ppmtobmp since I need to keep the
- * bitmaps in memory till I've loaded all ppms.
- * 
- * 8bpp => 1 byte/palette index.
- * 4bpp => High Nibble, Low Nibble
- * 1bpp => 1 palette value per bit, high bit 1st.
- */
-static ICON_bmp 
-create1Bitmap (pixel ** const pa, int const cols, int const rows, 
-               colorhash_table const cht) {
-   /*
-    * How wide should the u1 string for each row be?
-    * each byte is 8 pixels, but must be a multiple of 4 bytes.
-    */
-   ICON_bmp icBitmap;
-   int xBytes,y,x;
-   int wt = cols;
-   u1 ** rowData;
-
-   MALLOCVAR_NOFAIL(icBitmap);
-   
-   wt >>= 3;
-   if (wt & 3) {
-      wt = (wt & ~3) + 4;
-   }
-   xBytes = wt;
-   MALLOCARRAY_NOFAIL(rowData, rows);
-   icBitmap->xBytes = xBytes;
-   icBitmap->data   = rowData;
-   icBitmap->size   = xBytes * rows;
-   for (y=0;y<rows;y++) {
-      u1 * row;
-      int byteOn = 0;
-      int bitOn = 128;
-      int value;
-      
-      MALLOCARRAY_NOFAIL(row, xBytes);
-      memset (row, 0, xBytes);
-      rowData[rows-y-1] = row;
-      /* 
-       * Check there's a pixel array, otherwise we're just faking this...
+
+static ICON_bmp *
+newAndBitmap(gray **      const ba,
+             unsigned int const cols,
+             unsigned int const rows,
+             gray         const maxval) {
+/*----------------------------------------------------------------------------
+  create andBitmap from PGM
+-----------------------------------------------------------------------------*/
+    unsigned int const xByteCt = ROUNDUP(cols, 32)/8;
+       /* How wide the u1 string for each row should be -- Each byte is 8
+          pixels, but must be a multiple of 4 bytes.
        */
-      if (pa) {
-     for (x=0;x<cols;x++) {
-        /*
-         * So we've got a colorhash_table with two colors in it.
-         * Which is black?!
-         * 
-         * Unless the hashing function changes, 0's black.
-         */
-        value = ppm_lookupcolor(cht, &pa[y][x]);
-        if (!value) {
-           /* leave black. */
-        } else {
-           row[byteOn] |= bitOn;
-        }
-        if (bitOn == 1) {
-           byteOn++;
-           bitOn = 128;
+    ICON_bmp * icBitmapP;
+    unsigned int row;
+    u1 ** rowData;
+
+    MALLOCVAR_NOFAIL(icBitmapP);
+
+    MALLOCARRAY_NOFAIL(rowData, rows);
+    icBitmapP->xBytes = xByteCt;
+    icBitmapP->data   = rowData;
+    icBitmapP->size   = xByteCt * rows;
+    for (row = 0; row < rows; ++row) {
+        u1 * thisRow;  /* malloc'ed */
+        unsigned int byteOn;
+        unsigned int bitOn;
+
+        MALLOCARRAY_NOFAIL(thisRow, xByteCt);
+
+        byteOn =   0;  /* initial value */
+        bitOn  = 128;  /* initial value */
+
+        memset (thisRow, 0, xByteCt);
+        rowData[rows - row - 1] = thisRow;
+
+        if (ba) {
+            unsigned int col;
+
+            for (col = 0; col < cols; ++col) {
+                /* Black (bit clear) is transparent in PGM alpha maps,
+                   in ICO bit *set* is transparent.
+                */
+                if (ba[row][col] <= maxval/2) thisRow[byteOn] |= bitOn;
+
+                if (bitOn == 1) {
+                    ++byteOn;
+                    bitOn = 128;
+                } else {
+                    bitOn >>= 1;
+                }
+            }
         } else {
-           bitOn >>= 1;
+            /* No array -- we're just faking this */
         }
-     }
-      }
-   }
-   return icBitmap;
+    }
+    return icBitmapP;
 }
 
 
-static ICON_bmp 
-create4Bitmap (pixel ** const pa, int const cols, int const rows,
-               colorhash_table const cht) {
-   /*
-    * How wide should the u1 string for each row be?
-    * each byte is 8 pixels, but must be a multiple of 4 bytes.
-    */
-   ICON_bmp icBitmap;
-   int xBytes,y,x;
-   int wt = cols;
-   u1 ** rowData;
-
-   MALLOCVAR_NOFAIL(icBitmap);
-
-   wt >>= 1;
-   if (wt & 3) {
-      wt = (wt & ~3) + 4;
-   }
-   xBytes = wt;
-   MALLOCARRAY_NOFAIL(rowData, rows);
-   icBitmap->xBytes = xBytes;
-   icBitmap->data   = rowData;
-   icBitmap->size   = xBytes * rows;
-
-   for (y=0;y<rows;y++) {
-      u1 * row;
-      int byteOn = 0;
-      int nibble = 1;   /* high nibble = 1, low nibble = 0; */
-      int value;
-
-      MALLOCARRAY_NOFAIL(row, xBytes);
-
-      memset (row, 0, xBytes);
-      rowData[rows-y-1] = row;
-      /* 
-       * Check there's a pixel array, otherwise we're just faking this...
-       */
-      if (pa) {
-     for (x=0;x<cols;x++) {
-        value = ppm_lookupcolor(cht, &pa[y][x]);
-        /*
-         * Shift it, if we're putting it in the high nibble.
-         */
-        if (nibble) {
-           value <<= 4;
-        }
-        row[byteOn] |= value;
-        if (nibble) {
-           nibble = 0;
+
+/* Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the
+   encoding mechanism is different.
+
+   I didn't re-use the code from ppmtobmp since I need to keep the
+   bitmaps in memory until I've loaded all ppms.
+
+   8bpp => 1 byte/palette index.
+   4bpp => High Nibble, Low Nibble
+   1bpp => 1 palette value per bit, high bit 1st.
+*/
+
+
+
+static void
+fillInRaster1(u1 **           const rowData,
+              unsigned int    const xByteCt,
+              pixel **        const pa,
+              unsigned int    const cols,
+              unsigned int    const rows,
+              colorhash_table const cht) {
+
+    unsigned int row;
+
+    for (row = 0; row <rows; ++row) {
+        u1 * thisRow;  /* malloc'ed */
+        unsigned int byteSeq;
+        unsigned int bitOnMask;
+
+        MALLOCARRAY_NOFAIL(thisRow, xByteCt);
+        memset(thisRow, 0, xByteCt);  /* initial value */
+        rowData[rows - row - 1] = thisRow;
+        byteSeq   = 0;    /* initial value */
+        bitOnMask = 0x80; /* initial value */
+
+        if (pa) {
+            unsigned int col;
+
+            for (col = 0; col < cols; ++col) {
+                /* So we've got a colorhash_table with two colors in it.  Which
+                   is black?!
+
+                   Unless the hashing function changes, 0's black.
+                */
+                int const value = ppm_lookupcolor(cht, &pa[row][col]);
+
+                assert(byteSeq < xByteCt);
+
+                if (!value) {
+                    /* leave black. */
+                } else {
+                    thisRow[byteSeq] |= bitOnMask;
+                }
+                if (bitOnMask == 0x1) {
+                    ++byteSeq;
+                    bitOnMask = 0x80;
+                } else {
+                    bitOnMask >>= 1;
+                }
+            }
         } else {
-           nibble = 1;
-           byteOn++;
+            /* No pixel array -- we're just faking this */
         }
-     }
-      }
-   }
-   return icBitmap;
+    }
 }
 
 
 
-static ICON_bmp 
-create8Bitmap (pixel ** const pa, int const cols, int const rows,
-               colorhash_table const cht) {
-   /*
-    * How wide should the u1 string for each row be?
-    * each byte is 8 pixels, but must be a multiple of 4 bytes.
-    */
-   ICON_bmp icBitmap;
-   int xBytes,y,x;
-   int wt = cols;
-   u1 ** rowData;
-
-   MALLOCVAR_NOFAIL(icBitmap);
-
-   if (wt & 3) {
-      wt = (wt & ~3) + 4;
-   }
-   xBytes = wt;
-   MALLOCARRAY_NOFAIL(rowData, rows);
-   icBitmap->xBytes = xBytes;
-   icBitmap->data   = rowData;
-   icBitmap->size   = xBytes * rows;
-
-   for (y=0;y<rows;y++) {
-      u1 * row;
-
-      MALLOCARRAY_NOFAIL(row, xBytes);
-      memset (row, 0, xBytes);
-      rowData[rows-y-1] = row;
-      /* 
-       * Check there's a pixel array, otherwise we're just faking this...
-       */
-      if (pa) {
-     for (x=0;x<cols;x++) {
-        row[x] = ppm_lookupcolor(cht, &pa[y][x]);
-     }
-      }
-   }
-   return icBitmap;
+static void
+fillInRaster4(u1 **           const rowData,
+              unsigned int    const xByteCt,
+              pixel **        const pa,
+              unsigned int    const cols,
+              unsigned int    const rows,
+              colorhash_table const cht) {
+
+    unsigned int row;
+
+    for (row = 0; row < rows; ++row) {
+        u1 * thisRow;
+        unsigned int byteSeq;
+        unsigned int nibbleSig;   /* high nibble = 1, low nibble = 0; */
+
+        MALLOCARRAY_NOFAIL(thisRow, xByteCt);
+
+        memset(thisRow, 0, xByteCt);
+        rowData[rows - row - 1] = thisRow;
+        byteSeq   = 0;  /* initial value */
+        nibbleSig = 1;  /* initial value */
+
+        if (pa) {
+            unsigned int col;
+
+            for (col = 0; col < cols; ++col) {
+                int value;
+
+                assert(byteSeq < xByteCt);
+
+                value = ppm_lookupcolor(cht, &pa[row][col]);  /* init value */
+                /* Shift it, if we're putting it in the high nibble. */
+                if (nibbleSig == 1)
+                    value <<= 4;
+                thisRow[byteSeq] |= value;
+                if (nibbleSig == 1)
+                    nibbleSig = 0;
+                else {
+                    nibbleSig = 1;
+                    ++byteSeq;
+                }
+            }
+        } else {
+            /* No pixel array -- we're just faking this */
+        }
+    }
 }
 
 
 
-static IC_InfoHeader 
-createInfoHeader(IC_Entry const entry, ICON_bmp const xbmp,
-                 ICON_bmp const abmp) {
-   IC_InfoHeader ih;
-   
-   MALLOCVAR_NOFAIL(ih);
-
-   ih->size          = 40;
-   ih->width         = entry->width;
-   ih->height        = entry->height * 2;  
-   ih->planes        = 1;  
-   ih->bitcount      = entry->bitcount;
-   ih->compression   = 0;
-   ih->imagesize     = entry->width * entry->height * 8 / entry->bitcount;
-   ih->x_pixels_per_m= 0;
-   ih->y_pixels_per_m= 0;
-   ih->colors_used   = 1 << entry->bitcount;
-   ih->colors_important = 0;
-   return ih;
-}
+static void
+fillInRaster8(u1 **           const rowData,
+              unsigned int    const xByteCt,
+              pixel **        const pa,
+              unsigned int    const cols,
+              unsigned int    const rows,
+              colorhash_table const cht) {
 
+    unsigned int row;
+
+    for (row = 0; row < rows; ++row) {
+        u1 * thisRow;  /* malloc'ed */
 
+        assert(cols <= xByteCt);
 
-static IC_Palette 
-createCleanPalette(void) {
-   IC_Palette palette;
-   int x;
-   
-   MALLOCVAR_NOFAIL(palette);
+        MALLOCARRAY_NOFAIL(thisRow, xByteCt);
+        memset(thisRow, 0, xByteCt);
+        rowData[rows - row - 1] = thisRow;
+        if (pa) {
+            unsigned int col;
 
-   MALLOCARRAY_NOFAIL(palette->colors, MAXCOLORS);
-   for (x=0;x<MAXCOLORS;x++ ){
-      palette->colors[x] = NULL;
-   }
-   return palette;
+            for (col = 0; col < cols; ++col)
+                thisRow[col] = ppm_lookupcolor(cht, &pa[row][col]);
+        } else {
+            /* No pixel array -- we're just faking this */
+        }
+    }
 }
 
 
 
-static void 
-addColorToPalette(IC_Palette const palette, int const i,
-                  int const r, int const g, int const b) {
+static ICON_bmp *
+newBitmap(unsigned int    const bpp,
+          pixel **        const pa,
+          unsigned int    const cols,
+          unsigned int    const rows,
+          colorhash_table const cht) {
 
-    MALLOCVAR_NOFAIL(palette->colors[i]);
+    unsigned int const xByteCt = ROUNDUP(cols * bpp, 32)/8;
+       /* How wide the u1 string for each row should be.  Pixels are packed
+          into bytes, padded to a multiple of 4 bytes.
+       */
+    ICON_bmp * icBitmapP;  /* malloc'ed */
+    u1 ** rowData;  /* malloc'ed */
 
-    palette->colors[i]->red      = r;
-    palette->colors[i]->green    = g;
-    palette->colors[i]->blue     = b;
-    palette->colors[i]->reserved = 0;
-}
+    assert(cols < 256); assert(rows < 256);  /* required for no overflow */
 
+    MALLOCVAR_NOFAIL(icBitmapP);
 
+    MALLOCARRAY_NOFAIL(rowData, rows);
 
-static ICON_bmp 
-createBitmap (int const bpp, pixel ** const pa, 
-              int const cols, int const rows, 
-              colorhash_table const cht) {
-    
-    ICON_bmp retval;
-    const int assumed_bpp = (pa == NULL) ? 1 : bpp;
+    icBitmapP->xBytes = xByteCt;
+    icBitmapP->data   = rowData;
+    icBitmapP->size   = xByteCt * rows;
+
+    unsigned int const assumedBpp = (pa == NULL) ? 1 : bpp;
 
-    switch (assumed_bpp) {
+    switch (assumedBpp) {
     case 1:
-        retval = create1Bitmap (pa,cols,rows,cht);
+        fillInRaster1(rowData, xByteCt, pa, cols, rows, cht);
         break;
     case 4:
-        retval = create4Bitmap (pa,cols,rows,cht);
+        fillInRaster4(rowData, xByteCt, pa, cols, rows, cht);
         break;
     case 8:
     default:
-        retval = create8Bitmap (pa,cols,rows,cht);
+        fillInRaster8(rowData, xByteCt, pa, cols, rows, cht);
         break;
     }
-    return retval;
+    return icBitmapP;
+}
+
+
+
+static IC_InfoHeader *
+newInfoHeader(IC_Entry const entry) {
+
+   IC_InfoHeader * ihP;
+
+   MALLOCVAR_NOFAIL(ihP);
+
+   ihP->size             = 40;
+   ihP->width            = entry.width;
+   ihP->height           = entry.height * 2;
+   ihP->planes           = 1;
+   ihP->bitcount         = entry.bitcount;
+   ihP->compression      = 0;
+   ihP->imagesize        = entry.width * entry.height * 8 / entry.bitcount;
+   ihP->x_pixels_per_m   = 0;
+   ihP->y_pixels_per_m   = 0;
+   ihP->colors_used      = 1 << entry.bitcount;
+   ihP->colors_important = 0;
+
+   return ihP;
+}
+
+
+
+static IC_Palette *
+newCleanPalette(void) {
+
+    IC_Palette * paletteP;  /* malloc'ed */
+
+    unsigned int i;
+
+    MALLOCVAR_NOFAIL(paletteP);
+
+    MALLOCARRAY_NOFAIL(paletteP->colors, MAXCOLORS);
+
+    for (i=0; i <MAXCOLORS; ++i) {
+        paletteP->colors[i] = NULL;
+    }
+    return paletteP;
+}
+
+
+
+static void
+addColorToPalette(IC_Palette * const paletteP,
+                  unsigned int const i,
+                  unsigned int const r,
+                  unsigned int const g,
+                  unsigned int const b) {
+
+    MALLOCVAR_NOFAIL(paletteP->colors[i]);
+
+    paletteP->colors[i]->red      = r;
+    paletteP->colors[i]->green    = g;
+    paletteP->colors[i]->blue     = b;
+    paletteP->colors[i]->reserved = 0;
 }
 
 
 
 static void
 makePalette(pixel **          const xorPPMarray,
-            int               const xorCols,
-            int               const xorRows,
+            unsigned int      const xorCols,
+            unsigned int      const xorRows,
             pixval            const xorMaxval,
-            IC_Palette *      const paletteP,
+            IC_Palette **     const palettePP,
             colorhash_table * const xorChtP,
-            int *             const colorsP,
+            unsigned int *    const colorsP,
             const char **     const errorP) {
-   /*
-    * Figure out the colormap and turn it into the appropriate GIF
-    * colormap - this code's pretty much straight from ppmtobpm
-    */
+/*----------------------------------------------------------------------------
+   Figure out the colormap and turn it into the appropriate GIF colormap -
+   this code's pretty much straight from 'ppmtobpm'.
+-----------------------------------------------------------------------------*/
+    IC_Palette * const paletteP = newCleanPalette();
+
     colorhist_vector xorChv;
     unsigned int i;
-    int colors;
-    IC_Palette palette = createCleanPalette();
+    int colorCt;
+
+    if (verbose)
+        pm_message("computing colormap...");
 
-    if (verbose) pm_message("computing colormap...");
-    xorChv = ppm_computecolorhist(xorPPMarray, xorCols, xorRows, MAXCOLORS, 
-                                  &colors);
-    if (xorChv == NULL)
+    xorChv = ppm_computecolorhist(xorPPMarray, xorCols, xorRows, MAXCOLORS,
+                                  &colorCt);
+    if (!xorChv)
         pm_asprintf(errorP,
-                    "image has too many colors - try doing a 'pnmquant %d'",
+                    "image has too many colors - try doing a 'pnmquant %u'",
                     MAXCOLORS);
     else {
         *errorP = NULL;
 
-        if (verbose) pm_message("%d colors found", colors);
-        
+        if (verbose)
+            pm_message("%u colors found", colorCt);
+
         if (verbose && (xorMaxval > 255))
             pm_message("maxval is not 255 - automatically rescaling colors");
-        for (i = 0; i < colors; ++i) {
+        for (i = 0; i < colorCt; ++i) {
             if (xorMaxval == 255) {
-                addColorToPalette(palette,i,
+                addColorToPalette(paletteP, i,
                                   PPM_GETR(xorChv[i].color),
                                   PPM_GETG(xorChv[i].color),
                                   PPM_GETB(xorChv[i].color));
             } else {
-                addColorToPalette(palette,i,
+                addColorToPalette(paletteP, i,
                                   PPM_GETR(xorChv[i].color) * 255 / xorMaxval,
                                   PPM_GETG(xorChv[i].color) * 255 / xorMaxval,
                                   PPM_GETB(xorChv[i].color) * 255 / xorMaxval);
             }
         }
-        
+
         /* And make a hash table for fast lookup. */
-        *xorChtP = ppm_colorhisttocolorhash(xorChv, colors);
-        
+        *xorChtP = ppm_colorhisttocolorhash(xorChv, colorCt);
+
         ppm_freecolorhist(xorChv);
-        
-        *paletteP = palette;
-        *colorsP = colors;
+
+        *palettePP = paletteP;
+        *colorsP   = colorCt;
     }
 }
 
@@ -562,15 +561,15 @@ makePalette(pixel **          const xorPPMarray,
 
 static void
 getOrFakeAndMap(const char *      const andPgmFname,
-                int               const xorCols,
-                int               const xorRows,
+                unsigned int      const xorCols,
+                unsigned int      const xorRows,
                 gray ***          const andPGMarrayP,
                 pixval *          const andMaxvalP,
                 colorhash_table * const andChtP,
                 const char **     const errorP) {
 
     int andRows, andCols;
-    
+
     if (!andPgmFname) {
         /* He's not supplying a bitmap for 'and'.  Fake the bitmap. */
         *andPGMarrayP = NULL;
@@ -578,15 +577,15 @@ getOrFakeAndMap(const char *      const andPgmFname,
         *andChtP      = NULL;
         *errorP       = NULL;
     } else {
-        FILE * andfile;
-        andfile = pm_openr(andPgmFname);
-        *andPGMarrayP = pgm_readpgm(andfile, &andCols, &andRows, andMaxvalP);
-        pm_close(andfile);
+        FILE * andFileP;
+        andFileP = pm_openr(andPgmFname);
+        *andPGMarrayP = pgm_readpgm(andFileP, &andCols, &andRows, andMaxvalP);
+        pm_close(andFileP);
 
         if ((andCols != xorCols) || (andRows != xorRows)) {
             pm_asprintf(errorP,
                         "And mask and image have different dimensions "
-                        "(%d x %d vs %d x %d).  Aborting.",
+                        "(%u x %u vs %u x %u).  Aborting.",
                         andCols, xorCols, andRows, xorRows);
         } else
             *errorP = NULL;
@@ -596,18 +595,20 @@ getOrFakeAndMap(const char *      const andPgmFname,
 
 
 static void
-blackenTransparentAreas(pixel ** const xorPPMarray,
-                        int      const cols,
-                        int      const rows,
-                        gray **  const andPGMarray,
-                        pixval   const andMaxval) {
+blackenTransparentAreas(pixel **     const xorPPMarray,
+                        unsigned int const cols,
+                        unsigned int const rows,
+                        gray **      const andPGMarray,
+                        pixval       const andMaxval) {
 
     unsigned int row;
 
-    if (verbose) pm_message("Setting transparent pixels to black");
+    if (verbose)
+        pm_message("Setting transparent pixels to black");
 
     for (row = 0; row < rows; ++row) {
         unsigned int col;
+
         for (col = 0; col < cols; ++col) {
             if (andPGMarray[row][col] < andMaxval)
                 /* It's not opaque here; make it black */
@@ -618,70 +619,69 @@ blackenTransparentAreas(pixel ** const xorPPMarray,
 
 
 
-static void 
-addEntryToIcon(MS_Ico       const MSIconData, 
+static void
+addEntryToIcon(MS_Ico *     const MSIconDataP,
                const char * const xorPpmFname,
                const char * const andPgmFname,
                bool         const trueTransparent) {
 
-    IC_Entry entry;
+    IC_Entry * entryP;
     FILE * xorfile;
     pixel ** xorPPMarray;
     gray ** andPGMarray;
-    ICON_bmp xorBitmap;
-    ICON_bmp andBitmap;
+    ICON_bmp * xorBitmapP;
+    ICON_bmp * andBitmapP;
     int rows, cols;
-    int bpp, colors;
-    int entry_cols;
-    IC_Palette palette;
-    colorhash_table  xorCht;
-    colorhash_table  andCht; 
+    unsigned int bpp;
+    unsigned int colorCt;
+    unsigned int entryCols;
+    IC_Palette * paletteP;
+    colorhash_table xorCht;
+    colorhash_table andCht;
     const char * error;
-   
+
     pixval xorMaxval;
     gray andMaxval;
 
-    MALLOCVAR_NOFAIL(entry);
+    MALLOCVAR_NOFAIL(entryP);
 
-   /*
-    * Read the xor PPM.
-    */
+    /* Read the xor PPM. */
     xorfile = pm_openr(xorPpmFname);
     xorPPMarray = ppm_readppm(xorfile, &cols, &rows, &xorMaxval);
     pm_close(xorfile);
-    /*
-    * Since the entry uses 1 byte to hold the width and height of the icon, the
-    * image can't be more than 256 x 256.
+
+    /* Since the entry uses 1 byte to hold the width and height of the icon,
+       the image can't be more than 256 x 256.
     */
     if (rows > 255 || cols > 255) {
         pm_error("Max size for a icon is 255 x 255 (1 byte fields).  "
-                 "%s is %d x %d", xorPpmFname, cols, rows);
+                 "%s is %u x %u", xorPpmFname, cols, rows);
     }
-   
-    if (verbose) pm_message("read PPM: %dw x %dh, maxval = %d", 
-                            cols, rows, xorMaxval);
 
-    makePalette(xorPPMarray, cols, rows, xorMaxval, 
-                &palette, &xorCht, &colors, &error);
+    if (verbose)
+        pm_message("read PPM: %uw x %uh, maxval = %u", cols, rows, xorMaxval);
+
+    makePalette(xorPPMarray, cols, rows, xorMaxval,
+                &paletteP, &xorCht, &colorCt, &error);
 
     if (error)
         pm_error("Unable to make palette for '%s'.  %s", xorPpmFname, error);
-   /*
-    * All the icons I found seemed to pad the palette to the max entries
-    * for that bitdepth.
-    * 
-    * The spec indicates this isn't necessary, but I'll follow this behaviour
-    * just in case.
+
+    /* All the icons I found seemed to pad the palette to the max entries for
+       that bitdepth.
+
+       The spec indicates this isn't necessary, but I'll follow this behaviour
+       just in case.
     */
-    if (colors < 3) {
+    if (colorCt < 3) {
         bpp = 1;
-        entry_cols = 2;
-    } else if (colors < 17) {
+        entryCols = 2;
+    } else if (colorCt < 17) {
         bpp = 4;
-        entry_cols = 16;
+        entryCols = 16;
     } else {
         bpp = 8;
-        entry_cols = 256;
+        entryCols = 256;
     }
 
     getOrFakeAndMap(andPgmFname, cols, rows,
@@ -690,164 +690,182 @@ addEntryToIcon(MS_Ico       const MSIconData,
         pm_error("Error in and map for '%s'.  %s", xorPpmFname, error);
 
     if (andPGMarray && trueTransparent)
-        blackenTransparentAreas(xorPPMarray, cols, rows, 
+        blackenTransparentAreas(xorPPMarray, cols, rows,
                                 andPGMarray, andMaxval);
 
-    xorBitmap = createBitmap(bpp, xorPPMarray, cols, rows, xorCht);
-    andBitmap = createAndBitmap(andPGMarray, cols, rows, andMaxval);
-    /*
-     * Fill in the entry data fields.
-    */
-    entry->width         = cols;
-    entry->height        = rows;
-    entry->color_count   = entry_cols;
-    entry->reserved      = 0;
-    entry->planes        = 1;
-    /* 
-    * all the icons I looked at ignored this value...
-    */
-    entry->bitcount      = bpp;
-    entry->ih            = createInfoHeader(entry, xorBitmap, andBitmap);
-    entry->colors        = palette->colors;
-    entry->size_in_bytes = 
-        xorBitmap->size + andBitmap->size + 40 + (4 * entry->color_count);
-    if (verbose) 
-        pm_message("entry->size_in_bytes = %d + %d + %d = %d",
-                   xorBitmap->size ,andBitmap->size, 
-                   40, entry->size_in_bytes );
-    /*
-    * We don't know the offset ATM, set to 0 for now.
-    * Have to calculate this at the end.
-    */
-    entry->file_offset   = 0;
-    entry->xorBitmapOut  = xorBitmap->data;
-    entry->andBitmapOut  = andBitmap->data;
-    entry->xBytesXor     = xorBitmap->xBytes;
-    entry->xBytesAnd     = andBitmap->xBytes;  
-    /*
-    * Add the entry to the entries array.
+    xorBitmapP = newBitmap(bpp, xorPPMarray, cols, rows, xorCht);
+    andBitmapP = newAndBitmap(andPGMarray, cols, rows, andMaxval);
+
+    /* Fill in the entry data fields. */
+    entryP->width         = cols;
+    entryP->height        = rows;
+    entryP->color_count   = entryCols;
+    entryP->reserved      = 0;
+    entryP->planes        = 1;
+    entryP->bitcount      = bpp;
+    /* all the icons I looked at ignored this value */
+    entryP->ih            = newInfoHeader(*entryP);
+    entryP->colors        = paletteP->colors;
+    entryP->size_in_bytes =
+        xorBitmapP->size + andBitmapP->size + 40 + (4 * entryCols);
+    if (verbose)
+        pm_message("entry->size_in_bytes = %u + %u + %u = %u",
+                   xorBitmapP->size, andBitmapP->size,
+                   40, entryP->size_in_bytes );
+
+    /* We don't know the offset ATM, set to 0 for now.  Have to calculate this
+       at the end.
     */
-    ++MSIconData->count;
+    entryP->file_offset  = 0;
+    entryP->xorBitmapOut = xorBitmapP->data;
+    entryP->andBitmapOut = andBitmapP->data;
+    entryP->xBytesXor    = xorBitmapP->xBytes;
+    entryP->xBytesAnd    = andBitmapP->xBytes;
+
+    /* Add the entry to the entries array. */
+    ++MSIconDataP->count;
+
     /* Perhaps I should allocate ahead, and take fewer trips to the well. */
-    REALLOCARRAY(MSIconData->entries, MSIconData->count);
-    MSIconData->entries[MSIconData->count-1] = entry;
+    REALLOCARRAY(MSIconDataP->entries, MSIconDataP->count);
+    MSIconDataP->entries[MSIconDataP->count - 1] = entryP;
 }
 
 
 
-static void 
-writeIC_Entry (IC_Entry const entry) {
-   writeU1(entry->width);
-   writeU1(entry->height);
-   writeU1(entry->color_count); /* chops 256->0 on its own.. */
-   writeU1(entry->reserved);
-   writeU2(entry->planes);
-   writeU2(entry->bitcount);
-   writeU4(entry->size_in_bytes);
-   writeU4(entry->file_offset);
+static void
+writeIC_Entry(FILE *     const ofP,
+              IC_Entry * const entryP) {
+
+   writeU1(ofP, entryP->width);
+   writeU1(ofP, entryP->height);
+   writeU1(ofP, entryP->color_count); /* chops 256->0 on its own.. */
+   writeU1(ofP, entryP->reserved);
+   writeU2(ofP, entryP->planes);
+   writeU2(ofP, entryP->bitcount);
+   writeU4(ofP, entryP->size_in_bytes);
+   writeU4(ofP, entryP->file_offset);
 }
 
 
 
-static void 
-writeIC_InfoHeader (IC_InfoHeader const ih) {
-   writeU4(ih->size);
-   writeU4(ih->width);
-   writeU4(ih->height);
-   writeU2(ih->planes);
-   writeU2(ih->bitcount);
-   writeU4(ih->compression);
-   writeU4(ih->imagesize);
-   writeU4(ih->x_pixels_per_m);
-   writeU4(ih->y_pixels_per_m);
-   writeU4(ih->colors_used);
-   writeU4(ih->colors_important);
+static void
+writeIC_InfoHeader(FILE *          const ofP,
+                   IC_InfoHeader * const ihP) {
+
+   writeU4(ofP, ihP->size);
+   writeU4(ofP, ihP->width);
+   writeU4(ofP, ihP->height);
+   writeU2(ofP, ihP->planes);
+   writeU2(ofP, ihP->bitcount);
+   writeU4(ofP, ihP->compression);
+   writeU4(ofP, ihP->imagesize);
+   writeU4(ofP, ihP->x_pixels_per_m);
+   writeU4(ofP, ihP->y_pixels_per_m);
+   writeU4(ofP, ihP->colors_used);
+   writeU4(ofP, ihP->colors_important);
 }
 
 
 
-static void 
-writeIC_Color (IC_Color const col) {
-   /* Since the ppm might not have as many colors in it as we'd like,
-    * (2, 16, 256), stick 0 in the gaps.
-    * 
-    * This means that we lose palette information, but that can't be
-    * helped.  
+static void
+writeIC_Color(FILE *     const ofP,
+              IC_Color * const colorP) {
+
+    /* Since the ppm might not have as many colors in it as we'd like,
+       (2, 16, 256), stick 0 in the gaps.
+
+       This means that we lose palette information, but that can't be helped.
     */
-   if (col == NULL) {
-      writeU1(0);
-      writeU1(0);
-      writeU1(0);
-      writeU1(0);
-   } else {
-      writeU1(col->blue);
-      writeU1(col->green);
-      writeU1(col->red);
-      writeU1(col->reserved);
-   }
+    if (!colorP) {
+        writeU1(ofP, 0);
+        writeU1(ofP, 0);
+        writeU1(ofP, 0);
+        writeU1(ofP, 0);
+    } else {
+        writeU1(ofP, colorP->blue);
+        writeU1(ofP, colorP->green);
+        writeU1(ofP, colorP->red);
+        writeU1(ofP, colorP->reserved);
+    }
 }
 
 
 
 static void
-writeBitmap(u1 ** const bitmap, int const xBytes, int const height) {
-   int y;
-   for (y = 0;y<height;y++) {
-      fwrite (bitmap[y],1,xBytes,ofp);
-      file_offset += xBytes;
-   }
+writeBitmap(FILE *       const ofP,
+            u1 **        const bitmap,
+            unsigned int const xByteCt,
+            unsigned int const height) {
+
+    unsigned int row;
+
+    for (row = 0; row < height; ++row) {
+        fwrite(bitmap[row], 1, xByteCt, ofP);
+        fileOffset += xByteCt;
+    }
 }
 
 
 
-static void 
-writeMS_Ico(MS_Ico       const MSIconData, 
+static void
+writeMS_Ico(MS_Ico *     const MSIconDataP,
             const char * const outFname) {
-    int x,y;
-   
-    ofp = pm_openw(outFname);
-
-    writeU2(MSIconData->reserved);
-    writeU2(MSIconData->type);
-    writeU2(MSIconData->count);
-    for (x=0;x<MSIconData->count;x++) writeIC_Entry(MSIconData->entries[x]);
-    for (x=0;x<MSIconData->count;x++) {
-        writeIC_InfoHeader(MSIconData->entries[x]->ih);
-        for (y=0;y<(MSIconData->entries[x]->color_count);y++) {
-            writeIC_Color(MSIconData->entries[x]->colors[y]);
+
+    FILE * const ofP = pm_openw(outFname);
+
+    unsigned int i;
+
+    writeU2(ofP, MSIconDataP->reserved);
+    writeU2(ofP, MSIconDataP->type);
+    writeU2(ofP, MSIconDataP->count);
+
+    for (i = 0; i < MSIconDataP->count; ++i)
+        writeIC_Entry(ofP, MSIconDataP->entries[i]);
+
+    for (i = 0; i < MSIconDataP->count; ++i) {
+        IC_Entry * const entryP = MSIconDataP->entries[i];
+
+        unsigned int j;
+
+        writeIC_InfoHeader(ofP, MSIconDataP->entries[i]->ih);
+
+        for (j = 0; j < (MSIconDataP->entries[i]->color_count); ++j) {
+            writeIC_Color(ofP, MSIconDataP->entries[i]->colors[j]);
         }
-        if (verbose) pm_message("writing xor bitmap");
-        writeBitmap(MSIconData->entries[x]->xorBitmapOut,
-                    MSIconData->entries[x]->xBytesXor,
-                    MSIconData->entries[x]->height);
-        if (verbose) pm_message("writing and bitmap");
-        writeBitmap(MSIconData->entries[x]->andBitmapOut,
-                    MSIconData->entries[x]->xBytesAnd,
-                    MSIconData->entries[x]->height);
+        if (verbose)
+            pm_message("writing xor bitmap");
+
+        writeBitmap(ofP,
+                    entryP->xorBitmapOut, entryP->xBytesXor, entryP->height);
+        if (verbose)
+            pm_message("writing and bitmap");
+
+        writeBitmap(ofP,
+                    entryP->andBitmapOut, entryP->xBytesAnd, entryP->height);
     }
-    fclose(ofp);
+    fclose(ofP);
 }
 
 
 
-int 
-main(int argc, char ** argv) {
+int
+main(int argc, const char ** argv) {
 
-    struct cmdlineInfo cmdline;
+    MS_Ico * const MSIconDataP = newIconFile();
 
-    MS_Ico const MSIconDataP = createIconFile();
+    struct CmdlineInfo cmdline;
     unsigned int iconIndex;
     unsigned int offset;
-   
-    ppm_init (&argc, argv);
+
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
     verbose = cmdline.verbose;
 
     for (iconIndex = 0; iconIndex < cmdline.iconCount; ++iconIndex) {
-        addEntryToIcon(MSIconDataP, cmdline.inputFilespec[iconIndex],
-                       cmdline.andpgmFilespec[iconIndex], 
+        addEntryToIcon(MSIconDataP, cmdline.inputFileNm[iconIndex],
+                       cmdline.andpgmFileNm[iconIndex],
                        cmdline.truetransparent);
     }
     /*
@@ -856,22 +874,24 @@ main(int argc, char ** argv) {
      */
     offset = (MSIconDataP->count * 16) + 6;
     for (iconIndex = 0; iconIndex < MSIconDataP->count; ++iconIndex) {
-        IC_Entry entry = MSIconDataP->entries[iconIndex];
-        entry->file_offset = offset;
-        /* 
+        IC_Entry * const entryP = MSIconDataP->entries[iconIndex];
+
+        entryP->file_offset = offset;
+        /*
          * Increase the offset by the size of this offset & data.
          * this includes the size of the color data.
          */
-        offset += entry->size_in_bytes;
+        offset += entryP->size_in_bytes;
     }
     /*
      * And now, we have to actually SAVE the .ico!
      */
     writeMS_Ico(MSIconDataP, cmdline.output);
 
-    free(cmdline.inputFilespec);
-    free(cmdline.andpgmFilespec);
+    freeCmdline(cmdline);
 
     return 0;
 }
 
+
+