about summary refs log tree commit diff
path: root/converter/pbm
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm')
-rw-r--r--converter/pbm/Makefile8
-rw-r--r--converter/pbm/atktopbm.c2
-rw-r--r--converter/pbm/cmuwmtopbm.c181
-rw-r--r--converter/pbm/g3topbm.c147
-rw-r--r--converter/pbm/icontopbm.c12
-rw-r--r--converter/pbm/mgrtopbm.c171
-rw-r--r--converter/pbm/mrftopbm.c66
-rw-r--r--converter/pbm/pbmto4425.c2
-rw-r--r--converter/pbm/pbmtocmuwm.c167
-rw-r--r--converter/pbm/pbmtodjvurle.c166
-rw-r--r--converter/pbm/pbmtoepsi.c1
-rw-r--r--converter/pbm/pbmtoepson.c3
-rw-r--r--converter/pbm/pbmtoescp2.c1
-rw-r--r--converter/pbm/pbmtog3.c34
-rw-r--r--converter/pbm/pbmtogem.c6
-rw-r--r--converter/pbm/pbmtogo.c226
-rw-r--r--converter/pbm/pbmtoibm23xx.c1
-rw-r--r--converter/pbm/pbmtoicon.c252
-rw-r--r--converter/pbm/pbmtolj.c1
-rw-r--r--converter/pbm/pbmtoln03.c5
-rw-r--r--converter/pbm/pbmtolps.c2
-rw-r--r--converter/pbm/pbmtomgr.c209
-rw-r--r--converter/pbm/pbmtomrf.c162
-rw-r--r--converter/pbm/pbmtonokia.c686
-rw-r--r--converter/pbm/pbmtopi3.c6
-rw-r--r--converter/pbm/pbmtopk.c2
-rw-r--r--converter/pbm/pbmtoppa/Makefile4
-rw-r--r--converter/pbm/pbmtopsg3.c1
-rw-r--r--converter/pbm/pbmtoptx.c6
-rw-r--r--converter/pbm/pbmtox10bm45
-rw-r--r--converter/pbm/pbmtox10bm.c120
-rw-r--r--converter/pbm/pbmtoxbm.c410
-rw-r--r--converter/pbm/pbmtoybm.c6
-rw-r--r--converter/pbm/pbmtozinc.c2
-rw-r--r--converter/pbm/pktopbm.c2
-rw-r--r--converter/pbm/thinkjettopbm.l1
-rw-r--r--converter/pbm/xbmtopbm.c568
37 files changed, 2217 insertions, 1467 deletions
diff --git a/converter/pbm/Makefile b/converter/pbm/Makefile
index 318b8e9e..c859b105 100644
--- a/converter/pbm/Makefile
+++ b/converter/pbm/Makefile
@@ -5,7 +5,7 @@ endif
 SUBDIR = converter/pbm
 VPATH=.:$(SRCDIR)/$(SUBDIR)
 
-include $(BUILDDIR)/Makefile.config
+include $(BUILDDIR)/config.mk
 
 PORTBINARIES =	atktopbm brushtopbm cmuwmtopbm ddbugtopbm g3topbm escp2topbm \
 		icontopbm macptopbm mdatopbm mgrtopbm mrftopbm \
@@ -17,7 +17,7 @@ PORTBINARIES =	atktopbm brushtopbm cmuwmtopbm ddbugtopbm g3topbm escp2topbm \
 		pbmtomacp pbmtomatrixorbital pbmtomda pbmtomgr pbmtomrf \
 		pbmtonokia \
 		pbmtopi3 pbmtoplot pbmtopsg3 pbmtoptx pbmtowbmp \
-		pbmtox10bm pbmtoxbm pbmtoybm pbmtozinc \
+		pbmtoxbm pbmtoybm pbmtozinc \
 		pi3topbm pktopbm \
 		wbmptopbm xbmtopbm ybmtopbm	
 
@@ -29,7 +29,7 @@ endif
 #in libm?
 MATHBINARIES =	pbmtopk
 BINARIES =	$(PORTBINARIES) $(MATHBINARIES)
-SCRIPTS =
+SCRIPTS =       pbmtox10bm
 
 OBJECTS = $(BINARIES:%=%.o)
 
@@ -41,7 +41,7 @@ SUBDIRS=pbmtoppa
 .PHONY: all
 all: $(BINARIES) $(SUBDIRS:%=%/all)
 
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
 
 ifneq ($(LEX)x,x)
 thinkjettopbm.c1:%.c1:%.l
diff --git a/converter/pbm/atktopbm.c b/converter/pbm/atktopbm.c
index c4a81808..62664999 100644
--- a/converter/pbm/atktopbm.c
+++ b/converter/pbm/atktopbm.c
@@ -273,7 +273,7 @@ ReadATKRaster(FILE * const file,
 
     /* read the keyword */
     fscanf(file, " %5s", keyword);
-    if (!STREQ(keyword, "bits"))
+    if (!streq(keyword, "bits"))
       pm_error ("keyword is not 'bits'!");
 
     fscanf(file, " %d %d %d ", &objectid, &width, &height);
diff --git a/converter/pbm/cmuwmtopbm.c b/converter/pbm/cmuwmtopbm.c
index 53c64aaa..eabff40c 100644
--- a/converter/pbm/cmuwmtopbm.c
+++ b/converter/pbm/cmuwmtopbm.c
@@ -1,4 +1,4 @@
-/* cmuwmtopbm.c - read a CMU window manager bitmap and produce a portable bitmap
+/* cmuwmtopbm.c - read a CMU window manager bitmap and produce a PBM image.
 **
 ** Copyright (C) 1989 by Jef Poskanzer.
 **
@@ -10,105 +10,106 @@
 ** implied warranty.
 */
 
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from getc() to fread(),
+   write function from pbm_writepbmrow() to pbm_writepbmrow_packed().
+   Retired bitwise transformation functions.
+
+   This program does not check the pad bits at the end of each row.
+*/
+
+
 #include "pbm.h"
 #include "cmuwm.h"
 
-static void getinit ARGS(( FILE* file, int* colsP, int* rowsP, short* depthP, int* padrightP ));
-static bit getbit ARGS(( FILE* file ));
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, padright, row, col;
-    short depth;
 
+static void
+readCmuwmHeader(FILE *         const ifP,
+                unsigned int * const colsP,
+                unsigned int * const rowsP,
+                unsigned int * const depthP) {
 
-    pbm_init( &argc, argv );
+    const char * const initReadError =
+        "CMU window manager header EOF / read error";
 
-    if ( argc > 2 )
-	pm_usage( "[cmuwmfile]" );
+    long l;
+    short s;
+    int rc;
+
+    rc = pm_readbiglong(ifP, &l);
+    if (rc == -1 )
+        pm_error(initReadError);
+    if ((uint32_t)l != CMUWM_MAGIC)
+        pm_error("bad magic number in CMU window manager file");
+    rc = pm_readbiglong(ifP, &l);
+    if (rc == -1)
+        pm_error(initReadError);
+    *colsP = l;
+    rc = pm_readbiglong(ifP, &l);
+    if (rc == -1 )
+        pm_error(initReadError);
+    *rowsP = l;
+    rc = pm_readbigshort(ifP, &s);
+    if (rc == -1)
+        pm_error(initReadError);
+    *depthP = s;
+}
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
-
-    getinit( ifp, &cols, &rows, &depth, &padright );
-    if ( depth != 1 )
-	pm_error(
-	    "CMU window manager file has depth of %d, must be 1",
-	    (int) depth );
-
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
-
-    for ( row = 0; row < rows; ++row )
-	{
-	/* Get data. */
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-	    *bP = getbit( ifp );
-	/* Discard line padding */
-        for ( col = 0; col < padright; ++col )
-	    (void) getbit( ifp );
-	pbm_writepbmrow( stdout, bitrow, cols, 0 );
-	}
-
-    pm_close( ifp );
-    pm_close( stdout );
-
-    exit( 0 );
-    }
 
-static int item, bitsperitem, bitshift;
 
-static void
-getinit( file, colsP, rowsP, depthP, padrightP )
-    FILE* file;
-    int* colsP;
-    int* rowsP;
-    short* depthP;
-    int* padrightP;
-    {
-    long l;
+int
+main(int     argc,
+     char * argv[]) {
 
-    if ( pm_readbiglong( file, &l ) == -1 )
-	pm_error( "EOF / read error" );
-    if ( (uint32_t)l != CMUWM_MAGIC )
-	pm_error( "bad magic number in CMU window manager file" );
-    if ( pm_readbiglong( file, &l ) == -1 )
-	pm_error( "EOF / read error" );
-    *colsP = (int) l;
-    if ( pm_readbiglong( file, &l ) == -1 )
-	pm_error( "EOF / read error" );
-    *rowsP = (int) l;
-    if ( pm_readbigshort( file, depthP ) == -1 )
-	pm_error( "EOF / read error" );
-    *padrightP = ( ( *colsP + 7 ) / 8 ) * 8 - *colsP;
-
-    bitsperitem = 0;
-    }
+    FILE * ifP;
+    unsigned char * bitrow;
+    unsigned int rows, cols, depth;
+    unsigned int row;
+
+    const char * inputFileName;
 
-static bit
-getbit( file )
-    FILE* file;
-    {
-    bit b;
-
-    if ( bitsperitem == 0 )
-	{
-	item = getc( file );
-	if ( item == EOF )
-	    pm_error( "EOF / read error" );
-	bitsperitem = 8;
-	bitshift = 7;
-	}
-    b = ( ( item >> bitshift) & 1 ) ? PBM_WHITE : PBM_BLACK;
-    --bitsperitem;
-    --bitshift;
-    return b;
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
+    else
+        inputFileName = "-";
+    
+    ifP = pm_openr(inputFileName);
+
+    readCmuwmHeader(ifP, &cols, &rows, &depth);
+    if (depth != 1)
+        pm_error("CMU window manager file has depth of %u, must be 1", depth);
+
+    pbm_writepbminit(stdout, cols, rows, 0);
+    bitrow = pbm_allocrow_packed(cols);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int const bytesPerRow = pbm_packed_bytes(cols);
+        unsigned int byteSeq;
+        size_t bytesRead;
+
+        bytesRead = fread(bitrow, 1, bytesPerRow, ifP);
+        if (bytesRead != bytesPerRow)
+            pm_error("CWU window manager bitmap EOF / read error");
+            
+        /* Invert all bits in row - raster formats are similar.
+           CMUWM Black:0 White:1  End of row padded with 1
+           PBM   Black:1 White:0  End preferably padded with 0
+        */
+   
+        for (byteSeq = 0; byteSeq < bytesPerRow; ++byteSeq)
+            bitrow[byteSeq] = ~bitrow[byteSeq];
+                
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
     }
+
+    pm_close(ifP);
+    pm_close(stdout);
+
+    return 0;
+}
diff --git a/converter/pbm/g3topbm.c b/converter/pbm/g3topbm.c
index 1eefee96..7bb95c92 100644
--- a/converter/pbm/g3topbm.c
+++ b/converter/pbm/g3topbm.c
@@ -18,12 +18,19 @@
   contributing their work to the public domain.
 ===========================================================================*/
 
+#define _BSD_SOURCE   /* Make nstring.h define strcaseeq() */
+
+#include "pm_c_util.h"
 #include "pbm.h"
 #include "shhopt.h"
 #include "nstring.h"
 #include "mallocvar.h"
 #include "g3.h"
 #include "bitreverse.h"
+#include "bitarith.h"
+
+#define LEFTBITS pm_byteLeftBits
+#define RIGHTBITS pm_byteRightBits
 
 #define MAXCOLS 10800
 #define MAXROWS 14400   /* this allows up to two pages of image */
@@ -100,15 +107,15 @@ parseCommandLine(int argc, char ** const argv,
         if (cmdlineP->expectedLineSize < 1)
             pm_error("-width must be at least 1");
     } else if (paper_sizeSpec) {
-        if (STRCASEEQ(paperSize, "A6"))
+        if (strcaseeq(paperSize, "A6"))
             cmdlineP->expectedLineSize = 864;
-        else if (STRCASEEQ(paperSize, "A5"))
+        else if (strcaseeq(paperSize, "A5"))
             cmdlineP->expectedLineSize = 1216;
-        else if (STRCASEEQ(paperSize, "A4"))
+        else if (strcaseeq(paperSize, "A4"))
             cmdlineP->expectedLineSize = 1728;
-        else if (STRCASEEQ(paperSize, "B4"))
+        else if (strcaseeq(paperSize, "B4"))
             cmdlineP->expectedLineSize = 2048;
-        else if (STRCASEEQ(paperSize, "A3"))
+        else if (strcaseeq(paperSize, "A3"))
             cmdlineP->expectedLineSize = 2432;
         else
             pm_error("Unrecognized value for -paper_size '%s'.  "
@@ -295,12 +302,12 @@ buildHashes(g3TableEntry * (*whashP)[HASHSIZE],
 
 
 static void
-makeRowWhite(bit *        const bitrow,
-             unsigned int const cols) {
+makeRowWhite(unsigned char * const packedBitrow,
+             unsigned int    const cols) {
 
-    unsigned int col;
-    for (col = 0; col < MAXCOLS; ++col)
-        bitrow[col] = PBM_WHITE;
+    unsigned int colByte;
+    for (colByte = 0; colByte < pbm_packed_bytes(cols); ++colByte)
+        packedBitrow[colByte] = PBM_WHITE * 0xff;
 }
 
 
@@ -333,16 +340,45 @@ g3code(unsigned int const curcode,
 
 
 
-enum g3tableId {TERMWHITE, TERMBLACK, MKUPWHITE, MKUPBLACK};
+static void
+writeBlackBitSpan(unsigned char * const packedBitrow,
+                  int             const cols,
+                  int             const offset) {
+/*----------------------------------------------------------------------------
+   Write black (="1") bits into packedBitrow[], starting at 'offset',
+   length 'cols'.
+-----------------------------------------------------------------------------*/
+    unsigned char * const dest = & packedBitrow[offset/8];
+    unsigned int const rs  = offset % 8;
+    unsigned int const trs = (cols + rs) % 8;
+    unsigned int const colBytes = pbm_packed_bytes(cols + rs);
+    unsigned int const last = colBytes - 1;
+
+    unsigned char const origHead = dest[0];
+    unsigned char const origEnd =  0x00;
+
+    unsigned int i;
 
+    for( i = 0; i < colBytes; ++i)
+        dest[i] = PBM_BLACK * 0xff;
 
+    if (rs > 0)
+        dest[0] = LEFTBITS(origHead, rs) | RIGHTBITS(dest[0], 8-rs);
+
+    if (trs > 0)
+        dest[last] = LEFTBITS(dest[last], trs) | RIGHTBITS(origEnd, 8-trs);
+}
+
+
+
+enum g3tableId {TERMWHITE, TERMBLACK, MKUPWHITE, MKUPBLACK};
 
 static void
-processG3Code(g3TableEntry * const teP,
-              bit *          const bitrow,
-              unsigned int * const colP,
-              bit *          const colorP,
-              unsigned int * const countP) {
+processG3Code(const g3TableEntry * const teP,
+              unsigned char *      const packedBitrow,
+              unsigned int *       const colP,
+              bit *                const colorP,
+              unsigned int *       const countP) {
               
     enum g3tableId const teId =
         (teP > mtable ? 2 : 0) + (teP - ttable) % 2;
@@ -366,14 +402,10 @@ processG3Code(g3TableEntry * const teP,
         runLengthSoFar = MIN(*countP + teCount, MAXCOLS - col);
 
         if (runLengthSoFar > 0) {
-            if (*colorP == PBM_WHITE) {
-                /* Row was initialized to white, so we just skip */
-                col += runLengthSoFar;
-            } else {
-                unsigned int i;
-                for (i = 0; i < runLengthSoFar; ++i)
-                    bitrow[col++] = PBM_BLACK;
-            }
+            if (*colorP == PBM_BLACK)
+                writeBlackBitSpan(packedBitrow, runLengthSoFar, col);
+            /* else : Row was initialized to white, so we just skip */
+            col += runLengthSoFar;
         }
         *colorP = !*colorP;
         *countP = 0;
@@ -399,7 +431,7 @@ formatBadCodeException(const char ** const exceptionP,
     asprintfN(exceptionP,
         "bad code word at Column %u.  "
         "No prefix of the %u bits 0x%x matches any recognized "
-        "code word and no code words longer than 12 bits are "
+        "code word and no code words longer than 13 bits are "
         "defined.  ",
         col, curlen, curcode);
 }
@@ -408,13 +440,13 @@ formatBadCodeException(const char ** const exceptionP,
 
 static void
 readFaxRow(struct bitStream * const bitStreamP,
-           bit *              const bitrow,
+           unsigned char *    const packedBitrow,
            unsigned int *     const lineLengthP,
            const char **      const exceptionP,
            const char **      const errorP) {
 /*----------------------------------------------------------------------------
   Read one line of G3 fax from the bit stream *bitStreamP into 
-  bitrow[].  Return the length of the line, in pixels, as *lineLengthP.
+  packedBitrow[].  Return the length of the line, in pixels, as *lineLengthP.
 
   If there's a problem with the line, return as much of it as we can,
   advance the input stream past the next EOL mark, and put a text
@@ -438,11 +470,9 @@ readFaxRow(struct bitStream * const bitStreamP,
         /* Number of consecutive pixels of the same color */
     bit currentColor;
         /* The color of the current run of pixels */
-    g3TableEntry * te;
-        /* Address of structure that describes the current G3 code */
     bool done;
 
-    makeRowWhite(bitrow, MAXCOLS);  /* initialize row */
+    makeRowWhite(packedBitrow, MAXCOLS);  /* initialize row */
 
     col = 0;
     curlen = 0;
@@ -483,10 +513,14 @@ readFaxRow(struct bitStream * const bitStreamP,
                     formatBadCodeException(exceptionP, col, curlen, curcode);
                     done = TRUE;
                 } else if (curcode != 0) {
-                    te = g3code(curcode, curlen, currentColor);
-                    
-                    if (te) {
-                        processG3Code(te, bitrow, &col, &currentColor, &count);
+                    const g3TableEntry * const teP =
+                        g3code(curcode, curlen, currentColor);
+                        /* Address of structure that describes the 
+                           current G3 code
+                        */
+                    if (teP) {
+                        processG3Code(teP, packedBitrow,
+                                      &col, &currentColor, &count);
                         
                         curcode = 0;
                         curlen = 0;
@@ -504,9 +538,9 @@ readFaxRow(struct bitStream * const bitStreamP,
 
 
 static void
-freeBits(bit **       const bits,
-         unsigned int const rows,
-         bool         const stretched) {
+freeBits(unsigned char ** const packedBits,
+         unsigned int     const rows,
+         bool             const stretched) {
 
     unsigned int row;
 
@@ -516,9 +550,9 @@ freeBits(bit **       const bits,
                free it twice.
             */
         } else 
-            pbm_freerow(bits[row]);
+            pbm_freerow_packed(packedBits[row]);
     }
-    free(bits);
+    free(packedBits);
 }
 
 
@@ -623,8 +657,8 @@ analyzeLineSize(lineSizeAnalyzer * const analyzerP,
 
 
 /* An empty line means EOF.  An ancient comment in the code said there
-   is supposed to 6 EOL marks in a row to indicate EOF, but the code
-   checked for 3 and considered 2 in row just to mean a zero length
+   is supposed to be 6 EOL marks in a row to indicate EOF, but the code
+   checked for 3 and considered 2 in a row just to mean a zero length
    line.  Starting in Netpbm 10.24 (August 2004), we assume there is
    no valid reason to have an empty line and recognize EOF as any
    empty line.  Alternatively, we could read off and ignore two empty
@@ -636,17 +670,17 @@ readFax(struct bitStream * const bitStreamP,
         bool               const stretch,
         unsigned int       const expectedLineSize,
         bool               const tolerateErrors,
-        bit ***            const bitsP,
+        unsigned char ***  const packedBitsP,
         unsigned int *     const colsP,
         unsigned int *     const rowsP) {
 
     lineSizeAnalyzer lineSizeAnalyzer;
-    bit ** bits;
+    unsigned char ** packedBits;
     const char * error;
     bool eof;
     unsigned int row;
     
-    MALLOCARRAY_NOFAIL(bits, MAXROWS);
+    MALLOCARRAY_NOFAIL(packedBits, MAXROWS);
 
     initializeLineSizeAnalyzer(&lineSizeAnalyzer,
                                expectedLineSize, tolerateErrors);
@@ -664,8 +698,9 @@ readFax(struct bitStream * const bitStreamP,
         else {
             const char * exception;
 
-            bits[row] = pbm_allocrow(MAXCOLS);
-            readFaxRow(bitStreamP, bits[row], &lineSize, &exception, &error);
+            packedBits[row] = pbm_allocrow_packed(MAXCOLS);
+            readFaxRow(bitStreamP, packedBits[row],
+                       &lineSize, &exception, &error);
 
             handleRowException(exception, error, row, tolerateErrors);
 
@@ -683,16 +718,16 @@ readFax(struct bitStream * const bitStreamP,
                                       "program can handle at most %u rows "
                                       "after stretching", MAXROWS);
                         else
-                            bits[row] = bits[row-1];
+                            packedBits[row] = packedBits[row-1];
                     }
                     ++row;
                 }
             }
         }
     }
-    *rowsP  = row;
-    *colsP  = lineSizeAnalyzer.maxLineSize;
-    *bitsP  = bits;
+    *rowsP        = row;
+    *colsP        = lineSizeAnalyzer.maxLineSize;
+    *packedBitsP  = packedBits;
 }
 
 
@@ -704,7 +739,8 @@ main(int argc, char * argv[]) {
     FILE * ifP;
     struct bitStream bitStream;
     unsigned int rows, cols;
-    bit ** bits;
+    unsigned char ** packedBits;
+    int row;
 
     pbm_init(&argc, argv);
 
@@ -726,14 +762,17 @@ main(int argc, char * argv[]) {
 
     readFax(&bitStream, cmdline.stretch, cmdline.expectedLineSize,
             !cmdline.stop_error, 
-            &bits, &cols, &rows);
+            &packedBits, &cols, &rows);
 
     pm_close(ifP);
 
-    pbm_writepbm(stdout, bits, cols, rows, 0);
+    pbm_writepbminit(stdout, cols, rows, 0);
+    for (row = 0; row < rows; ++row)
+        pbm_writepbmrow_packed(stdout, packedBits[row], cols, 0);
+
     pm_close(stdout);
 
-    freeBits(bits, rows, cmdline.stretch);
+    freeBits(packedBits, rows, cmdline.stretch);
 
     return 0;
 }
diff --git a/converter/pbm/icontopbm.c b/converter/pbm/icontopbm.c
index d6dba8ae..a0d1bd2b 100644
--- a/converter/pbm/icontopbm.c
+++ b/converter/pbm/icontopbm.c
@@ -46,35 +46,35 @@ ReadIconFile(FILE *                const file,
         }
         variable[i] = '\0';
 
-        if ( STREQ( variable, "*/" )&& gotsome )
+        if ( streq( variable, "*/" )&& gotsome )
             break;
 
         if ( fscanf( file, "%d", &value ) != 1 )
             continue;
 
-        if ( STREQ( variable, "Width" ) )
+        if ( streq( variable, "Width" ) )
         {
             *widthP = value;
             gotsome = 1;
         }
-        else if ( STREQ( variable, "Height" ) )
+        else if ( streq( variable, "Height" ) )
         {
             *heightP = value;
             gotsome = 1;
         }
-        else if ( STREQ( variable, "Depth" )  )
+        else if ( streq( variable, "Depth" )  )
         {
             if ( value != 1 )
                 pm_error( "invalid depth" );
             gotsome = 1;
         }
-        else if ( STREQ( variable, "Format_version" ) )
+        else if ( streq( variable, "Format_version" ) )
         {
             if ( value != 1 )
                 pm_error( "invalid Format_version" );
             gotsome = 1;
         }
-        else if ( STREQ( variable, "Valid_bits_per_item" ) )
+        else if ( streq( variable, "Valid_bits_per_item" ) )
         {
             if ( value != 16 )
                 pm_error( "invalid Valid_bits_per_item" );
diff --git a/converter/pbm/mgrtopbm.c b/converter/pbm/mgrtopbm.c
index cea4be48..9f7004a1 100644
--- a/converter/pbm/mgrtopbm.c
+++ b/converter/pbm/mgrtopbm.c
@@ -1,13 +1,10 @@
-/* mgrtopbm.c - read a MGR bitmap and produce a portable bitmap
-**
-** Copyright (C) 1989 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
+/* mgrtopbm.c - read a MGR bitmap and produce a PBM image.
+
+   Copyright information is at end of file.
+
+   You can find MGR and some MGR format test images at
+   ftp://sunsite.unc.edu/pub/Linux/apps/MGR/!INDEX.html
+
 */
 
 #include <string.h>
@@ -17,29 +14,29 @@
 #include "mgr.h"
 
 
-static unsigned char item;
-static int bitsperitem, bitshift;
 
 static void
-getinit(FILE * const file, 
-        int *  const colsP, 
-        int *  const rowsP, 
-        int *  const depthP, 
-        int *  const padrightP,
-        int *  const bitsperitemP) {
-
+readMgrHeader(FILE *          const ifP, 
+              unsigned int *  const colsP, 
+              unsigned int *  const rowsP, 
+              unsigned int *  const depthP, 
+              unsigned int *  const padrightP ) {
+    
     struct b_header head;
-    int pad;
+    unsigned int pad;
+    size_t bytesRead;
 
-    if (fread(&head, sizeof(struct old_b_header), 1, file ) != 1)
+    bytesRead = fread(&head, sizeof(struct old_b_header), 1, ifP);
+    if (bytesRead != 1)
         pm_error("Unable to read 1st byte of file.  "
                  "fread() returns errno %d (%s)",
                  errno, strerror(errno));
     if (head.magic[0] == 'y' && head.magic[1] == 'z') { 
         /* new style bitmap */
-        if (fread(&head.depth, 
-                  sizeof(head) - sizeof(struct old_b_header), 1, file) 
-             != 1 )
+        size_t bytesRead;
+        bytesRead = fread(&head.depth, 
+                          sizeof(head) - sizeof(struct old_b_header), 1, ifP);
+        if (bytesRead != 1 )
             pm_error("Unable to read header after 1st byte.  "
                      "fread() returns errno %d (%s)",
                      errno, strerror(errno));
@@ -60,7 +57,7 @@ getinit(FILE * const file,
     } else {
         pm_error("bad magic chars in MGR file: '%c%c'",
                  head.magic[0], head.magic[1] );
-        pad = -1;  /* should never reach here */
+        pad = 0;  /* should never reach here */
     }
 
     if (head.h_wide < ' ' || head.l_wide < ' ')
@@ -71,75 +68,79 @@ getinit(FILE * const file,
     *colsP = (((int)head.h_wide - ' ') << 6) + ((int)head.l_wide - ' ');
     *rowsP = (((int)head.h_high - ' ') << 6) + ((int) head.l_high - ' ');
     *padrightP = ( ( *colsP + pad - 1 ) / pad ) * pad - *colsP;
-    
-    *bitsperitemP = 8;
 }
 
 
 
-static bit
-getbit( file )
-    FILE* file;
-    {
-    bit b;
-
-    if ( bitsperitem == 8 )
-	{
-	item = getc( file );
-	bitsperitem = 0;
-	bitshift = 7;
-	}
-    bitsperitem++;
-    b = ( ( item >> bitshift) & 1 ) ? PBM_BLACK : PBM_WHITE;
-    bitshift--;
-    return b;
-    }
-
+int
+main(int    argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    unsigned char * bitrow;
+    unsigned int rows, cols, depth;
+    unsigned int padright;
+    unsigned int row;
+    unsigned int itemCount;
+    const char * inputFileName;
+
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
+    else
+        inputFileName = "-";
+    
+    ifP = pm_openr(inputFileName);
 
+    readMgrHeader(ifP, &cols, &rows, &depth, &padright);
+    if (depth != 1)
+        pm_error("MGR file has depth of %u, must be 1", depth);
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, depth, padright, row, col;
+    pbm_writepbminit(stdout, cols, rows, 0);
 
+    bitrow = pbm_allocrow_packed(cols + padright);
+    
+    itemCount = (cols + padright ) / 8;
+
+    for (row = 0; row < rows; ++row) {
+        /* The raster formats are nearly identical.
+           MGR may have rows padded to 16 or 32 bit boundaries.
+        */
+        size_t bytesRead;
+        bytesRead = fread(bitrow, 1, itemCount, ifP);
+        if (bytesRead < itemCount)
+            pm_error("fread() failed to read mgr bitmap data");
+
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
+    }
+    pm_close(ifP);
+    pm_close(stdout);
+    return 0;
+}
 
-    pbm_init( &argc, argv );
 
-    if ( argc > 2 )
-	pm_usage( "[mgrfile]" );
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
-
-    getinit( ifp, &cols, &rows, &depth, &padright, &bitsperitem );
-    if ( depth != 1 )
-	pm_error( "MGR file has depth of %d, must be 1", depth );
-
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
-
-    for ( row = 0; row < rows; row++ )
-	{
-	/* Get data, bit-reversed within each byte. */
-        for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
-	    *bP = getbit( ifp );
-	/* Discard line padding */
-        for ( col = 0; col < padright; col ++ )
-	    (void) getbit( ifp );
-	pbm_writepbmrow( stdout, bitrow, cols, 0 );
-	}
-
-    pm_close( ifp );
-    pm_close( stdout );
-
-    exit( 0 );
-    }
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from getc() to fread(),
+   write function from pbm_writepbmrow() to pbm_writepbmrow_packed().
+   Retired bitwise transformation functions.
+   
+   NOT tested for old-style format files.  Only one zz file in mgrsrc-0.69 .
+  
+*/
 
 
+/*
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+*/
diff --git a/converter/pbm/mrftopbm.c b/converter/pbm/mrftopbm.c
index 9534f3a5..51281028 100644
--- a/converter/pbm/mrftopbm.c
+++ b/converter/pbm/mrftopbm.c
@@ -41,34 +41,50 @@ bit_input(FILE * const in) {
 
 
 static void 
-doSquare(FILE *          const in,
-          unsigned char * const image,
-          int             const ox,
-          int             const oy,
-          int             const w,
-          int             const size) {
-
-    if (size == 1 || bit_input(in)) { 
+doSquare(FILE *          const ifP,
+         unsigned char * const image,
+         unsigned int    const ulCol,
+         unsigned int    const ulRow,
+         unsigned int    const imageWidth,
+         unsigned int    const size) {
+/*----------------------------------------------------------------------------
+   Do a square of side 'size', whose upper left corner is at (ulCol, ulRow).
+   The contents of that square are next in file *ifP, in MRF format.
+
+   Return the pixel values of the square in the corresponding position of
+   image[], which is a concatenation of rows 'imageWidth' pixels wide, one
+   byte per pixel.
+-----------------------------------------------------------------------------*/
+    if (size == 1 || bit_input(ifP)) { 
         /* It's all black or all white.  Next bit says which. */
 
-        unsigned int const c = bit_input(in);
+        unsigned int const c = bit_input(ifP);
 
-        unsigned int y;
+        unsigned int rowOfSquare;
 
-        for (y = 0; y < size; ++y) {
-            unsigned int x;
-            for (x = 0; x < size; ++x)
-                image[(oy+y)*w+ox+x] = c;
+        for (rowOfSquare = 0; rowOfSquare < size; ++rowOfSquare) {
+            unsigned int colOfSquare;
+            for (colOfSquare = 0; colOfSquare < size; ++colOfSquare) {
+                unsigned int rowOfImage = ulRow + rowOfSquare;
+                unsigned int colOfImage = ulCol + colOfSquare;
+
+                image[rowOfImage * imageWidth + colOfImage] = c;
+            }
         }
     } else {
-        /* not all one color, so recurse. */
-
-        int halfsize = size >> 1;
-
-        doSquare(in, image, ox,          oy,          w, halfsize);
-        doSquare(in, image, ox+halfsize, oy,          w, halfsize);
-        doSquare(in, image, ox,          oy+halfsize, w, halfsize);
-        doSquare(in, image, ox+halfsize, oy+halfsize, w, halfsize);
+        /* Square is not all one color, so recurse.  Do each of the four
+           quadrants of this square individually.
+        */
+        unsigned int const quadSize = size/2;
+
+        doSquare(ifP, image, ulCol,            ulRow,
+                 imageWidth, quadSize);
+        doSquare(ifP, image, ulCol + quadSize, ulRow,
+                 imageWidth, quadSize);
+        doSquare(ifP, image, ulCol,            ulRow + quadSize,
+                 imageWidth, quadSize);
+        doSquare(ifP, image, ulCol + quadSize, ulRow + quadSize,
+                 imageWidth, quadSize);
     }
 }
 
@@ -80,7 +96,7 @@ writeOutput(FILE *                const ofP,
             int                   const rows,
             const unsigned char * const image) {
             
-    /* w64 is units-of-64-bits width, h64 same for height */
+    /* w64 is units-of-64-bits width */
     unsigned int const w64 = (cols+63)/64;
 
     bit * bitrow;
@@ -145,7 +161,7 @@ readMrfImage(FILE *           const ifP,
         pm_error("Ridiculously large, unprocessable image: %u cols x %u rows",
                  cols, rows);
 
-    image = calloc(w64*h64*64*64,1);
+    image = calloc(w64*h64*64*64, 1);
     if (image == NULL)
         pm_error("Unable to get memory for raster");
                  
@@ -179,7 +195,7 @@ main(int argc, char *argv[]) {
 
     expandAll = FALSE;  /* initial assumption */
 
-    if (argc-1 >= 1 && STREQ(argv[1], "-a")) {
+    if (argc-1 >= 1 && streq(argv[1], "-a")) {
         expandAll = TRUE;
         argc--,argv++;
     }
diff --git a/converter/pbm/pbmto4425.c b/converter/pbm/pbmto4425.c
index 605b12d5..1d97ac6a 100644
--- a/converter/pbm/pbmto4425.c
+++ b/converter/pbm/pbmto4425.c
@@ -145,7 +145,7 @@ main(int argc, char * argv[]) {
         pbmfile = argv[argn];
     }
 
-    if(STREQ(pbmfile, "-"))
+    if(streq(pbmfile, "-"))
     {
         pbmfp = stdin;
     }
diff --git a/converter/pbm/pbmtocmuwm.c b/converter/pbm/pbmtocmuwm.c
index 64d7af40..773d988b 100644
--- a/converter/pbm/pbmtocmuwm.c
+++ b/converter/pbm/pbmtocmuwm.c
@@ -1,4 +1,4 @@
-/* pbmtocmuwm.c - read a portable bitmap and produce a CMU window manager bitmap
+/* pbmtocmuwm.c - read a PBM image and produce a CMU window manager bitmap
 **
 ** Copyright (C) 1989 by Jef Poskanzer.
 **
@@ -10,108 +10,95 @@
 ** implied warranty.
 */
 
-#include "pbm.h"
-#include "cmuwm.h"
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from pbm_readpbmrow() to
+   pbm_readpbmrow_packed(), write function from putc() to fwrite().
 
-static void putinit ARGS(( int rows, int cols ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
-
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, format, padright, row, col;
+   Retired bitwise transformation functions.
+*/
 
+#include "pbm.h"
+#include "cmuwm.h"
 
-    pbm_init( &argc, argv );
+static void
+putinit(unsigned int const rows,
+        unsigned int const cols) {
 
-    if ( argc > 2 )
-	pm_usage( "[pbmfile]" );
+    const char * const initWriteError =
+        "CMU window manager header write error";
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
+    int rc;
 
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
-    
-    /* Round cols up to the nearest multiple of 8. */
-    padright = ( ( cols + 7 ) / 8 ) * 8 - cols;
+    rc = pm_writebiglong(stdout, CMUWM_MAGIC);
+    if (rc == -1)
+        pm_error(initWriteError);
+    rc = pm_writebiglong(stdout, cols);
+    if (rc == -1)
+        pm_error(initWriteError);
+    rc = pm_writebiglong(stdout, rows);
+    if (rc == -1)
+        pm_error(initWriteError);
+    rc = pm_writebigshort(stdout, (short) 1);
+    if (rc == -1)
+        pm_error(initWriteError);
+}
 
-    putinit( rows, cols );
-    for ( row = 0; row < rows; row++ )
-	{
-	pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
-	    putbit( *bP );
-	for ( col = 0; col < padright; col++ )
-	    putbit( 0 );
-        }
 
-    pm_close( ifp );
 
-    putrest( );
+int
+main(int argc,
+     char * argv[]) {
 
-    exit( 0 );
-    }
+    FILE * ifP;
+    unsigned char * bitrow;
+    int rows, cols;
+    int format;
+    unsigned int row;
+    const char * inputFileName;
 
-static unsigned char item;
-static int bitsperitem, bitshift;
+    pbm_init(&argc, argv);
 
-static void
-putinit( rows, cols )
-    int rows, cols;
-    {
-    if ( pm_writebiglong( stdout, CMUWM_MAGIC ) == -1 )
-	pm_error( "write error" );
-    if ( pm_writebiglong( stdout, cols ) == -1 )
-	pm_error( "write error" );
-    if ( pm_writebiglong( stdout, rows ) == -1 )
-	pm_error( "write error" );
-    if ( pm_writebigshort( stdout, (short) 1 ) == -1 )
-	pm_error( "write error" );
-
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
-    }
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
+    else
+        inputFileName = "-";
+    
+    ifP = pm_openr(inputFileName);
 
-#if __STDC__
-static void
-putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
-    {
-    if ( bitsperitem == 8 )
-	putitem( );
-    if ( b == PBM_WHITE )
-	item += 1 << bitshift;
-    bitsperitem++;
-    bitshift--;
-    }
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+    bitrow = pbm_allocrow_packed(cols);
 
-static void
-putrest( )
-    {
-    if ( bitsperitem > 0 )
-	putitem( );
+    putinit(rows, cols);
+    
+    /* Convert PBM raster data to CMUWM and write */ 
+    for (row = 0; row < rows; ++row) {
+        unsigned int const bytesPerRow = pbm_packed_bytes(cols);
+        unsigned char const padding = 
+            (cols % 8 == 0) ? 0x00 : ((unsigned char) ~0 >> (cols % 8));
+
+        unsigned int i;
+        size_t bytesWritten;
+
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+
+        /* Invert all bits in row - raster formats are similar.
+           PBM   Black:1 White:0  "Don't care" bits at end of row
+           CMUWM Black:0 White:1  End of row padded with 1
+        */
+
+        for (i = 0; i < bytesPerRow; ++i)
+            bitrow[i] = ~bitrow[i];
+
+        bitrow[bytesPerRow-1] |= padding;  /* Set row end pad bits */
+        
+        bytesWritten = fwrite(bitrow, 1, bytesPerRow, stdout);
+        if (bytesWritten != bytesPerRow)
+            pm_error("fwrite() failed to write CMU window manager bitmap");
     }
 
-static void
-putitem( )
-    {
-    (void) putc( item, stdout );
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
-    }
+    pm_close(ifP);
+    return 0;
+}
diff --git a/converter/pbm/pbmtodjvurle.c b/converter/pbm/pbmtodjvurle.c
index dbe96f31..83e99ec4 100644
--- a/converter/pbm/pbmtodjvurle.c
+++ b/converter/pbm/pbmtodjvurle.c
@@ -50,91 +50,97 @@ writebyte(FILE *        const ofP,
 
 /* Write a run length to the RLE file. */
 static void 
-write_rle (FILE *rlefile, uint32n tally)
-{
-  do {
-    /* Output a single run. */
-    if (tally < 192) {
-      /* Single-byte runs */
-      writebyte (rlefile, tally);
-      tally >>= 8;
+write_rle(FILE *   const rlefile,
+          uint32_t const tallyArg) {
+
+    uint32_t remainingTally;
+
+    remainingTally = tallyArg;  /* initial value */
+
+    do {
+        /* Output a single run. */
+        if (remainingTally < 192) {
+            /* Single-byte runs */
+            writebyte (rlefile, remainingTally);
+            remainingTally >>= 8;
+        }
+        else {
+            /* Two-byte runs */
+            writebyte (rlefile, ((remainingTally>>8) & 0x3F) + 0xC0);
+            writebyte (rlefile, remainingTally & 0xFF);
+            remainingTally >>= 14;
+        }
+
+        /* Very large runs need to be split into smaller runs.  We
+           therefore need to toggle back to the same color we had for the
+           previous smaller run.
+        */
+        if (remainingTally > 0)
+            writebyte (rlefile, 0);
     }
-    else {
-      /* Two-byte runs */
-      writebyte (rlefile, ((tally>>8)&0x3F) + 0xC0);
-      writebyte (rlefile, tally&0xFF);
-      tally >>= 14;
-    }
-
-    /* Very large runs need to be split into smaller runs.  We
-     * therefore need to toggle back to the same color we had for the
-     * previous smaller run. */
-    if (tally > 0)
-      writebyte (rlefile, 0);
-  }
-  while (tally > 0);
+    while (remainingTally > 0);
 }
 
 
 
 int 
-main (int argc, char *argv[])
-{
-  FILE * const rlefile = stdout;    /* Generated Bitonal RLE file */
-
-  FILE *pbmfile;             /* PBM file to convert */
-  int numcols, numrows;      /* Width and height in pixels of the PBM file */
-  int format;                /* Original image type before conversion to PBM */
-  bit *pbmrow;               /* One row of the PBM file */
-  uint32n pixeltally = 0;    /* Run length of the current color */
-  int row, col;              /* Row and column loop variables */
-  const char * pbmfilename;  /* Name of input file */
-
-  /* Parse the command line. */
-  pbm_init (&argc, argv);
-
-  if (argc-1 < 1)
-      pbmfilename = "-";
-  else if (argc-1 == 1)
-      pbmfilename = argv[1];
-  else
-      pm_error("Program takes at most 1 argument -- the input file name.  "
-               "You specified %d", argc-1);
-
-  pbmfile = pm_openr(pbmfilename);
-
-  /* Write an RLE header. */
-  pbm_readpbminit (pbmfile, &numcols, &numrows, &format);
-  fprintf (rlefile, "R4\n");
-  fprintf (rlefile, "%d %d\n", numcols, numrows);
-
-  /* Write the RLE data. */
-  pbmrow = pbm_allocrow (numcols);
-  for (row=0; row<numrows; row++) {
-    bit prevpixel;        /* Previous pixel seen */
-
-    pbm_readpbmrow (pbmfile, pbmrow, numcols, format);
-    prevpixel = PBM_WHITE;   /* Bitonal RLE rows always start with white */
-    pixeltally = 0;
-    for (col=0; col<numcols; col++) {
-      bit newpixel = pbmrow[col];      /* Current pixel color */
-
-      if (newpixel == prevpixel)
-        pixeltally++;
-      else {
-        write_rle (rlefile, pixeltally);
-        pixeltally = 1;
-        prevpixel = newpixel;
-      }
+main (int argc, const char * argv[]) {
+
+    FILE * const rlefile = stdout; /* Generated Bitonal RLE file */
+
+    FILE * pbmfile;          /* PBM file to convert */
+    int numcols, numrows;    /* Width and height in pixels of the PBM file */
+    int format;              /* Original image type before conversion to PBM */
+    bit * pbmrow;            /* One row of the PBM file */
+    unsigned int row;
+    const char * pbmfilename;  /* Name of input file */
+
+    pm_proginit(&argc, argv);
+
+    if (argc-1 < 1)
+        pbmfilename = "-";
+    else if (argc-1 == 1)
+        pbmfilename = argv[1];
+    else
+        pm_error("Program takes at most 1 argument -- the input file name.  "
+                 "You specified %d", argc-1);
+
+    pbmfile = pm_openr(pbmfilename);
+
+    /* Write an RLE header. */
+    pbm_readpbminit(pbmfile, &numcols, &numrows, &format);
+    fprintf(rlefile, "R4\n");
+    fprintf(rlefile, "%d %d\n", numcols, numrows);
+
+    /* Write the RLE data. */
+    pbmrow = pbm_allocrow(numcols);
+    for (row = 0; row < numrows; ++row) {
+        unsigned int col;
+        uint32_t pixeltally;   /* Run length of the current color */
+        bit prevpixel;         /* Previous pixel seen */
+
+        pbm_readpbmrow(pbmfile, pbmrow, numcols, format);
+        prevpixel = PBM_WHITE;   /* Bitonal RLE rows always start with white */
+        pixeltally = 0;
+        for (col = 0; col < numcols; ++col) {
+            bit newpixel = pbmrow[col];      /* Current pixel color */
+
+            if (newpixel == prevpixel)
+                ++pixeltally;
+            else {
+                write_rle(rlefile, pixeltally);
+                pixeltally = 1;
+                prevpixel = newpixel;
+            }
+        }
+        write_rle(rlefile, pixeltally);
     }
-    write_rle (rlefile, pixeltally);
-  }
-
-  /* Finish up cleanly. */
-  pbm_freerow (pbmrow);
-  if (rlefile != stdout)
-    pm_close (rlefile);
-  if (pbmfile != stdin)
-    pm_close (pbmfile);
-  exit (0);
+
+    pbm_freerow(pbmrow);
+    if (rlefile != stdout)
+        pm_close(rlefile);
+    if (pbmfile != stdin)
+        pm_close(pbmfile);
+
+    return 0;
 }
diff --git a/converter/pbm/pbmtoepsi.c b/converter/pbm/pbmtoepsi.c
index 81e03fbe..5eccc298 100644
--- a/converter/pbm/pbmtoepsi.c
+++ b/converter/pbm/pbmtoepsi.c
@@ -16,6 +16,7 @@
 ** implied warranty.
 */
 
+#include "pm_c_util.h"
 #include "pbm.h"
 #include "shhopt.h"
 
diff --git a/converter/pbm/pbmtoepson.c b/converter/pbm/pbmtoepson.c
index 1d1b1608..86185d15 100644
--- a/converter/pbm/pbmtoepson.c
+++ b/converter/pbm/pbmtoepson.c
@@ -16,8 +16,9 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "shhopt.h"
+#include "pm_c_util.h"
 #include "mallocvar.h"
+#include "shhopt.h"
 
 #include "pbm.h"
 
diff --git a/converter/pbm/pbmtoescp2.c b/converter/pbm/pbmtoescp2.c
index 9992fec9..e280b3df 100644
--- a/converter/pbm/pbmtoescp2.c
+++ b/converter/pbm/pbmtoescp2.c
@@ -16,6 +16,7 @@
 
 #include <string.h>
 
+#include "pm_c_util.h"
 #include "pbm.h"
 #include "shhopt.h"
 
diff --git a/converter/pbm/pbmtog3.c b/converter/pbm/pbmtog3.c
index 77ea545a..c0dd8c64 100644
--- a/converter/pbm/pbmtog3.c
+++ b/converter/pbm/pbmtog3.c
@@ -18,12 +18,14 @@
 
 #include <assert.h>
 
-#include "pbm.h"
+#include "pm_c_util.h"
 #include "shhopt.h"
 #include "mallocvar.h"
 #include "bitreverse.h"
 #include "wordaccess.h"
+#include "wordintclz.h"
 #include "g3.h"
+#include "pbm.h"
 
 #define TC_MC 64
 
@@ -55,7 +57,7 @@ struct bitString {
 
 struct outStream {
     struct bitString buffer;
-    
+
     bool reverseBits;
 };
 
@@ -109,6 +111,8 @@ parseCommandLine(int argc, char ** const argv,
     optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
+    free(option_def);
+
     if (argc-1 == 0) 
         cmdlineP->inputFileName = "-";
     else if (argc-1 != 1)
@@ -142,7 +146,7 @@ makeBs(wordint      const bits,
     return retval;
 }
 
-    
+
 
 static __inline__ void
 putbits(struct bitString const newBits) {
@@ -153,7 +157,7 @@ putbits(struct bitString const newBits) {
    Flush the buffer to stdout as necessary to make room.
 
    'newBits' must be shorter than a whole word.
-   
+
    N.B. the definition of struct bitString requires upper bits to be zero.
 -----------------------------------------------------------------------------*/
     unsigned int const spaceLeft = 
@@ -182,11 +186,11 @@ putbits(struct bitString const newBits) {
                        | (newBits.intBuffer >> nextBufBitCount));
         if (out.reverseBits)
             reversebuffer(outbytes, sizeof(outbytes));
-            
+
         rc = fwrite(outbytes, 1, sizeof(outbytes), stdout);
         if (rc != sizeof(outbytes))
             pm_error("Output error.  Unable to fwrite() to stdout");
-        
+
         out.buffer.intBuffer = newBits.intBuffer & ((1<<nextBufBitCount) - 1); 
         out.buffer.bitCount = nextBufBitCount;
     }
@@ -237,7 +241,7 @@ putcode2(int const clr,
 
     if (sizeof(wordint) * 8 > 24) {
         unsigned int const l1 = ttable[loIndex].length;
-        
+
         putbits(
             makeBs(mtable[hiIndex].code << l1 | ttable[loIndex].code,
                    mtable[hiIndex].length + l1)
@@ -299,7 +303,7 @@ puteol(void) {
         puts("EOL");
     else {
         struct bitString const eol = {12, 1};
-            
+
         putbits(eol);
     }
 }
@@ -341,7 +345,7 @@ convertRowToRunLengths(unsigned char * const bitrow,
     wordint      * const bitrowByWord = (wordint *) bitrow;
     int            const wordCount    = (cols + bitsPerWord - 1)/bitsPerWord; 
         /* Number of full and partial words in the row */
-        
+
 
     if (cols % bitsPerWord != 0) {
         /* Clean final word in row.  For loop simplicity */
@@ -411,7 +415,7 @@ main(int    argc,
            a word of zero padding on the high (right) end for the convenience
            of code that accesses this buffer in word-size bites.
         */
-     
+
     int rows;
     int cols;
     int readcols;
@@ -423,7 +427,7 @@ main(int    argc,
     pbm_init(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
-     
+
     ifP = pm_openr(cmdline.inputFileName);
 
     pbm_readpbminit(ifP, &cols, &rows, &format);
@@ -447,9 +451,9 @@ main(int    argc,
         unsigned int i;
 
         pbm_readpbmrow_packed(ifP, bitrow, cols, format);
-        
+
         convertRowToRunLengths(bitrow, readcols, milepost, &nRun);
-        
+
         padToDesiredWidth(milepost, &nRun, readcols, outwidth);
 
         for (i = p = 0; i < nRun; p = milepost[i++])
@@ -459,6 +463,8 @@ main(int    argc,
     }
 
     free(milepost);
+    pbm_freerow_packed(bitrow);
+
     {
         unsigned int i;  
         for( i = 0; i < 6; ++i)
@@ -467,7 +473,7 @@ main(int    argc,
     if (out.buffer.bitCount > 0) {
         /* flush final partial buffer */
         unsigned int const bytesToWrite = (out.buffer.bitCount+7)/8;
-        
+
         unsigned char outbytes[sizeof(wordint)];
         size_t rc;
         wordintToBytes(&outbytes, 
diff --git a/converter/pbm/pbmtogem.c b/converter/pbm/pbmtogem.c
index 59f2b9cf..cefbdc95 100644
--- a/converter/pbm/pbmtogem.c
+++ b/converter/pbm/pbmtogem.c
@@ -129,14 +129,8 @@ putinit (rows, cols)
   linerepeat = -1;
 }
 
-#if __STDC__
 static void
 putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
     {
     if ( bitsperitem == 8 )
 	putitem( );
diff --git a/converter/pbm/pbmtogo.c b/converter/pbm/pbmtogo.c
index 18f3ab6c..23b2ee9a 100644
--- a/converter/pbm/pbmtogo.c
+++ b/converter/pbm/pbmtogo.c
@@ -1,11 +1,11 @@
 /* pbmtogo.c - read a PBM image and produce a GraphOn terminal raster file
-**	
-**	Rev 1.1 was based on pbmtolj.c
+**      
+**      Rev 1.1 was based on pbmtolj.c
 **
-**	Bo Thide', Swedish Institute of Space Physics, bt@irfu.se
-**				   
+**      Bo Thide', Swedish Institute of Space Physics, bt@irfu.se
+**                                 
 **
-** $Log:	pbmtogo.c,v $
+** $Log:        pbmtogo.c,v $
  * Revision 1.5  89/11/25  00:24:12  00:24:12  root (Bo Thide)
  * Bug found: The byte after 64 repeated bytes sometimes lost. Fixed.
  * 
@@ -35,63 +35,125 @@
 ** implied warranty.
 */
 
+#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
 #include "pm_c_util.h"
 #include "pbm.h"
 
-#define BUFSIZE 132	/* GraphOn has 132 byte/1056 bit wide raster lines */
-#define REPEAT_CURRENT_LINE_MASK	0x00 
-#define SKIP_AND_PLOT_MASK		0x40 
-#define REPEAT_PLOT_MASK		0x80 
-#define PLOT_ARBITRARY_DATA_MASK	0xc0 
+#define GRAPHON_WIDTH 1056 /* GraphOn has 1056 bit wide raster lines */
+#define GRAPHON_WIDTH_BYTES (GRAPHON_WIDTH / 8)
+#define REPEAT_CURRENT_LINE_MASK        0x00 
+#define SKIP_AND_PLOT_MASK              0x40 
+#define REPEAT_PLOT_MASK                0x80 
+#define PLOT_ARBITRARY_DATA_MASK        0xc0 
 #define MAX_REPEAT 64
 
-static unsigned char *scanlineptr;		/* Pointer to current scan line byte */
+static unsigned char * scanlineptr;
+    /* Pointer to current scan line byte */
 
-static void putinit ARGS(( void ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
+static int item, bitsperitem, bitshift;
 
-int
-main( argc, argv )
-     int argc;
-     char* argv[];
-{
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int argn, rows, cols, format, rucols, padright, row, col;
-    int nbyte, bytesperrow, ecount, ucount, nout, i, linerepeat;
-    int	olditem;
-    unsigned char oldscanline[BUFSIZE];
-    unsigned char newscanline[BUFSIZE];
-    unsigned char diff[BUFSIZE];
-    unsigned char buffer[BUFSIZE];
-    unsigned char outbuffer[2*(BUFSIZE+1)];	/* Worst case.  Should malloc */
-    const char* usage = "[-c] [pbmfile]";
+static void
+putinit(void) {
+
+    /* Enter graphics window */
+    printf("\0331");
+
+    /* Erase graphics window */
+    printf("\033\014");
+
+    /* Set graphics window in raster mode */
+    printf("\033r");
+
+    /* Select standard Tek coding **/
+    printf("\033[=11l");
+
+    bitsperitem = 1;
+    item = 0;
+    bitshift = 7;
+}
+
+
+
+static void
+putitem(void) {
 
+    *scanlineptr++ = item;
+    bitsperitem = 0;
+    item = 0;
+}
+
+
+
+static void
+putbit(bit const b) {
+
+    if (b == PBM_BLACK)
+        item += 1 << bitshift;
+
+    bitshift--;
+
+    if (bitsperitem == 8)
+    {
+        putitem();
+        bitshift = 7;
+    }
+    bitsperitem++;
+}
+
+
+
+static void
+putrest(void) {
 
-    pbm_init( &argc, argv );
+    if (bitsperitem > 1)
+        putitem();
 
-    argn = 2;
+    /* end raster downloading */
+    printf("\033\134");
 
-    /* Check for flags. */
-    if (argc > argn + 1)
-      pm_usage(usage);
+    /* Exit raster mode */
+    printf("\033t");
 
-    if (argc == argn)
-      ifp = pm_openr( argv[argn-1] );
+    /* Exit graphics window
+       printf("\0332"); */
+}
+
+
+
+int
+main(int           argc,
+     const char ** argv) {
+
+    FILE * ifP;
+    bit * bitrow;
+    bit * bP;
+    int rows, cols, format, rucols, padright, row, col;
+    int nbyte, bytesperrow, ecount, ucount, nout, i, linerepeat;
+    int olditem;
+    unsigned char oldscanline[GRAPHON_WIDTH_BYTES];
+    unsigned char newscanline[GRAPHON_WIDTH_BYTES];
+    unsigned char diff[GRAPHON_WIDTH_BYTES];
+    unsigned char buffer[GRAPHON_WIDTH_BYTES];
+    unsigned char outbuffer[2*(GRAPHON_WIDTH_BYTES+1)];     /* Worst case. */
+
+    pm_proginit(&argc, argv);
+
+    if (argc-1 == 0)
+      ifP = stdin;
+    else if (argc-1 == 1)
+      ifP = pm_openr(argv[1]);
     else
-      ifp = stdin;
+        pm_error("There is at most one argument: input file name.  "
+                 "You specified %u", argc-1);
 
-    pbm_readpbminit(ifp, &cols, &rows, &format);
+    pbm_readpbminit(ifP, &cols, &rows, &format);
 
-    if (cols > 1056)
+    if (cols > GRAPHON_WIDTH)
         pm_error("Image is wider (%u pixels) than a Graphon terminal "
-                 "(%u pixels)", cols, 1056);
+                 "(%u pixels)", cols, GRAPHON_WIDTH);
 
     bitrow = pbm_allocrow(cols);
 
@@ -101,7 +163,7 @@ main( argc, argv )
     rucols = rucols * 8;
     padright = rucols - cols;
 
-    for (i = 0; i < BUFSIZE; ++i )
+    for (i = 0; i < GRAPHON_WIDTH_BYTES; ++i )
       buffer[i] = oldscanline[i] = 0;
     putinit();
 
@@ -113,12 +175,14 @@ main( argc, argv )
     for (row = 0; row < rows; row++) {
         /* Store scan line data in the new scan line vector */
         scanlineptr = newscanline;
-        pbm_readpbmrow(ifp, bitrow, cols, format);
+        pbm_readpbmrow(ifP, bitrow, cols, format);
         /* Transfer raster graphics */
         for (col = 0, bP = bitrow; col < cols; col++, bP++)
           putbit(*bP);
         for (col = 0; col < padright; col++)
           putbit(0);
+
+        assert(bytesperrow <= GRAPHON_WIDTH_BYTES);
         
         /* XOR data from the new scan line with data from old scan line */
         for (i = 0; i < bytesperrow; i++)
@@ -219,7 +283,7 @@ main( argc, argv )
             fflush(stdout);
 
             /* Output the plot data */
-            write(1, outbuffer, nout);
+            fwrite(outbuffer, 1, nout, stdout);
 
             /* Reset the counters */
             linerepeat = 0;
@@ -230,7 +294,7 @@ main( argc, argv )
                   putchar(linerepeat);
                   printf("%d/", nout+1);
                   fflush(stdout);
-                  write(1, outbuffer, nout);
+                  fwrite(outbuffer, 1, nout, stdout);
                   linerepeat = 0;
               }
         }
@@ -240,75 +304,11 @@ main( argc, argv )
           oldscanline[i] = newscanline[i];
     }
     putchar(linerepeat);        /* For the last line(s) to be plotted */
-    pm_close(ifp);
+    pm_close(ifP);
     putrest();
-    exit(0);
-}
-
-
-
-static int item, bitsperitem, bitshift;
-
-static void
-putinit()
-{
-  /* Enter graphics window */
-  printf("\0331");
-
-  /* Erase graphics window */
-  printf("\033\014");
-
-  /* Set graphics window in raster mode */
-  printf("\033r");
-
-  /* Select standard Tek coding **/
-  printf("\033[=11l");
 
-  bitsperitem = 1;
-  item = 0;
-  bitshift = 7;
-}
-
-#if __STDC__
-static void
-putbit(bit b)
-#else /*__STDC__*/
-static void
-putbit(b)
-bit b;
-#endif /*__STDC__*/
-{
-  if (b == PBM_BLACK)
-    item += 1 << bitshift;
-  bitshift--;
-  if (bitsperitem == 8)
-  {
-    putitem();
-    bitshift = 7;
-  }
-  bitsperitem++;
+    return 0;
 }
 
-static void
-putrest()
-{
-  if (bitsperitem > 1)
-      putitem();
-
-  /* end raster downloading */
-  printf("\033\134");
 
-  /* Exit raster mode */
-  printf("\033t");
 
-  /* Exit graphics window
-  printf("\0332"); */
-}
-
-static void
-putitem()
-  {
-  *scanlineptr++ = item;
-  bitsperitem = 0;
-  item = 0;
-  }
diff --git a/converter/pbm/pbmtoibm23xx.c b/converter/pbm/pbmtoibm23xx.c
index 973f7de0..a83e260d 100644
--- a/converter/pbm/pbmtoibm23xx.c
+++ b/converter/pbm/pbmtoibm23xx.c
@@ -46,6 +46,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "pm_c_util.h"
 #include "pbm.h"
 #include "shhopt.h"
 #include "mallocvar.h"
diff --git a/converter/pbm/pbmtoicon.c b/converter/pbm/pbmtoicon.c
index 0e21c202..d5fefb76 100644
--- a/converter/pbm/pbmtoicon.c
+++ b/converter/pbm/pbmtoicon.c
@@ -1,4 +1,4 @@
-/* pbmtoicon.c - read a portable bitmap and produce a Sun icon file
+/* pbmtoicon.c - read a PBM image and produce a Sun icon file
 **
 ** Copyright (C) 1988 by Jef Poskanzer.
 **
@@ -10,125 +10,177 @@
 ** implied warranty.
 */
 
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from pbm_readpbmrow() to
+   pbm_readpbmrow_packed.  Applied wordint to scoop up 16 bit output items.
+   putitem changed to better express the output format.
+   Retired bitwise transformation functions.
+*/
+
+#include "wordaccess.h"
 #include "pbm.h"
 
-static void putinit ARGS(( void ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
+static unsigned short int itemBuff[8];
+static unsigned int itemCnt;    /* takes values 0 to 8 */
+FILE * putFp;
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, format, pad, padleft, padright, row, col;
 
 
-    pbm_init( &argc, argv );
+static void
+putinit(FILE * const ofP) {
+    putFp = ofP;
+    itemCnt = 0;
+}
 
-    if ( argc > 2 )
-	pm_usage( "[pbmfile]" );
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
-    else
-	ifp = stdin;
 
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
+static void
+putitem(wordint const item) {
+
+    if (itemCnt == 8 ) {
+        /* Buffer is full.  Write out one line. */
+        int rc;
     
-    /* Round cols up to the nearest multiple of 16. */
-    pad = ( ( cols + 15 ) / 16 ) * 16 - cols;
-    padleft = pad / 2;
-    padright = pad - padleft;
-
-    printf( "/* Format_version=1, Width=%d, Height=%d", cols + pad, rows );
-    printf( ", Depth=1, Valid_bits_per_item=16\n */\n" );
-
-    putinit( );
-    for ( row = 0; row < rows; ++row )
-	{
-	pbm_readpbmrow( ifp, bitrow, cols, format );
-	for ( col = 0; col < padleft; ++col )
-	    putbit( 0 );
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-	    putbit( *bP );
-	for ( col = 0; col < padright; ++col )
-	    putbit( 0 );
-        }
+        rc = fprintf(putFp,
+                     "\t0x%04x,0x%04x,0x%04x,0x%04x,"
+                     "0x%04x,0x%04x,0x%04x,0x%04x,\n",
+                     itemBuff[0],itemBuff[1],itemBuff[2],itemBuff[3],
+                     itemBuff[4],itemBuff[5],itemBuff[6],itemBuff[7]);
+        if (rc < 0)        
+           pm_error("fprintf() failed to write Icon bitmap");
+           
+        itemCnt = 0;
+    }
+    itemBuff[itemCnt++] = item & 0xffff;  /* Only lower 16 bits are used */
+}
 
-    pm_close( ifp );
 
-    putrest( );
 
-    exit( 0 );
-    }
+static void
+putterm(void) {
 
-static int item, bitsperitem, bitshift, itemsperline, firstitem;
+    unsigned int i;
 
-static void
-putinit( )
-    {
-    itemsperline = 0;
-    bitsperitem = 0;
-    item = 0;
-    bitshift = 15;
-    firstitem = 1;
+    for (i = 0; i < itemCnt; ++i) {
+        int rc;
+        rc = fprintf(putFp, "%s0x%04x%c", i == 0  ? "\t" : "", itemBuff[i],
+                     i == itemCnt - 1 ? '\n' : ',');
+        if (rc < 0)        
+            pm_error("fprintf() failed to write Icon bitmap");
     }
+}     
+
+
 
-#if __STDC__
-static void
-putbit( bit b )
-#else /*__STDC__*/
 static void
-putbit( b )
-bit b;
-#endif /*__STDC__*/
-    {
-    if ( bitsperitem == 16 )
-	putitem( );
-    ++bitsperitem;
-    if ( b == PBM_BLACK )
-	item += 1 << bitshift;
-    --bitshift;
-    }
+writeIconHeader(FILE *       const ofP,
+                unsigned int const width,
+                unsigned int const height) {
+
+    int rc;
+
+    rc = fprintf(ofP,
+                 "/* Format_version=1, Width=%u, Height=%u", width, height);
+    if (rc < 0)
+        pm_error("fprintf() failed to write Icon header");
+        
+    rc = fprintf(ofP, ", Depth=1, Valid_bits_per_item=16\n */\n");
+    if (rc < 0)
+        pm_error("fprintf() failed to write Icon header");
+}
+
+
 
 static void
-putrest( )
-    {
-    if ( bitsperitem > 0 )
-	putitem( );
-    putchar( '\n' );
+writeIcon(FILE *       const ifP,
+          unsigned int const cols,
+          unsigned int const rows,
+          int          const format,
+          FILE *       const ofP) {
+
+    unsigned int const wordintSize = sizeof(wordint) * 8;
+        /* wordintSize is usually 32 or 64 bits.  Must be at least 24. */
+    unsigned int const items = (cols + 15) / 16;
+    unsigned int const bitrowBytes = pbm_packed_bytes(cols);
+    unsigned int const pad = items * 16 - cols;
+    /* 'padleft' is added to the output.  'padbyte' is for cleaning
+       the input
+    */
+    unsigned int const padleft = pad / 2;
+    unsigned int const padbyte = bitrowBytes * 8 - cols;
+    unsigned int const shift   = (wordintSize - 24) + padleft;
+    
+    unsigned char * bitbuffer;
+    unsigned char * bitrow;
+    unsigned int row;
+
+    bitbuffer = pbm_allocrow_packed(cols + wordintSize);
+    bitrow = &bitbuffer[1];
+    bitbuffer[0] = 0;
+    bitrow[bitrowBytes] = 0;
+    
+    writeIconHeader(ofP, cols + pad, rows);
+
+    putinit(ofP);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int itemSeq;
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+
+        /* Clear post-data junk in final partial byte */
+        if (padbyte > 0) {
+            bitrow[bitrowBytes-1] >>= padbyte;
+            bitrow[bitrowBytes-1] <<= padbyte;
+        }
+        
+        for (itemSeq = 0; itemSeq < items; ++itemSeq) {
+            /* Scoop up bits, shift-align, send to format & print function.
+    
+               An item is 16 bits, typically spread over 3 bytes due to
+               left-padding.  We use wordint here to scoop up 4 (or more)
+               consecutive bytes.  An item always resides within the higher
+               24 bits of each scoop.  It is essential to use wordint
+               (or rather the wordaccess function bytesToWordInt() ); 
+               simple long, uint_32t, etc. do not work for they are not
+               shift-tolerant.
+            */
+            
+            wordint const scoop = bytesToWordint(&bitbuffer[itemSeq*2]);
+            putitem (scoop >> shift);
+        }
     }
+    putterm();    
+}
 
-static void
-putitem( )
-    {
-    const char* hexits = "0123456789abcdef";
 
-    if ( firstitem )
-	firstitem = 0;
+
+int
+main(int argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    int rows, cols;
+    int format;
+    const char * inputFileName;
+
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
     else
-	putchar( ',' );
-    if ( itemsperline == 8 )
-	{
-	putchar( '\n' );
-	itemsperline = 0;
-	}
-    if ( itemsperline == 0 )
-	putchar( '\t' );
-    putchar( '0' );
-    putchar( 'x' );
-    putchar( hexits[item >> 12] );
-    putchar( hexits[( item >> 8 ) & 15] );
-    putchar( hexits[( item >> 4 ) & 15] );
-    putchar( hexits[item & 15] );
-    ++itemsperline;
-    bitsperitem = 0;
-    item = 0;
-    bitshift = 15;
-    }
+        inputFileName = "-";
+    
+    ifP = pm_openr(inputFileName);
+
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+
+    writeIcon(ifP, cols, rows, format, stdout);
+
+    pm_close(ifP);
+
+    return 0;
+}
+
diff --git a/converter/pbm/pbmtolj.c b/converter/pbm/pbmtolj.c
index e8373050..be28f635 100644
--- a/converter/pbm/pbmtolj.c
+++ b/converter/pbm/pbmtolj.c
@@ -27,6 +27,7 @@
 ** implied warranty.
 */
 
+#include "pm_c_util.h"
 #include "pbm.h"
 #include "shhopt.h"
 #include "mallocvar.h"
diff --git a/converter/pbm/pbmtoln03.c b/converter/pbm/pbmtoln03.c
index 07c8629f..f7cf53c7 100644
--- a/converter/pbm/pbmtoln03.c
+++ b/converter/pbm/pbmtoln03.c
@@ -219,13 +219,8 @@ main (int argc, char **argv) {
    if( argn != argc )
       pm_usage(usage);
 
-
-   /* Initialize pbm file */
    pbm_readpbminit (input, &width, &height, &format) ;
 
-   if (format != PBM_FORMAT && format != RPBM_FORMAT)
-      pm_error ("input not in PBM format") ;
-
 /*
  * In explanation of the sequence below:
  *      <ESC>[!p        DECSTR  soft terminal reset
diff --git a/converter/pbm/pbmtolps.c b/converter/pbm/pbmtolps.c
index 13a14e2b..5adef4c8 100644
--- a/converter/pbm/pbmtolps.c
+++ b/converter/pbm/pbmtolps.c
@@ -112,7 +112,7 @@ main(int argc, char ** argv) {
 	pbm_init(&argc, argv);
 
     i = 1;
-    if (i < argc && STREQ(argv[i], "-dpi")) {
+    if (i < argc && streq(argv[i], "-dpi")) {
         if (i == argc - 1)
             pm_usage(usage);
         sscanf(argv[i + 1], "%f", &dpi);
diff --git a/converter/pbm/pbmtomgr.c b/converter/pbm/pbmtomgr.c
index acf689e1..d12e6635 100644
--- a/converter/pbm/pbmtomgr.c
+++ b/converter/pbm/pbmtomgr.c
@@ -1,124 +1,127 @@
-/* pbmtomgr.c - read a portable bitmap and produce a MGR bitmap
-**
-** Copyright (C) 1989 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
+/* pbmtomgr.c - read a PBM image and produce a MGR bitmap
+
+   Copyright information is at end of file.
+
+   You can find MGR and some MGR format test images at
+   ftp://sunsite.unc.edu/pub/Linux/apps/MGR/!INDEX.html
 */
 
+#include <assert.h>
 #include "pbm.h"
 #include "mgr.h"
 
-static void putinit ARGS(( int rows, int cols ));
-static void putbit ARGS(( bit b ));
-static void putrest ARGS(( void ));
-static void putitem ARGS(( void ));
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, format, padright, row, col;
 
+static void
+putinit(unsigned int const rows,
+        unsigned int const cols) {
 
-    pbm_init( &argc, argv );
+    struct b_header head;
+    size_t writtenCount;
+
+    /* Because of argument restrictions: maximum dimensions: */
+    assert((rows & 0xfff) == rows);
+    assert((cols & 0xfff) == cols);
+
+    head.magic[0] = 'y';
+    head.magic[1] = 'z';
+    head.h_wide = ((cols >> 6) & 0x3f) + ' ';
+    head.l_wide = (cols & 0x3f) + ' ';
+    head.h_high = (( rows >> 6) & 0x3f) + ' ';
+    head.l_high = (rows & 0x3f) + ' ';
+    head.depth = (1 & 0x3f) + ' ';
+    head._reserved = ' ';
+    writtenCount = fwrite(&head, sizeof(head), 1, stdout);
+    if (writtenCount != 1)
+        pm_error("fwrite() failed to write the MGR header.");    
+}
 
-    if ( argc > 2 )
-	pm_usage( "[pbmfile]" );
 
-    if ( argc == 2 )
-	ifp = pm_openr( argv[1] );
+
+int
+main(int argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    unsigned char * bitrow;
+    int rows;
+    int cols;
+    int format;
+    unsigned int row;
+    unsigned int bytesPerRow;
+        /* Number of packed bytes (8 columns per byte) in a row. */
+    unsigned int padright;
+        /* Number of columns added to the right of each row to get up to
+           a multiple of 8, i.e. an integral number of packed bytes.
+        */
+    const char * inputFileName;
+    unsigned int const maxDimension = 4095;
+        /* Dimensions are 2 characters of the header -- 12 bits */
+
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  "
+                 "Only argument is optional input file", argc-1);
+    if (argc-1 == 1)
+        inputFileName = argv[1];
     else
-	ifp = stdin;
-
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    if (cols > 4095)
-        pm_error("Image width too large: %u (max: 4095)", cols);
-    if (rows > 4095)
-        pm_error("Image heigth too large: %u (max: 4095)", cols);
-    bitrow = pbm_allocrow( cols );
+        inputFileName = "-";
     
-    /* Round cols up to the nearest multiple of 8. */
-    padright = ( ( cols + 7 ) / 8 ) * 8 - cols;
-
-    putinit( rows, cols );
-    for ( row = 0; row < rows; ++row )
-	{
-	pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-	    putbit( *bP );
-	for ( col = 0; col < padright; ++col )
-	    putbit( 0 );
-        }
+    ifP = pm_openr(inputFileName);
 
-    pm_close( ifp );
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+    if (cols > maxDimension)
+        pm_error("Image width too large: %u (max: %u)", cols, maxDimension);
+    if (rows > maxDimension)
+        pm_error("Image height too large: %u (max: %u)", rows, maxDimension);
+    
+    bitrow = pbm_allocrow_packed(cols);
+    bytesPerRow = pbm_packed_bytes(cols);
+    padright = bytesPerRow * 8 - cols;
 
-    putrest( );
+    putinit(rows, cols);
+    
+    for (row = 0; row < rows; ++row) {
+        /* The raster formats are identical. 
+           The row end pad bits are set to 0 in mgr.
+        */
+        size_t bytesWritten;
+
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+        
+        if (padright > 0) {
+            bitrow[bytesPerRow-1] >>= padright;
+            bitrow[bytesPerRow-1] <<= padright;
+        }
 
-    exit( 0 );
+        bytesWritten = fwrite(bitrow, 1, bytesPerRow, stdout);
+        if (bytesWritten != bytesPerRow )
+            pm_error("fwrite() failed to write MGR bitmap "
+                     "to Standard Output.");    
     }
+    pm_close(ifP);
+    return 0;
+}
 
-static unsigned char item;
-static int bitsperitem, bitshift;
 
-static void
-putinit( rows, cols )
-    int rows, cols;
-    {
-    struct b_header head;
 
-    head.magic[0] = 'y';
-    head.magic[1] = 'z';
-    head.h_wide = ( ( cols >> 6 ) & 0x3f ) + ' ';
-    head.l_wide = ( cols & 0x3f ) + ' ';
-    head.h_high = ( ( rows >> 6 ) & 0x3f ) + ' ';
-    head.l_high = ( rows & 0x3f ) + ' ';
-    head.depth = ( 1 & 0x3f ) + ' ';
-    head._reserved = ' ';
-    fwrite( &head, sizeof(head), 1, stdout );
-
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
-    }
+/* 2006.10 (afu)
+   Changed bitrow from plain to raw, read function from pbm_readpbmrow() to
+   pbm_readpbmrow_packed(), write function from putc() to fwrite().
 
-#if __STDC__
-static void
-putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
-    {
-    if ( bitsperitem == 8 )
-	putitem( );
-    ++bitsperitem;
-    if ( b == PBM_BLACK )
-	item += 1 << bitshift;
-    --bitshift;
-    }
-
-static void
-putrest( )
-    {
-    if ( bitsperitem > 0 )
-	putitem( );
-    }
+   Retired bitwise transformation functions.
+   
+   Produces only new style bitmap (8 bit padding.)  See mgrtopbm.c .
+*/
 
-static void
-putitem( )
-    {
-    fwrite( &item, sizeof(item), 1, stdout );
-    item = 0;
-    bitsperitem = 0;
-    bitshift = 7;
-    }
+/*
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+*/
diff --git a/converter/pbm/pbmtomrf.c b/converter/pbm/pbmtomrf.c
index c93c88aa..e7b7fcc9 100644
--- a/converter/pbm/pbmtomrf.c
+++ b/converter/pbm/pbmtomrf.c
@@ -13,83 +13,139 @@
 #include "pm_c_util.h"
 #include "pbm.h"
 
-static int bitbox;
-static int bitsleft;
 
-static FILE *bit_out;
+
+typedef struct bitOut {
+    int bitbox;
+    int bitsleft;
+    FILE * fileP;
+} bitOut;
+
 
 
 static void 
-bit_init(FILE * const out) {
-    bitbox = 0; 
-    bitsleft = 8;
-    bit_out = out;
+bit_init(struct bitOut * const bitOutP,
+         FILE *          const ofP) {
+
+    bitOutP->bitbox = 0; 
+    bitOutP->bitsleft = 8;
+    bitOutP->fileP = ofP;
 }
 
 
 
 static void 
-bit_output(int const bit) {
-    --bitsleft;
-    bitbox |= (bit << bitsleft);
-    if (bitsleft == 0) {
-        fputc(bitbox, bit_out);
-        bitbox = 0;
-        bitsleft = 8;
+bit_output(struct bitOut * const bitOutP,
+           int             const bit) {
+
+    --bitOutP->bitsleft;
+    bitOutP->bitbox |= (bit << bitOutP->bitsleft);
+    if (bitOutP->bitsleft == 0) {
+        fputc(bitOutP->bitbox, bitOutP->fileP);
+        bitOutP->bitbox = 0;
+        bitOutP->bitsleft = 8;
     }
 }
 
 
 
 static void 
-bit_flush(void) {
+bit_flush(struct bitOut * const bitOutP) {
     /* there are never 0 bits left outside of bit_output, but
      * if 8 bits are left here there's nothing to flush, so
      * only do it if bitsleft!=8.
      */
-    if (bitsleft != 8) {
-        bitsleft = 1;
-        bit_output(0);    /* yes, really. This will always work. */
+    if (bitOutP->bitsleft != 8) {
+        bitOutP->bitsleft = 1;
+        bit_output(bitOutP, 0);    /* yes, really. This will always work. */
     }
 }
 
 
 
-static void 
-doSquare(unsigned char * const image,
-         int             const ox,
-         int             const oy,
-         int             const w,
-         int             const size) {
-
-    unsigned int y;
+static void
+determineBlackWhiteOrMix(const unsigned char * const image,
+                         unsigned int          const ulCol,
+                         unsigned int          const ulRow,
+                         unsigned int          const imageWidth,
+                         unsigned int          const size,
+                         bool *                const oneColorP,
+                         int *                 const colorP) {
+/*----------------------------------------------------------------------------
+   Determine whether a square within 'image' is all white, all black,
+   or a mix.
+-----------------------------------------------------------------------------*/
+    unsigned int rowOfSquare;
     unsigned int t;
 
-    /* check square to see if it's all black or all white. */
+    for (rowOfSquare = 0, t = 0; rowOfSquare < size; ++rowOfSquare) {
+        unsigned int colOfSquare;
+        for (colOfSquare = 0; colOfSquare < size; ++colOfSquare) {
+            unsigned int rowOfImage = ulRow + rowOfSquare;
+            unsigned int colOfImage = ulCol + colOfSquare;
 
-    t = 0;
-    for (y = 0; y < size; ++y) {
-        unsigned int x;
-        for (x = 0; x < size; ++x)
-            t += image[(oy+y)*w + ox + x];
+            t += image[rowOfImage * imageWidth + colOfImage];
+        }
     }        
     /* if the total's 0, it's black. if it's size*size, it's white. */
-    if (t == 0 || t == size*size) {
-        if (size != 1)     /* (it's implicit when size is 1, of course) */
-            bit_output(1);  /* all same color */
-        bit_output(t?1:0);
-        return;
-    }
-    
-    /* otherwise, if our square is greater than 1x1, we need to recurse. */
-    if(size > 1) {
-        int halfsize = size >> 1;
-
-        bit_output(0);    /* not all same */
-        doSquare(image, ox,          oy,          w, halfsize);
-        doSquare(image, ox+halfsize, oy,          w, halfsize);
-        doSquare(image, ox,          oy+halfsize, w, halfsize);
-        doSquare(image, ox+halfsize, oy+halfsize, w, halfsize);
+    if (t == 0) {
+        *oneColorP = TRUE;
+        *colorP = 0;
+    } else if (t == SQR(size)) {
+        *oneColorP = TRUE;
+        *colorP = 1;
+    } else
+        *oneColorP = FALSE;
+}
+
+
+
+static void 
+doSquare(bitOut *              const bitOutP,
+         const unsigned char * const image,
+         unsigned int          const ulCol,
+         unsigned int          const ulRow,
+         unsigned int          const imageWidth,
+         unsigned int          const size) {
+/*----------------------------------------------------------------------------
+   Do a square of side 'size', whose upper left corner is at (ulCol, ulRow).
+   This is a square within 'image', which is a concatenation of rows
+   'imageWidth' pixels wide, one byte per pixel.
+
+   Write the pixel values out to the bit stream *bitOutP, in MRF format.
+-----------------------------------------------------------------------------*/
+    if (size == 1) {
+        /* The fact that it is all one color is implied because the square is
+           just one pixel; no bit goes in MRF output to state that.
+        */
+        bit_output(bitOutP, image[ulRow * imageWidth + ulCol] ? 1 : 0);
+    } else {
+        bool oneColor;
+        int color;
+
+        determineBlackWhiteOrMix(image, ulCol, ulRow, imageWidth, size,
+                                 &oneColor, &color);
+
+        if (oneColor) {
+            bit_output(bitOutP, 1);  /* all same color */
+            bit_output(bitOutP, color);
+        } else {
+            /* Square is not all the same color, so recurse.  Do each
+               of the four quadrants of this square individually.
+            */
+            unsigned int const quadSize = size/2;
+
+            bit_output(bitOutP, 0);    /* not all same color */
+
+            doSquare(bitOutP, image, ulCol,            ulRow,
+                     imageWidth, quadSize);
+            doSquare(bitOutP, image, ulCol + quadSize, ulRow,
+                     imageWidth, quadSize);
+            doSquare(bitOutP, image, ulCol,            ulRow + quadSize,
+                     imageWidth, quadSize);
+            doSquare(bitOutP, image, ulCol + quadSize, ulRow + quadSize,
+                     imageWidth, quadSize);
+        }
     }
 }
     
@@ -243,7 +299,7 @@ readPbmImage(FILE *           const ifP,
         pm_error("Ridiculously large, unprocessable image: %u cols x %u rows",
                  cols, rows);
 
-    image = calloc(w64*h64*64*64,1);
+    image = calloc(w64*h64*64*64, 1);
     if (image == NULL)
         pm_error("Unable to get memory for raster");
                  
@@ -276,6 +332,8 @@ outputMrf(FILE *          const ofP,
     unsigned int const w64 = (cols + 63) / 64;
     unsigned int const h64 = (rows + 63) / 64;
 
+    bitOut bitOut;
+
     unsigned int row;
 
     fprintf(ofP, "MRF1");
@@ -285,14 +343,14 @@ outputMrf(FILE *          const ofP,
     
     /* now recursively check squares. */
 
-    bit_init(ofP);
+    bit_init(&bitOut, ofP);
 
     for (row = 0; row < h64; ++row) {
         unsigned int col;
         for (col = 0; col < w64; ++col)
-            doSquare(image, col*64, row*64, w64*64, 64);
+            doSquare(&bitOut, image, col*64, row*64, w64*64, 64);
     }
-    bit_flush();
+    bit_flush(&bitOut);
 }
 
 
diff --git a/converter/pbm/pbmtonokia.c b/converter/pbm/pbmtonokia.c
index 214958c5..b8057393 100644
--- a/converter/pbm/pbmtonokia.c
+++ b/converter/pbm/pbmtonokia.c
@@ -1,231 +1,527 @@
-/* pbmtonokia.c - convert a portable bitmap to Nokia Smart Messaging
+/* pbmtonokia.c - convert a PBM image to Nokia Smart Messaging
    Formats (NOL, NGG, HEX)
 
-** Copyright (C)2001 OMS Open Media System GmbH, Tim Rühsen
-** <tim.ruehsen@openmediasystem.de>.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
+   Copyright information is at end of file.
+*/
 
-History
-  07.06.2001 Created
-  20.11.2001 Handle Picture Messages
-             new option -txt to embed text into Picture Messages
-             new option -net to specify operator network code for 
-                Nokia Operator Logos
+#define _BSD_SOURCE    /* Make sure strcaseeq() is in nstring.h */
+#include <string.h>
+#include <assert.h>
 
-Notes:
-  - limited to rows <= 255 and columns <= 255
-  - limited to b/w graphics, not animated
+#include "pm_c_util.h"
+#include "nstring.h"
+#include "mallocvar.h"
+#include "shhopt.h"
+#include "pbm.h"
 
-Testing:
-  Testing was done with SwissCom SMSC (Switzerland) and IC3S SMSC (Germany).
-  The data was send with EMI/UCP protocol over TCP/IP.
+enum outputFormat {
+    FMT_HEX_NOL,
+    FMT_HEX_NGG,
+    FMT_HEX_NPM,
+    FMT_NOL,
+    FMT_NGG,
+    FMT_NPM
+};
 
-  - 7.6.2001: tested with Nokia 3210: 72x14 Operator Logo
-  - 7.6.2001: tested with Nokia 6210: 72x14 Operator Logo and 
-              72x14 Group Graphic
 
-Todo:
-  - more testing
-  - sendsms compatibility ?
-  - are -fmt NOL and -fmt NGG working ok?  */
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileName;  /* Filename of input files */
+    int outputFormat;
+    const char * networkCode;
+    const char * txt;  /* NULL means unspecified */
+};
 
-#define _BSD_SOURCE    /* Make sure strcasecmp() is in string.h */
-#include <string.h>
 
-#include "nstring.h"
-#include "pbm.h"
 
-#define FMT_HEX_NOL   1
-#define FMT_HEX_NGG   2
-#define FMT_HEX_NPM   3
-#define FMT_NOL       4
-#define FMT_NGG       5
-
-static void 
-usage(char *myname)
-{
-    pm_message("Copyright (C)2001 OMS GmbH");
-    pm_message("Contact: Tim Ruehsen <tim.ruehsen@openmediasystem.de>\n");
-    pm_usage("[options] [pbmfile]\n"
-             "  Options:\n"
-             "    -fmt <HEX_NOL|HEX_NGG|HEX_NPM|NOL|NGG>  "
-             "Output format (default=HEX_NOL)\n"
-             "    -net <network code>                     "
-             "Network code for NOL operator logos\n"
-             "    -txt <text message>                     "
-             "Text for NPM picture messages\n");
-
-    exit(1);
+static const char *
+uppercase(const char * const subject) {
+
+    char * buffer;
+
+    buffer = malloc(strlen(subject) + 1);
+
+    if (buffer == NULL)
+        pm_error("Out of memory allocating buffer for uppercasing a "
+                 "%u-character string", strlen(subject));
+    else {
+        unsigned int i;
+
+        i = 0;
+        while (subject[i]) {
+            buffer[i] = TOUPPER(subject[i]);
+            ++i;
+        }
+        buffer[i] = '\0';
+    }
+    return buffer;
+}
+
+
+
+static void
+parseCommandLine(int argc, char ** argv,
+                 struct cmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that the file spec array we return is stored in the storage that
+   was passed to us as the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;
+        /* Instructions to optParseOptions3 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+    unsigned int fmtSpec, netSpec, txtSpec;
+    const char * fmtOpt;
+    const char * netOpt;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0, "fmt",     OPT_STRING, &fmtOpt, 
+            &fmtSpec, 0);
+    OPTENT3(0, "net",     OPT_STRING, &netOpt,
+            &netSpec, 0);
+    OPTENT3(0, "txt",     OPT_STRING, &cmdlineP->txt,
+            &txtSpec, 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 */
+
+    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (fmtSpec) {
+        if (strcaseeq(fmtOpt, "HEX_NOL"))
+            cmdlineP->outputFormat = FMT_HEX_NOL;
+        else if (strcaseeq(fmtOpt, "HEX_NGG"))
+            cmdlineP->outputFormat = FMT_HEX_NGG;
+        else if (strcaseeq(fmtOpt, "HEX_NPM"))
+            cmdlineP->outputFormat = FMT_HEX_NPM;
+        else if (strcaseeq(fmtOpt, "NOL"))
+            cmdlineP->outputFormat = FMT_NOL;
+        else if (strcaseeq(fmtOpt, "NGG"))
+            cmdlineP->outputFormat = FMT_NGG;
+        else if (strcaseeq(fmtOpt, "NPM"))
+            cmdlineP->outputFormat = FMT_NPM;
+        else
+            pm_error("-fmt option must be HEX_NGG, HEX_NOL, HEX_NPM, "
+                     "NGG, NOL or NPM.  You specified '%s'", fmtOpt);
+    } else
+        cmdlineP->outputFormat = FMT_HEX_NOL;
+
+    if (netSpec) {
+        if (strlen(netOpt) != 6)
+            pm_error("-net option must be 6 hex digits long.  "
+                     "You specified %u characters", strlen(netOpt));
+        else if (!strishex(netOpt))
+            pm_error("-net option must be hexadecimal.  You specified '%s'",
+                     netOpt);
+        else
+            cmdlineP->networkCode = uppercase(netOpt);
+    } else
+        cmdlineP->networkCode = strdup("62F210");  /* German D1 net */
+
+    if (!txtSpec)
+        cmdlineP->txt = NULL;
+    else if (strlen(cmdlineP->txt) > 120)
+        pm_error("Text message is longer (%u characters) than "
+                 "the 120 characters allowed by the format.",
+                 strlen(cmdlineP->txt));
+
+    if (argc-1 == 0) 
+        cmdlineP->inputFileName = "-";
+    else if (argc-1 != 1)
+        pm_error("Program takes zero or one argument (filename).  You "
+                 "specified %u", argc-1);
+    else
+        cmdlineP->inputFileName = argv[1];
 }
 
-int 
-main(int argc, char *argv[])
-{
-    FILE    *fp;
-    bit    **image;
-    unsigned int    c;
-    int    argpos, output=FMT_HEX_NOL, rows, cols, row, col, p, it, len;
-    char    header[32], *myname;
-    char    network_code[6+1];
-    char    *text=NULL;
-
-    if ((myname=strrchr(argv[0],'/'))!=NULL) myname++; else myname=argv[0];
 
-    pbm_init(&argc, argv);
 
-    strcpy(network_code, "62F210"); /* default is German D1 net */
-
-    for(argpos=1;argpos<argc;argpos++) {
-        if (argv[argpos][0]=='-') {
-            if (argv[argpos][1]=='-') {
-                if (argc>argpos+1 && ISDIGIT(argv[argpos+1][0]))
-                    {argpos++;break;}
-            } else if (STREQ(argv[argpos],"-fmt") && argc>argpos+1) {
-                ++argpos;
-                if (!strcasecmp(argv[argpos],"HEX_NOL")) output=FMT_HEX_NOL;
-                else if (!strcasecmp(argv[argpos],"HEX_NGG")) 
-                    output=FMT_HEX_NGG;
-                else if (!strcasecmp(argv[argpos],"HEX_NPM")) 
-                    output=FMT_HEX_NPM;
-                else if (!strcasecmp(argv[argpos],"NOL")) output=FMT_NOL;
-                else if (!strcasecmp(argv[argpos],"NGG")) output=FMT_NGG;
-                else usage(myname);
-            } else if (STREQ(argv[argpos],"-net") && argc>argpos+1) {
-                char * const network_code_arg=argv[++argpos];
-                unsigned int it;
-                len=strlen(network_code_arg);
-                if (len!=6) 
-                    pm_error("Network code must be 6 hex-digits long");
-                for (it=0;it<strlen(network_code_arg);it++) {
-                    if (!ISXDIGIT(network_code_arg[it])) 
-                        pm_error("Network code must contain hex-digits only");
-                    network_code[it]=TOUPPER(network_code_arg[it]);
-                }
-                network_code[it] = '\0';
-            } else if (STREQ(argv[argpos],"-txt") && argc>argpos+1) {
-                text=argv[++argpos];
+static void
+freeCmdline(struct cmdlineInfo const cmdline) {
+
+    strfree(cmdline.networkCode);
+}
+
+
+
+static void
+validateSize(unsigned int const cols,
+             unsigned int const rows){
+
+    if (cols > 255)
+        pm_error("This program cannot handle files with more than 255 "
+                 "columns");
+    if (rows > 255)
+        pm_error("This program cannot handle files with more than 255 "
+                 "rows");
+}
+
+
+
+
+static void
+convertToHexNol(bit **       const image,
+                unsigned int const cols,
+                unsigned int const rows,
+                const char * const networkCode,
+                FILE *       const ofP) {
+
+    unsigned int row;
+
+    /* header */
+    fprintf(ofP, "06050415820000%s00%02X%02X01", networkCode, cols, rows);
+    
+    /* image */
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        unsigned int p;
+        unsigned int c;
+
+        c = 0;
+
+        for (p = 0, col = 0; col < cols; ++col) {
+            if (image[row][col] == PBM_BLACK)
+                c |= 0x80 >> p;
+            if (++p == 8) {
+                fprintf(ofP, "%02X",c);
+                p = c = 0;
             }
-            else usage(myname);
-        } else break;
+        }
+        if (p > 0)
+            fprintf(ofP, "%02X", c);
     }
+}
 
-    if (argpos==argc) {
-        image = pbm_readpbm(stdin, &cols, &rows);
-    } else {
-        fp=pm_openr(argv[argpos]);
-        image = pbm_readpbm(fp, &cols, &rows);
-        pm_close(fp);
-    }
 
-    memset(header,0,sizeof(header));
 
-    switch (output) {
-    case FMT_HEX_NOL:
-        /* header */
-        printf("06050415820000%s00%02X%02X01",network_code,cols,rows);
-
-        /* image */
-        for (row=0;row<rows;row++) {
-            for (p=c=col=0;col<cols;col++) {
-                if (image[row][col]==PBM_BLACK) c|=0x80>>p;
-                if (++p==8) {
-                    printf("%02X",c);
-                    p=c=0;
-                }
+static void
+convertToHexNgg(bit **       const image,
+                unsigned int const cols,
+                unsigned int const rows,
+                FILE *       const ofP) {
+
+    unsigned int row;
+
+    /* header */
+    fprintf(ofP, "0605041583000000%02X%02X01", cols, rows);
+
+    /* image */
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        unsigned int p;
+        unsigned int c;
+
+        for (p = 0, c = 0, col = 0; col < cols; ++col) {
+            if (image[row][col] == PBM_BLACK)
+                c |= 0x80 >> p;
+            if (++p == 8) {
+                fprintf(ofP, "%02X", c);
+                p = c = 0;
             }
-            if (p) printf("%02X",c);
         }
-        break;
-    case FMT_HEX_NGG:
-        /* header */
-        printf("0605041583000000%02X%02X01",cols,rows);
-
-        /* image */
-        for (row=0;row<rows;row++) {
-            for (p=c=col=0;col<cols;col++) {
-                if (image[row][col]==PBM_BLACK) c|=0x80>>p;
-                if (++p==8) {
-                    printf("%02X",c);
-                    p=c=0;
-                }
+        if (p > 0)
+            fprintf(ofP, "%02X", c);
+    }
+}
+
+
+
+
+static void
+convertToHexNpm(bit **       const image,
+                unsigned int const cols,
+                unsigned int const rows,
+                const char * const text,
+                FILE *       const ofP) {
+
+    unsigned int row;
+    
+    /* header */
+    fprintf(ofP, "060504158A0000");
+
+    /* text */
+    if (text) {
+        size_t const len = strlen(text);
+
+        unsigned int it;
+
+        fprintf(ofP, "00%04X", len);
+
+        for (it = 0; it < len; ++it)
+            fprintf(ofP, "%02X", text[it]);
+    }
+
+    /* image */
+    fprintf(ofP, "02%04X00%02X%02X01", (cols * rows) / 8 + 4, cols, rows);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        unsigned int p;
+        unsigned int c;
+
+        for (p = 0, c = 0, col = 0; col < cols; ++col) {
+            if (image[row][col] == PBM_BLACK)
+                c |= 0x80 >> p;
+            if (++p == 8) {
+                fprintf(ofP, "%02X", c);
+                p = c = 0;
             }
-            if (p) printf("%02X",c);
         }
-        break;
-    case FMT_HEX_NPM:
-        /* header */
-        printf("060504158A0000");
+        if (p > 0)
+            fprintf(ofP, "%02X", c);
+    }
+}
+
+
+
+static void
+convertToNol(bit **       const image,
+             unsigned int const cols,
+             unsigned int const rows,
+             FILE *       const ofP) {
+
+    unsigned int row;
+    char header[32];
+    unsigned int it;
+    
+    /* header - this is a hack */
+
+    header[ 0] = 'N';
+    header[ 1] = 'O';
+    header[ 2] = 'L';
+    header[ 3] = 0;
+    header[ 4] = 1;
+    header[ 5] = 0;
+    header[ 6] = 4;
+    header[ 7] = 1;
+    header[ 8] = 1;
+    header[ 9] = 0;
+    header[10] = cols;
+    header[11] = 0;
+    header[12] = rows;
+    header[13] = 0;
+    header[14] = 1;
+    header[15] = 0;
+    header[16] = 1;
+    header[17] = 0;
+    header[18] = 0x53;
+    header[19] = 0;
 
-        /* text */
-        if (text!=NULL) {
-            printf("00%04X",(len=strlen(text)));
-            for (it=0;it<len;it++) printf("%02X",text[it]);
+    fwrite(header, 20, 1, ofP);
+    
+    /* image */
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        unsigned int p;
+        unsigned int c;
+
+        for (p = 0, c = 0, col = 0; col < cols; ++col) {
+            char const output = image[row][col] == PBM_BLACK ? '1' : '0';
+
+            putc(output, ofP);
         }
+    }
 
-        /* image */
-        printf("02%04X00%02X%02X01",(cols*rows)/8+4,cols,rows);
-        for (row=0;row<rows;row++) {
-            for (p=c=col=0;col<cols;col++) {
-                if (image[row][col]==PBM_BLACK) c|=0x80>>p;
-                if (++p==8) {
-                    printf("%02X",c);
-                    p=c=0;
-                }
-            }
-            if (p) printf("%02X",c);
+    /* padding (to keep gnokii happy) */
+    for (it = 0; it < 8 - cols * rows % 8; ++it)
+        putc('0', ofP);
+}
+
+
+
+
+static void
+convertToNgg(bit **       const image,
+             unsigned int const cols,
+             unsigned int const rows,
+             FILE *       const ofP) {
+
+    unsigned int row;
+    char    header[32];
+    unsigned int it;
+
+    /* header - this is a hack */
+
+    header[ 0] = 'N';
+    header[ 1] = 'G';
+    header[ 2] = 'G';
+    header[ 3] = 0;
+    header[ 4] = 1;
+    header[ 5] = 0;
+    header[ 6] = cols;
+    header[ 7] = 0;
+    header[ 8] = rows;
+    header[ 9] = 0;
+    header[10] = 1;
+    header[11] = 0;
+    header[12] = 1;
+    header[13] = 0;
+    header[14] = 0x4a;
+    header[15] = 0;
+
+    fwrite(header, 16, 1, ofP);
+    
+    /* image */
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        unsigned int p;
+        unsigned int c;
+
+        for (p = 0, c = 0, col = 0; col < cols; ++col) {
+            char const output = image[row][col] == PBM_BLACK ? '1' : '0';
+
+            putc(output, ofP);
         }
-        break;
-    case FMT_NOL:
-        /* header - this is a hack */
-        header[0]='N';
-        header[1]='O';
-        header[2]='L';
-        header[4]=header[7]=header[8]=header[14]=header[16]=1;
-        header[6]=4;
-        header[10]=cols;
-        header[12]=rows;
-        header[18]=0x53;
-        fwrite(header,20,1,stdout);
-
-        /* image */
-        for (row=0;row<rows;row++) {
-            for (p=c=col=0;col<cols;col++) {
-                if (image[row][col]==PBM_BLACK) putchar('1');
-                else putchar('0');
+    }
+
+    /* padding (to keep gnokii happy) */
+    for (it = 0; it < 8 - cols * rows % 8; ++it)
+        putc('0', ofP);
+}
+
+
+
+static void
+convertToNpm(bit **       const image,
+             unsigned int const cols,
+             unsigned int const rows,
+             const char * const text,
+             FILE *       const ofP) {
+
+    unsigned int row;
+    char header[132];
+    size_t len;
+
+    if (text) 
+        len = strlen(text);
+    else
+        len = 0;
+
+    /* header and optional text */
+
+    header[       0] = 'N';
+    header[       1] = 'P';
+    header[       2] = 'M';
+    header[       3] = 0;
+    header[       4] = len;
+    header[       5] = 0;
+    memcpy(&header[5], text, len);
+    header[ 6 + len] = cols;
+    header[ 7 + len] = rows;
+    header[ 8 + len] = 1;
+    header[ 9 + len] = 1;
+    header[10 + len] = 0; /* unknown */
+
+    assert(10 + len < sizeof(header));
+
+    fwrite(header, 11 + len, 1, ofP);
+    
+    /* image: stream of bits, each row padded to a byte boundary
+       inspired by gnokii/common/gsm-filesystems.c
+     */
+    for (row = 0; row < rows; row++) {
+        unsigned int byteNumber;
+        int bitNumber;
+        char buffer[32];  /* picture messages are (always?) 72 x 28 */
+        unsigned int col;
+
+        byteNumber = 0;
+        bitNumber = 7;
+
+        memset(buffer, 0, sizeof(buffer));
+
+        for (col = 0; col < cols; ++col) {
+            if (image[row][col] == PBM_BLACK)
+                buffer[byteNumber] |= (1 << bitNumber);
+            --bitNumber;
+            if (bitNumber < 0 && col < (cols - 1)) {
+                bitNumber = 7;
+                ++byteNumber;
             }
         }
+        fwrite(buffer, byteNumber + 1, 1, ofP);
+    }
+}
+
+
+
+int 
+main(int    argc,
+     char * argv[]) {
+
+    struct cmdlineInfo cmdline;
+    FILE  * ifP;
+    bit ** bits;
+    int rows, cols;
+
+    pbm_init(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+    bits = pbm_readpbm(ifP, &cols, &rows);
+    pm_close(ifP);
+
+    validateSize(cols, rows);
+
+    switch (cmdline.outputFormat) {
+    case FMT_HEX_NGG:
+        convertToHexNgg(bits, cols, rows, stdout);
+        break;
+    case FMT_HEX_NOL:
+        convertToHexNol(bits, cols, rows, cmdline.networkCode, stdout);
+        break;
+    case FMT_HEX_NPM:
+        convertToHexNpm(bits, cols, rows, cmdline.txt, stdout);
         break;
     case FMT_NGG:
-        /* header - this is a hack */
-        header[0]='N';
-        header[1]='G';
-        header[2]='G';
-        header[4]=header[10]=header[12]=1;
-        header[6]=cols;
-        header[8]=rows;
-        header[14]=0x4a;
-        fwrite(header,16,1,stdout);
-
-        /* image */
-        for (row=0;row<rows;row++) {
-            for (p=c=col=0;col<cols;col++) {
-                if (image[row][col]==PBM_BLACK) putchar('1');
-                else putchar('0');
-            }
-        }
+        convertToNgg(bits, cols, rows, stdout);
+        break;
+    case FMT_NOL:
+        convertToNol(bits, cols, rows, stdout);
+        break;
+    case FMT_NPM:
+        convertToNpm(bits, cols, rows, cmdline.txt, stdout);
         break;
-    default:
-        pm_error("Output format %d not implemented!\n"
-                 "Contact Tim Ruehsen <tim.ruehsen@openmediasystem.de>\n",
-                 output);
-        return 1;
     }
+
+freeCmdline(cmdline);
+
     return 0;
 }
 
+
+
+/* Copyright (C)2001 OMS Open Media System GmbH, Tim Rühsen
+** <tim.ruehsen@openmediasystem.de>.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+
+  Created 2001.06.07
+
+Notes:
+  - limited to rows <= 255 and columns <= 255
+  - limited to b/w graphics, not animated
+
+Testing:
+  Testing was done with SwissCom SMSC (Switzerland) and IC3S SMSC (Germany).
+  The data was send with EMI/UCP protocol over TCP/IP.
+
+  - 7.6.2001: tested with Nokia 3210: 72x14 Operator Logo
+  - 7.6.2001: tested with Nokia 6210: 72x14 Operator Logo and 
+              72x14 Group Graphic
+*/
diff --git a/converter/pbm/pbmtopi3.c b/converter/pbm/pbmtopi3.c
index 8d178f61..1dbf1a71 100644
--- a/converter/pbm/pbmtopi3.c
+++ b/converter/pbm/pbmtopi3.c
@@ -90,14 +90,8 @@ putinit( )
     bitshift = 7;
     }
 
-#if __STDC__
 static void
 putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
     {
     if (bitsperitem == 8)
 	putitem( );
diff --git a/converter/pbm/pbmtopk.c b/converter/pbm/pbmtopk.c
index 08aff49a..fc94f855 100644
--- a/converter/pbm/pbmtopk.c
+++ b/converter/pbm/pbmtopk.c
@@ -172,7 +172,7 @@ pbmtopk_add_suffix(char * const name,
     char *slash = strrchr(name, '/');
     char *dot = strrchr(name, '.');
 
-    if ((dot && slash ? dot < slash : !dot) && !STREQ(name, "-"))
+    if ((dot && slash ? dot < slash : !dot) && !streq(name, "-"))
         strcat(name, suffix);
 }
 
diff --git a/converter/pbm/pbmtoppa/Makefile b/converter/pbm/pbmtoppa/Makefile
index ba15adaa..5f205230 100644
--- a/converter/pbm/pbmtoppa/Makefile
+++ b/converter/pbm/pbmtoppa/Makefile
@@ -5,7 +5,7 @@ endif
 SUBDIR = converter/pbm/pbmtoppa
 VPATH=.:$(SRCDIR)/$(SUBDIR)
 
-include $(BUILDDIR)/Makefile.config
+include $(BUILDDIR)/config.mk
 
 all: pbmtoppa
 
@@ -16,7 +16,7 @@ MERGEBINARIES = $(BINARIES)
 OBJECTS = pbmtoppa.o ppa.o pbm.o cutswath.o
 MERGE_OBJECTS = pbmtoppa.o2 ppa.o pbm.o cutswath.o
 
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
 
 pbmtoppa: $(OBJECTS) $(NETPBMLIB) $(LIBOPT)
 	$(LD) -o pbmtoppa $(OBJECTS) \
diff --git a/converter/pbm/pbmtopsg3.c b/converter/pbm/pbmtopsg3.c
index 68b265f0..54d0a0a0 100644
--- a/converter/pbm/pbmtopsg3.c
+++ b/converter/pbm/pbmtopsg3.c
@@ -26,6 +26,7 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include "pm_c_util.h"
 #include "pbm.h"
 #include "shhopt.h"
 
diff --git a/converter/pbm/pbmtoptx.c b/converter/pbm/pbmtoptx.c
index 5031efcb..8cd60326 100644
--- a/converter/pbm/pbmtoptx.c
+++ b/converter/pbm/pbmtoptx.c
@@ -67,14 +67,8 @@ putinit( )
     bitshift = 0;
     }
 
-#if __STDC__
 static void
 putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
     {
     if ( bitsperitem == 6 )
 	putitem( );
diff --git a/converter/pbm/pbmtox10bm b/converter/pbm/pbmtox10bm
new file mode 100644
index 00000000..9a1a7286
--- /dev/null
+++ b/converter/pbm/pbmtox10bm
@@ -0,0 +1,45 @@
+#! /usr/bin/perl
+
+#============================================================================
+#  This is a compatibility interface to Pbmtoxbm.
+#
+#  It exists so existing programs and procedures that rely on Pbmtox10bm
+#  syntax continue to work.  You should not make new use of Pbmtox10bm and
+#  if you modify an old use, you should upgrade it to use Pbmtoxbm.
+#
+#  Pbmtoxbm with the -x10 option is backward compatible with Pbmtox10bm.
+#============================================================================
+
+use strict;
+use File::Basename;
+use Cwd 'abs_path';
+
+my $infile;
+
+foreach (@ARGV) {
+    if (/^-/) {
+        # It's an option.  But Pbmtox10bm didn't have any options.
+        print(STDERR "Invalid option '$_'\n");
+        exit(10);
+    } else {
+        # It's a parameter
+        if (defined($infile)) {
+            print(STDERR
+                  "You may specify at most one non-option parameter.\n");
+            exit(10);
+        } else {
+            $infile = $_;
+        }
+    }
+}
+
+my $infileParm = defined($infile) ? $infile : "-";
+
+# We want to get Pbmtoxbm from the same directory we came from if
+# it's there.  Frequently, the directory containing Netpbm programs is
+# not in the PATH and we were invoked by absolute path.
+
+my $my_directory = abs_path(dirname($0));
+$ENV{"PATH"} = $my_directory . ":" . $ENV{"PATH"};
+
+exec('pbmtoxbm', '-x10', $infileParm);
diff --git a/converter/pbm/pbmtox10bm.c b/converter/pbm/pbmtox10bm.c
deleted file mode 100644
index ef31fb9b..00000000
--- a/converter/pbm/pbmtox10bm.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* pbmtox10bm.c - read a portable bitmap and produce an X10 bitmap file
-**
-** Copyright (C) 1988 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
-*/
-
-#include <string.h>
-
-#include "nstring.h"
-#include "pbm.h"
-
-int
-main(int argc, char * argv[]) {
-
-    FILE* ifp;
-    bit* bitrow;
-    bit * bP;
-    int rows, cols, format, padright, row;
-    int col;
-    char name[100];
-    char* cp;
-    int itemsperline;
-    int bitsperitem;
-    int item;
-    int firstitem;
-    const char* const hexchar = "0123456789abcdef";
-
-
-    pbm_init( &argc, argv );
-
-    if ( argc > 2 )
-        pm_usage( "[pbmfile]" );
-
-    if ( argc == 2 )
-	{
-        ifp = pm_openr( argv[1] );
-        strcpy( name, argv[1] );
-        if (STREQ( name, "-" ))
-            strcpy( name, "noname" );
-
-        if ( ( cp = strchr( name, '.' ) ) != 0 )
-            *cp = '\0';
-	}
-    else
-	{
-        ifp = stdin;
-        strcpy( name, "noname" );
-	}
-
-    pbm_readpbminit( ifp, &cols, &rows, &format );
-    bitrow = pbm_allocrow( cols );
-
-    /* Compute padding to round cols up to the nearest multiple of 16. */
-    padright = ( ( cols + 15 ) / 16 ) * 16 - cols;
-
-    printf( "#define %s_width %d\n", name, cols );
-    printf( "#define %s_height %d\n", name, rows );
-    printf( "static short %s_bits[] = {\n", name );
-
-    itemsperline = 0;
-    bitsperitem = 0;
-    item = 0;
-    firstitem = 1;
-
-#define PUTITEM \
-    { \
-        if ( firstitem ) \
-	        firstitem = 0; \
-        else \
-	        putchar( ',' ); \
-    if ( itemsperline == 11 ) \
-	{ \
-	    putchar( '\n' ); \
-	    itemsperline = 0; \
-	} \
-    if ( itemsperline == 0 ) \
-	    putchar( ' ' ); \
-    ++itemsperline; \
-    putchar('0'); \
-    putchar('x'); \
-    putchar(hexchar[item >> 12]); \
-    putchar(hexchar[(item >> 8) & 15]); \
-    putchar(hexchar[(item >> 4) & 15]); \
-    putchar(hexchar[item & 15]); \
-    bitsperitem = 0; \
-    item = 0; \
-    }
-
-#define PUTBIT(b) \
-    { \
-    if ( bitsperitem == 16 ) \
-	    PUTITEM; \
-    if ( (b) == PBM_BLACK ) \
-	    item += 1 << bitsperitem; \
-    ++bitsperitem; \
-    }
-
-    for ( row = 0; row < rows; ++row )
-	{
-        pbm_readpbmrow( ifp, bitrow, cols, format );
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-            PUTBIT(*bP);
-        for ( col = 0; col < padright; ++col )
-            PUTBIT(0);
-    }
-
-    pm_close( ifp );
-    
-    if ( bitsperitem > 0 )
-        PUTITEM;
-    printf( "};\n" );
-
-    return 0;
-}
diff --git a/converter/pbm/pbmtoxbm.c b/converter/pbm/pbmtoxbm.c
index 96830a0c..340642ce 100644
--- a/converter/pbm/pbmtoxbm.c
+++ b/converter/pbm/pbmtoxbm.c
@@ -1,4 +1,4 @@
-/* pbmtoxbm.c - read a portable bitmap and produce an X11 bitmap file
+/* pbmtoxbm.c - read a PBM image and produce an X11/X10 bitmap file
 **
 ** Copyright (C) 1988 by Jef Poskanzer.
 **
@@ -10,17 +10,114 @@
 ** implied warranty.
 */
 
+/* 2006.10 (afu)   
+   Changed bitrow from plain to raw, read function from pbm_readpbmrow() to
+   pbm_readpbmrow_packed().  Retired bitwise transformation functions.
+ 
+   Output function putitem rewritten to handle both X10 and X11.
+
+   Added -name option.  There is no check for the string thus given.
+
+*/
+
 #define _BSD_SOURCE 1      /* Make sure strdup() is in string.h */
 #define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 
 #include <string.h>
 
+#include "pm_c_util.h"
 #include "pbm.h"
+#include "shhopt.h"
+#include "mallocvar.h"
+#include "bitreverse.h"
 #include "nstring.h"
 
 
+enum xbmVersion { X10, X11 };
+
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char *    inputFileName;
+    const char *    name;
+    enum xbmVersion xbmVersion;
+};
+
+static void
+parseCommandLine(int                 argc, 
+                 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.  
+
+   If command line is internally inconsistent (invalid options, etc.),
+   issue error message to stderr and abort program.
+
+   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 optParseOptions3 on how to parse our options. */
+
+    optStruct3 opt;
+    unsigned int option_def_index;
+    unsigned int x10, x11, nameSpec;
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+
+    OPTENT3(0, "name", OPT_STRING, &cmdlineP->name, &nameSpec, 0);
+    OPTENT3(0, "x10" , OPT_FLAG,   NULL, &x10, 0);
+    OPTENT3(0, "x11" , OPT_FLAG,   NULL, &x11, 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 */
+
+    optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (!nameSpec)
+        cmdlineP->name = NULL;
+    else if (strlen(cmdlineP->name) > 56)
+        pm_error("Image name too long: %d chars. (max 56)",
+                 strlen(cmdlineP->name));
+    else if (!ISALPHA(cmdlineP->name[0]) && cmdlineP->name[0] !='_')
+        pm_error("Image name '%s' starts with non-alphabet character.",
+                  cmdlineP->name);
+    else {
+        unsigned int i;
+        for (i = 0 ; i < strlen(cmdlineP->name); ++i)
+            if (!ISALNUM(cmdlineP->name[i]) && cmdlineP->name[i] != '_')
+                pm_error("Image name '%s' contains invalid character (%c).",
+                         cmdlineP->name, cmdlineP->name[i]);
+    }
+    
+    if (x10 && x11)
+        pm_error("You can't specify both -x10 and -x11");
+    else if (x10)
+        cmdlineP->xbmVersion = X10;
+    else 
+        cmdlineP->xbmVersion = X11;
+        
+    if (argc-1 < 1) 
+        cmdlineP->inputFileName = "-";
+    else {
+        cmdlineP->inputFileName = argv[1];
+        
+        if (argc-1 > 1)
+            pm_error("Program takes zero or one argument (filename).  You "
+                     "specified %u", argc-1);
+    }
+}
+
+
+
 static void
-generateName(char const filenameArg[], const char ** const nameP) {
+generateName(char          const filenameArg[],
+             const char ** const nameP) {
 /*----------------------------------------------------------------------------
    Generate a name for the image to put in the bitmap file.  Derive it from
    the filename argument filenameArg[] and return it as a null-terminated
@@ -34,7 +131,7 @@ generateName(char const filenameArg[], const char ** const nameP) {
    "noname".  Also, if the argument is null or ends in a slash, we
    return "noname".
 -----------------------------------------------------------------------------*/
-    if (STREQ(filenameArg, "-"))
+    if (streq(filenameArg, "-"))
         *nameP = strdup("noname");
     else {
         int nameIndex, argIndex;
@@ -67,99 +164,248 @@ generateName(char const filenameArg[], const char ** const nameP) {
 
 
 
-int
-main(int argc, char * argv[]) {
+static unsigned short int itemBuff[22];
+static int itemCnt;    /* takes values 0 to 15 (x11) or 21 (x10) */
+static enum xbmVersion itemVersion;
 
-    FILE* ifp;
-    bit* bitrow;
-    int rows, cols, format;
-    int padright;
-    int row;
-    const char * inputFilename;
-    const char *name;
-    int itemsperline;
-    int bitsperitem;
-    int item;
-    int firstitem;
-    const char hexchar[] = "0123456789abcdef";
 
-    pbm_init(&argc, argv);
 
-    if (argc-1 > 1)
-        pm_error("Too many arguments (%d).  The only valid argument is an "
-                 "input file name.", argc-1);
-    else if (argc-1 == 1) 
-        inputFilename = argv[1];
-    else
-        inputFilename = "-";
+static void
+putitemX10(unsigned char const item) {
 
-    generateName(inputFilename, &name);
-    ifp = pm_openr(inputFilename);
-    
-    pbm_readpbminit(ifp, &cols, &rows, &format);
-    bitrow = pbm_allocrow(cols);
-    
-    /* Compute padding to round cols up to the nearest multiple of 8. */
-    padright = ((cols + 7)/8) * 8 - cols;
-
-    printf("#define %s_width %d\n", name, cols);
-    printf("#define %s_height %d\n", name, rows);
-    printf("static char %s_bits[] = {\n", name);
-
-    itemsperline = 0;
-    bitsperitem = 0;
-    item = 0;
-    firstitem = 1;
-
-#define PUTITEM \
-    { \
-    if ( firstitem ) \
-        firstitem = 0; \
-    else \
-        putchar( ',' ); \
-    if ( itemsperline == 15 ) \
-        { \
-        putchar( '\n' ); \
-        itemsperline = 0; \
-        } \
-    if ( itemsperline == 0 ) \
-        putchar( ' ' ); \
-    ++itemsperline; \
-    putchar('0'); \
-    putchar('x'); \
-    putchar(hexchar[item >> 4]); \
-    putchar(hexchar[item & 15]); \
-    bitsperitem = 0; \
-    item = 0; \
+    if (itemCnt == 22) {
+        /* Buffer is full.  Write out one line. */
+        int rc;
+        rc = printf(" 0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x,"
+                    "0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x,"
+                    "0x%02x%02x,0x%02x%02x,0x%02x%02x,\n",
+                    itemBuff[ 1], itemBuff[ 0], itemBuff[ 3], itemBuff[ 2],
+                    itemBuff[ 5], itemBuff[ 4], itemBuff[ 7], itemBuff[ 6],
+                    itemBuff[ 9], itemBuff[ 8], itemBuff[11], itemBuff[10],
+                    itemBuff[13], itemBuff[12], itemBuff[15], itemBuff[14],
+                    itemBuff[17], itemBuff[16], itemBuff[19], itemBuff[18],
+                    itemBuff[21], itemBuff[20]
+            );
+
+        if (rc < 0)        
+            pm_error("Error writing X10 bitmap raster item.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
+        
+        itemCnt = 0;
     }
+    itemBuff[itemCnt++] = bitreverse[item];
+}
+
 
-#define PUTBIT(b) \
-    { \
-    if ( bitsperitem == 8 ) \
-        PUTITEM; \
-    if ( (b) == PBM_BLACK ) \
-        item += 1 << bitsperitem; \
-    ++bitsperitem; \
+
+static void
+putitemX11(unsigned char const item) {
+
+    if (itemCnt == 15 ) {
+        /* Buffer is full.  Write out one line. */
+        int rc;
+        rc = printf(" 0x%02x,0x%02x,0x%02x,0x%02x,"
+                    "0x%02x,0x%02x,0x%02x,0x%02x,"
+                    "0x%02x,0x%02x,0x%02x,0x%02x,"
+                    "0x%02x,0x%02x,0x%02x,\n",
+                    itemBuff[0], itemBuff[1], itemBuff[2], itemBuff[3],
+                    itemBuff[4], itemBuff[5], itemBuff[6], itemBuff[7],
+                    itemBuff[8], itemBuff[9], itemBuff[10],itemBuff[11],
+                    itemBuff[12],itemBuff[13],itemBuff[14]
+            );
+        if (rc < 0)        
+            pm_error("Error writing X11 bitmap raster item.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
+        
+        itemCnt = 0;
     }
+    itemBuff[itemCnt++] = bitreverse[item];
+}
 
-    for (row = 0; row < rows; ++row) {
-        int col;
-        pbm_readpbmrow(ifp, bitrow, cols, format);
-        for (col = 0; col < cols; ++col)
-            PUTBIT(bitrow[col]);
-        for (col = 0; col < padright; ++col)
-            PUTBIT(0);
+
+
+static void
+putitem(unsigned char const item) {
+
+    switch (itemVersion) {
+    case X10: putitemX10(item); break;
+    case X11: putitemX11(item); break;
     }
+}
+
+
+
+static void
+puttermX10(void) {
+
+    unsigned int i;
+
+    for (i = 0; i < itemCnt; i += 2) {
+        int rc;
+
+        rc = printf("%s0x%02x%02x%s",
+                    (i == 0) ? " " : "",
+                    itemBuff[i+1],
+                    itemBuff[i], 
+                    (i == itemCnt - 2) ? "" : ",");
+        if (rc < 0)        
+            pm_error("Error writing end of X10 bitmap raster.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
+    }
+}
+
+
+
+static void
+puttermX11(void) {
+
+    unsigned int i;
 
-    pm_close(ifp);
+    for (i = 0; i < itemCnt; ++i) {
+        int rc;
 
-    if (bitsperitem > 0)
-        PUTITEM;
-    printf("};\n");
+        rc = printf("%s0x%02x%s",
+                    (i == 0)  ? " " : "",
+                    itemBuff[i],
+                    (i == itemCnt - 1) ? "" : ",");
+
+        if (rc < 0)        
+            pm_error("Error writing end of X11 bitmap raster.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
+    }
+}
+
+
+
+static void
+putinit(enum xbmVersion const xbmVersion) {
+
+    itemCnt = 0;
+    itemVersion = xbmVersion;
+}
+
+
+
+static void
+putterm(void) {
+
+    switch (itemVersion) {
+    case X10: puttermX10(); break;
+    case X11: puttermX11(); break;
+    }
+
+    {
+        int rc;
+
+        rc = printf("};\n");
+
+        if (rc < 0)        
+            pm_error("Error writing end of X11 bitmap raster.  "
+                     "printf() failed with errno %d (%s)",
+                     errno, strerror(errno));
+    }
+}
+
+
+
+static void
+writeXbmHeader(enum xbmVersion const xbmVersion,
+               const char *    const name,
+               unsigned int    const width,
+               unsigned int    const height,
+               FILE *          const ofP) {
+
+    printf("#define %s_width %d\n", name, width);
+    printf("#define %s_height %d\n", name, height);
+    printf("static %s %s_bits[] = {\n",
+           xbmVersion == X10 ? "short" : "char",
+           name);
+}
+
+
+
+static void
+convertRaster(FILE *          const ifP,
+              unsigned int    const cols,
+              unsigned int    const rows,
+              int             const format,
+              FILE *          const ofP,
+              enum xbmVersion const xbmVersion) {
+              
+    unsigned int const bitsPerUnit = xbmVersion == X10 ? 16 : 8;   
+    unsigned int const padright =
+        ((cols + bitsPerUnit - 1 ) / bitsPerUnit) * bitsPerUnit - cols;
+        /* Amount of padding to round cols up to the nearest multiple of 
+           8 (if x11) or 16 (if x10).
+        */
+    unsigned int const bitrowBytes = (cols + padright) / 8;
+
+    unsigned char * bitrow;
+    unsigned int row;
+
+    putinit(xbmVersion);
+
+    bitrow = pbm_allocrow_packed(cols + padright);
+    
+    for (row = 0; row < rows; ++row) {
+        int const bitrowInBytes = pbm_packed_bytes(cols);
+        int const padrightIn    = bitrowInBytes * 8 - cols;
+
+        unsigned int i;
+
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+
+        if (padrightIn > 0) {
+            bitrow[bitrowInBytes - 1] >>= padrightIn;
+            bitrow[bitrowInBytes - 1] <<= padrightIn;
+        }
+
+        if (padright >= 8)
+            bitrow[bitrowBytes-1] = 0x00;
+
+        for (i = 0; i < bitrowBytes; ++i)
+            putitem(bitrow[i]);
+    }
+
+    putterm();
 
     pbm_freerow(bitrow);
+}
+
+
+
+int
+main(int    argc,
+     char * argv[]) {
+
+    struct cmdlineInfo cmdline; 
+    FILE * ifP;
+    int rows, cols, format;
+    const char * name;
+
+    pbm_init(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+    if (cmdline.name == NULL) 
+        generateName(cmdline.inputFileName, &name);
+    else
+        name = strdup(cmdline.name);
+
+    ifP = pm_openr(cmdline.inputFileName);
+    
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+    
+    writeXbmHeader(cmdline.xbmVersion, name, cols, rows, stdout);
+
+    convertRaster(ifP, cols, rows, format, stdout, cmdline.xbmVersion);
 
     strfree(name);
+    pm_close(ifP);
 
-    exit(0);
+    return 0;
 }
+
diff --git a/converter/pbm/pbmtoybm.c b/converter/pbm/pbmtoybm.c
index 1d2be3d9..508e8e92 100644
--- a/converter/pbm/pbmtoybm.c
+++ b/converter/pbm/pbmtoybm.c
@@ -80,14 +80,8 @@ putinit( cols, rows )
     bitshift = 0;
     }
 
-#if __STDC__
 static void
 putbit( bit b )
-#else /*__STDC__*/
-static void
-putbit( b )
-    bit b;
-#endif /*__STDC__*/
     {
     if ( bitsperitem == 16 )
 	putitem( );
diff --git a/converter/pbm/pbmtozinc.c b/converter/pbm/pbmtozinc.c
index d39b71bc..2df39f0d 100644
--- a/converter/pbm/pbmtozinc.c
+++ b/converter/pbm/pbmtozinc.c
@@ -49,7 +49,7 @@ main(int argc, char * argv[]) {
 	{
         ifp = pm_openr( argv[1] );
         strcpy( name, argv[1] );
-        if ( STREQ( name, "-" ) )
+        if ( streq( name, "-" ) )
             strcpy( name, "noname" );
 
         if ( ( cp = strchr( name, '.' ) ) != 0 )
diff --git a/converter/pbm/pktopbm.c b/converter/pbm/pktopbm.c
index af49e9c7..712f339f 100644
--- a/converter/pbm/pktopbm.c
+++ b/converter/pbm/pktopbm.c
@@ -50,7 +50,7 @@ pktopbm_add_suffix(char *       const name,
     char * const slash = strrchr(name, '/');
     char * const dot   = strrchr(name, '.');
     
-    if ((dot && slash ? dot < slash : !dot) && !STREQ(name, "-"))
+    if ((dot && slash ? dot < slash : !dot) && !streq(name, "-"))
         strcat(name, suffix);
 }
 
diff --git a/converter/pbm/thinkjettopbm.l b/converter/pbm/thinkjettopbm.l
index a66ae07e..71501596 100644
--- a/converter/pbm/thinkjettopbm.l
+++ b/converter/pbm/thinkjettopbm.l
@@ -37,6 +37,7 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include "pm_c_util.h"
 #include "pbm.h"
 #include "shhopt.h"
 
diff --git a/converter/pbm/xbmtopbm.c b/converter/pbm/xbmtopbm.c
index 7779a9b5..9505ba67 100644
--- a/converter/pbm/xbmtopbm.c
+++ b/converter/pbm/xbmtopbm.c
@@ -1,4 +1,4 @@
-/* xbmtopbm.c - read an X bitmap file and produce a portable bitmap
+/* xbmtopbm.c - read an X bitmap file and produce a PBM image
 **
 ** Copyright (C) 1988 by Jef Poskanzer.
 **
@@ -10,246 +10,382 @@
 ** implied warranty.
 */
 
+
+#include <assert.h>
 #include <string.h>
 
+#include "pm_c_util.h"
+#include "mallocvar.h"
 #include "nstring.h"
 #include "pbm.h"
+#include "bitreverse.h"
 
-#define TRUE 1
-#define FALSE 0
 
-static void ReadBitmapFile ARGS(( FILE* stream, int* widthP, int* heightP, char** dataP ));
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, row, col, charcount;
-    char* data;
-    char mask;
-
-    pbm_init( &argc, argv );
-
-    if ( argc > 2 )
-        pm_usage( "[bitmapfile]" );
-    
-    if ( argc == 2 )
-        ifp = pm_openr( argv[1] );
-    else
-        ifp = stdin;
-
-    ReadBitmapFile( ifp, &cols, &rows, &data );
-
-    pm_close( ifp );
-
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
-
-    for ( row = 0; row < rows; ++row )
-        {
-        charcount = 0;
-        mask = 1;
-        for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
-            {
-            if ( charcount >= 8 )
-                {
-                ++data;
-                charcount = 0;
-                mask = 1;
-                }
-            *bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE;
-            ++charcount;
-            mask = mask << 1;
-            }
-        ++data;
-        pbm_writepbmrow( stdout, bitrow, cols, 0 );
-        }
+#define MAX_LINE 500
+
+static unsigned int hexTable[256];
+    /* Hexadecimal ASCII translation table.  Constant */
+
+static void
+initHexTable(void) {
+
+    unsigned int i;
+
+    for (i = 0; i < 256; ++i)
+        hexTable[i] = 256;
+
+    hexTable['0'] =  0;
+    hexTable['1'] =  1;
+    hexTable['2'] =  2;
+    hexTable['3'] =  3;
+    hexTable['4'] =  4;
+    hexTable['5'] =  5;
+    hexTable['6'] =  6;
+    hexTable['7'] =  7;
+    hexTable['8'] =  8;
+    hexTable['9'] =  9;
+    hexTable['A'] = 10;
+    hexTable['B'] = 11;
+    hexTable['C'] = 12;
+    hexTable['D'] = 13;
+    hexTable['E'] = 14;
+    hexTable['F'] = 15;
+    hexTable['a'] = 10;
+    hexTable['b'] = 11;
+    hexTable['c'] = 12;
+    hexTable['d'] = 13;
+    hexTable['e'] = 14;
+    hexTable['f'] = 15;
+}
 
-    pm_close( stdout );
-    exit( 0 );
-    }
 
-#define MAX_LINE 500
 
 static void
-ReadBitmapFile( stream, widthP, heightP, dataP )
-     FILE* stream;
-     int* widthP;
-     int* heightP;
-     char** dataP;
-{
-  char line[MAX_LINE], name_and_type[MAX_LINE];
-  char* ptr;
-  char* t;
-  int version10, raster_length, v;
-  register int bytes, bytes_per_line, padding;
-  register int c1, c2, value1, value2;
-  int hex_table[256];
-  int found_declaration;
-  /* In scanning through the bitmap file, we have found the first
-     line of the C declaration of the array (the "static char ..."
-     or whatever line)
-     */
-  int eof;
-  /* We've encountered end of file while searching file */
-
-  *widthP = *heightP = -1;
-
-  found_declaration = FALSE;    /* Haven't found it yet; haven't even looked*/
-  eof = FALSE;                  /* Haven't encountered end of file yet */
-
-  while (!found_declaration && !eof) {
-    if ( fgets( line, MAX_LINE, stream ) == NULL )
-      eof = TRUE;
-    else {
-      if ( strlen( line ) == MAX_LINE - 1 )
-        pm_error( "line too long" );
-
-      if ( sscanf( line, "#define %s %d", name_and_type, &v ) == 2 ) {
-        if ( ( t = strrchr( name_and_type, '_' ) ) == NULL )
-          t = name_and_type;
+parseWidthHeightLine(const char *   const line,
+                     bool *         const gotWidthP,
+                     unsigned int * const widthP,
+                     bool *         const gotHeightP,
+                     unsigned int * const heightP) {
+
+    int rc;
+    char nameAndType[MAX_LINE];
+    unsigned int value;
+
+    rc = sscanf(line, "#define %s %u", nameAndType, &value);
+    if (rc == 2) {
+        const char * underscorePos = strrchr(nameAndType, '_');
+        const char * type;
+        if (underscorePos)
+            type = underscorePos + 1;
         else
-          ++t;
-        if ( STREQ( "width", t ) )
-          *widthP = v;
-        else if ( STREQ( "height", t ) )
-          *heightP = v;
-        continue;
-      }
+            type = nameAndType;
+        if (streq(type, "width")) {
+            *gotWidthP = TRUE;
+            *widthP = value;
+        } else if (streq(type, "height")) {
+            *gotHeightP = TRUE;
+            *heightP = value;
+        }
+    }
+}
+
+
+
+static void
+parseDeclaration(const char * const line,
+                 bool *       const isDeclarationP,
+                 bool *       const version10P) {
+/*----------------------------------------------------------------------------
+   Parse the XBM file line 'line' as the first line of the data structure
+   declaration, i.e. the one that looks like this:
+
+      static unsigned char myImage = {
+
+   Return as *isDeclarationP whether the line actually is such a line,
+   and if so, return as nameAndType what the variable name ('myImage'
+   in the example) is and as *version10P whether it's of the type used
+   by X10 as opposed to X11.
+-----------------------------------------------------------------------------*/
+    char nameAndType[MAX_LINE];
+    int rc;
         
-      if ( sscanf( line, "static short %s = {", name_and_type ) == 1 ) {
-        version10 = TRUE;
-        found_declaration = TRUE;
-      }
-      else if ( sscanf( line, "static char %s = {", name_and_type ) == 1 ) {
-        version10 = FALSE;
-        found_declaration = TRUE;
-      }
-      else if (sscanf(line, 
-                      "static unsigned char %s = {", name_and_type ) == 1 ) {
-        version10 = FALSE;
-        found_declaration = TRUE;
-      }
+    rc = sscanf(line, "static short %s = {", nameAndType);
+    if (rc == 1) {
+        *version10P     = TRUE;
+        *isDeclarationP = TRUE;
+    } else {
+        int rc;
+        rc = sscanf(line, "static char %s = {", nameAndType);
+        if (rc == 1) {
+            *version10P     = FALSE;
+            *isDeclarationP = TRUE;
+        } else {
+            int rc;
+            rc = sscanf(line, "static unsigned char %s = {", nameAndType);
+            if (rc == 1) {
+                *version10P     = FALSE;
+                *isDeclarationP = TRUE;
+            } else
+                *isDeclarationP = FALSE;
+        }
     }
-  }
- 
-  if (!found_declaration) 
-    pm_error("Unable to find a line in the file containing the start "
-             "of C array declaration (\"static char\" or whatever)");
-
-  if ( *widthP == -1 )
-    pm_error( "invalid width" );
-  if ( *heightP == -1 )
-    pm_error( "invalid height" );
-
-  padding = 0;
-  if ( ((*widthP % 16) >= 1) && ((*widthP % 16) <= 8) && version10 )
-    padding = 1;
-
-  bytes_per_line = (*widthP+7)/8 + padding;
+}
+
+
+
+static void
+getXbmHeader(FILE *         const ifP,
+             unsigned int * const widthP,
+             unsigned int * const heightP,
+             bool *         const version10P) {
+
+    bool foundDeclaration;
+        /* In scanning through the bitmap file, we have found the first
+           line of the C declaration of the array (the "static char ..."
+           or whatever line)
+        */
+    bool gotWidth, gotHeight;
+        /* We found the line in the bitmap file that gives the width
+           or height, respectively, of the image (and have set
+           *widthP or *heightP to the value in it).
+        */
+
+    bool eof;
+        /* We've encountered end of file while searching file */
+
+    gotWidth = FALSE;
+    gotHeight = FALSE;
+    foundDeclaration = FALSE;    /* Haven't found it yet; haven't even looked*/
+    eof = FALSE;                 /* Haven't encountered end of file yet */
+
+    while (!foundDeclaration && !eof) {
+        char * rc;
+        char line[MAX_LINE];
+
+        rc = fgets(line, MAX_LINE, ifP);
+        if (rc == NULL)
+            eof = TRUE;
+        else {
+            if (strlen(line) == MAX_LINE - 1)
+                pm_error("A line in the input file is %u characters long.  "
+                         "%u is the maximum we can handle",
+                         strlen(line), MAX_LINE-1);
+
+            parseWidthHeightLine(line, &gotWidth, widthP, &gotHeight, heightP);
+
+            parseDeclaration(line, &foundDeclaration, version10P);
+        }
+    }
+
+    if (!foundDeclaration) 
+        pm_error("Unable to find a line in the file containing the start "
+                 "of C array declaration (\"static char\" or whatever)");
+
+    if (!gotWidth)
+        pm_error("Unable to find the #define statement that gives the "
+                 "width of the image, before the data structure "
+                 "declaration.");
+    if (!gotHeight)
+        pm_error("Unable to find the #define statement that gives the "
+                 "height of the image, before the data structure "
+                 "declaration.");
+}
+
+
+
+static void
+getHexByte(FILE *         const ifP,
+           unsigned int * const valueP) {
+
+    int c1, c2;
+    unsigned int value;
+
+    c1 = getc(ifP);
+    c2 = getc(ifP);
+    if (c1 == EOF || c2 == EOF)
+        pm_error("EOF / read error");
+
+    assert(c1 >= 0); assert(c1 < 256);
+    assert(c2 >= 0); assert(c2 < 256);
     
-  raster_length =  bytes_per_line * *heightP;
-  *dataP = (char*) malloc( raster_length );
-  if ( *dataP == (char*) 0 )
-    pm_error( "out of memory" );
-
-  /* Initialize hex_table. */
-  for ( c1 = 0; c1 < 256; ++c1 )
-    hex_table[c1] = 256;
-  hex_table['0'] = 0;
-  hex_table['1'] = 1;
-  hex_table['2'] = 2;
-  hex_table['3'] = 3;
-  hex_table['4'] = 4;
-  hex_table['5'] = 5;
-  hex_table['6'] = 6;
-  hex_table['7'] = 7;
-  hex_table['8'] = 8;
-  hex_table['9'] = 9;
-  hex_table['A'] = 10;
-  hex_table['B'] = 11;
-  hex_table['C'] = 12;
-  hex_table['D'] = 13;
-  hex_table['E'] = 14;
-  hex_table['F'] = 15;
-  hex_table['a'] = 10;
-  hex_table['b'] = 11;
-  hex_table['c'] = 12;
-  hex_table['d'] = 13;
-  hex_table['e'] = 14;
-  hex_table['f'] = 15;
-
-  if ( version10 )
-    for ( bytes = 0, ptr = *dataP; bytes < raster_length; bytes += 2 ) {
-      while ( ( c1 = getc( stream ) ) != 'x' )
-        if ( c1 == EOF )
-          pm_error( "EOF / read error" );
-      c1 = getc( stream );
-      c2 = getc( stream );
-      if ( c1 == EOF || c2 == EOF )
-        pm_error( "EOF / read error" );
-      value1 = ( hex_table[c1] << 4 ) + hex_table[c2];
-      if ( value1 >= 256 )
-        pm_error( "syntax error" );
-      c1 = getc( stream );
-      c2 = getc( stream );
-      if ( c1 == EOF || c2 == EOF )
-        pm_error( "EOF / read error" );
-      value2 = ( hex_table[c1] << 4 ) + hex_table[c2];
-      if ( value2 >= 256 )
-        pm_error( "syntax error" );
-      *ptr++ = value2;
-      if ( ( ! padding ) || ( ( bytes + 2 ) % bytes_per_line ) )
-        *ptr++ = value1;
+    value = (hexTable[c1] << 4) + hexTable[c2];
+    if (value >= 256)
+        pm_error("Invalid XBM input.  What should be a two digit "
+                 "hexadecimal cipher is instead '%c%c'", c1, c2);
+
+    *valueP = value;
+}
+
+
+                     
+static void
+readX10Raster(FILE *          const ifP,
+              unsigned int    const rasterLength,
+              unsigned char * const data,
+              unsigned int    const bytesPerLine,
+              bool            const mustPad) {
+
+    unsigned int bytesDone;
+    unsigned char * p;
+
+    for (bytesDone = 0, p = &data[0];
+         bytesDone < rasterLength;
+         bytesDone += 2) {
+
+        unsigned int value1;
+        unsigned int value2;
+
+        while (getc(ifP) != 'x') {}  /* Read up through the 'x' in 0x1234 */
+
+        getHexByte(ifP, &value1);  /* Read first two hex digits */
+        getHexByte(ifP, &value2);  /* Read last two hex digits */
+
+        *p++ = value2;
+
+        if (!mustPad || ((bytesDone + 2) % bytesPerLine))
+            *p++ = value1;
     }
-  else
-    for ( bytes = 0, ptr = *dataP; bytes < raster_length; ++bytes ) {
-      /*
-       ** Skip until digit is found.
-       */
-      for ( ; ; )
-        {
-          c1 = getc( stream );
-          if ( c1 == EOF )
-            pm_error( "EOF / read error" );
-          value1 = hex_table[c1];
-          if ( value1 != 256 )
-            break;
-        }
-      /*
-       ** Loop on digits.
-       */
-      for ( ; ; ) {
-        c2 = getc( stream );
-        if ( c2 == EOF )
-          pm_error( "EOF / read error" );
-        value2 = hex_table[c2];
-        if ( value2 != 256 ) {
-          value1 = (value1 << 4) | value2;
-          if ( value1 >= 256 )
-            pm_error( "syntax error" );
+}
+
+
+
+static void
+readX11Raster(FILE * const ifP,
+              unsigned int const rasterLength,
+              unsigned char * data) {
+
+    unsigned int i;
+
+    for (i = 0; i < rasterLength; ++i) {
+        unsigned int value;
+        int c;
+
+        /* Read up through the 'x' in 0x12 */
+        while ((c = getc(ifP))) {
+            if (c == EOF)
+                pm_error("EOF where 0x expected");
+            else if (toupper(c) == 'X')
+                break;
         }
-        else if ( c2 == 'x' || c2 == 'X' )
-          if ( value1 == 0 )
-            continue;
-          else pm_error( "syntax error" );
-        else break;
-      }
-      *ptr++ = value1;
+
+        getHexByte(ifP, &value);  /* Read the two hex digits */
+
+        assert(value < 256);
+
+        data[i] = value;
     }
 }
 
 
-/*  CHANGE HISTORY:
 
-  99.09.08 bryanh    Recognize "static unsigned char" declaration.
+static void
+readBitmapFile(FILE *           const ifP,
+               unsigned int *   const widthP,
+               unsigned int *   const heightP,
+               unsigned char ** const dataP) {
+
+    bool version10;
+    unsigned int rasterLength;
+    unsigned int width, height;
+    unsigned char * data;
 
+    unsigned int bytesPerLine;
+    bool mustPad;
 
+    getXbmHeader(ifP, &width, &height, &version10);
 
+    *widthP = width;
+    *heightP = height;
 
+    mustPad = (width % 16 >= 1 && width % 16 <= 8 && version10);
+
+    bytesPerLine = (width + 7) / 8 + (mustPad ? 1 : 0);
+    
+    rasterLength = bytesPerLine * height;
+
+    MALLOCARRAY(data, rasterLength);
+    if (data == NULL)
+        pm_error("Unable to allocate memory for the %u-byte raster",
+                 rasterLength);
+
+    if (version10)
+        readX10Raster(ifP, rasterLength, data, bytesPerLine, mustPad);
+    else
+        readX11Raster(ifP, rasterLength, data);
+
+    *dataP = data;
+}
+
+
+
+int
+main(int    argc,
+     char * argv[]) {
+
+    FILE * ifP;
+    bit * bitrow;
+    unsigned int rows, cols;
+    unsigned int row;
+    unsigned char * data;
+    const char * inputFileName;
+    unsigned char * p;
+        /* Cursor in raster data data[] */
+    
+    initHexTable();
+
+    pbm_init(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("The only possible argument is the input file name.  "
+                 "You specified %u arguments", argc-1);
+    
+    if (argc-1 > 0)
+        inputFileName = argv[1];
+    else
+        inputFileName = "-";
+
+    ifP = pm_openr(inputFileName);
+
+    readBitmapFile(ifP, &cols, &rows, &data);
+
+    pm_close(ifP);
+
+    pbm_writepbminit(stdout, cols, rows, 0);
+    bitrow = pbm_allocrow_packed(cols);
+
+    p = &data[0];  /* Start at beginning of raster */
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int const bytesPerRow = pbm_packed_bytes(cols);
+        unsigned int i;
+        
+        for (i = 0; i < bytesPerRow; ++i)
+            bitrow[i] = bitreverse[*p++];
+            
+        if (cols % 8 > 0) {
+            bitrow[bytesPerRow-1] >>= 8 - cols % 8;
+            bitrow[bytesPerRow-1] <<= 8 - cols % 8;
+        }
+            
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
+    }
+
+    pbm_freerow(bitrow);
+    free(data);
+    pm_close(stdout);
+
+    return 0;
+}
+
+/*  CHANGE HISTORY:
+
+  99.09.08 bryanh    Recognize "static unsigned char" declaration.
+
+  06.10 (afu)
+   Changed bitrow from plain to raw, write function from pbm_writepbmrow()
+   to pbm_writepbmrow_packed().
+   Retired bitwise transformation functions.
 
 */
+