about summary refs log tree commit diff
path: root/converter/ppm
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm')
-rw-r--r--converter/ppm/411toppm.c1
-rw-r--r--converter/ppm/Makefile4
-rw-r--r--converter/ppm/eyuvtoppm.c2
-rw-r--r--converter/ppm/hpcdtoppm/Makefile6
-rw-r--r--converter/ppm/ilbmtoppm.c464
-rw-r--r--converter/ppm/mitsu.h1
-rw-r--r--converter/ppm/pcxtoppm.c1
-rw-r--r--converter/ppm/picttoppm.c1436
-rw-r--r--converter/ppm/ppmtoarbtxt.c493
-rw-r--r--converter/ppm/ppmtobmp.c512
-rw-r--r--converter/ppm/ppmtogif.c1571
-rw-r--r--converter/ppm/ppmtoilbm.c66
-rw-r--r--converter/ppm/ppmtoleaf.c259
-rw-r--r--converter/ppm/ppmtomitsu.c897
-rw-r--r--converter/ppm/ppmtomitsu.test12
-rw-r--r--converter/ppm/ppmtompeg/Makefile33
-rw-r--r--converter/ppm/ppmtompeg/bframe.c1
-rw-r--r--converter/ppm/ppmtompeg/bsearch.c1
-rw-r--r--converter/ppm/ppmtompeg/combine.c6
-rw-r--r--converter/ppm/ppmtompeg/file.c351
-rw-r--r--converter/ppm/ppmtompeg/frames.c58
-rw-r--r--converter/ppm/ppmtompeg/gethostname_win32.c404
-rw-r--r--converter/ppm/ppmtompeg/headers/bitio.h4
-rw-r--r--converter/ppm/ppmtompeg/headers/block.h44
-rw-r--r--converter/ppm/ppmtompeg/headers/byteorder.h2
-rw-r--r--converter/ppm/ppmtompeg/headers/frame.h16
-rw-r--r--converter/ppm/ppmtompeg/headers/frames.h170
-rw-r--r--converter/ppm/ppmtompeg/headers/iframe.h118
-rw-r--r--converter/ppm/ppmtompeg/headers/motion_search.h3
-rw-r--r--converter/ppm/ppmtompeg/headers/mpeg.h5
-rw-r--r--converter/ppm/ppmtompeg/headers/mproto.h8
-rw-r--r--converter/ppm/ppmtompeg/headers/param.h97
-rw-r--r--converter/ppm/ppmtompeg/headers/prototypes.h9
-rw-r--r--converter/ppm/ppmtompeg/headers/subsample.h39
-rw-r--r--converter/ppm/ppmtompeg/huff.h34
-rw-r--r--converter/ppm/ppmtompeg/iframe.c225
-rw-r--r--converter/ppm/ppmtompeg/jpeg.c28
-rw-r--r--converter/ppm/ppmtompeg/mheaders.c712
-rw-r--r--converter/ppm/ppmtompeg/mpeg.c120
-rw-r--r--converter/ppm/ppmtompeg/noparallel.c2
-rw-r--r--converter/ppm/ppmtompeg/parallel.c10
-rw-r--r--converter/ppm/ppmtompeg/param.c143
-rw-r--r--converter/ppm/ppmtompeg/pframe.c2
-rw-r--r--converter/ppm/ppmtompeg/ppmtompeg.c160
-rw-r--r--converter/ppm/ppmtompeg/psearch.c2
-rw-r--r--converter/ppm/ppmtompeg/rate.c1
-rw-r--r--converter/ppm/ppmtompeg/specifics.c45
-rw-r--r--converter/ppm/ppmtompeg/subsample.c1
-rw-r--r--converter/ppm/ppmtopcx.c1
-rw-r--r--converter/ppm/ppmtopict.c11
-rw-r--r--converter/ppm/ppmtopj.c6
-rw-r--r--converter/ppm/ppmtopjxl.c570
-rw-r--r--converter/ppm/ppmtoterm.c1
-rw-r--r--converter/ppm/ppmtowinicon.c3
-rw-r--r--converter/ppm/ppmtoxpm.c4
-rw-r--r--converter/ppm/ppmtoyuvsplit.c270
-rw-r--r--converter/ppm/rawtoppm.c418
-rw-r--r--converter/ppm/sldtoppm.c726
-rw-r--r--converter/ppm/spctoppm.c7
-rw-r--r--converter/ppm/tgatoppm.c4
-rw-r--r--converter/ppm/winicontoppm.c5
-rw-r--r--converter/ppm/ximtoppm.c4
-rw-r--r--converter/ppm/xpmtoppm.c15
-rw-r--r--converter/ppm/xvminitoppm.c10
-rw-r--r--converter/ppm/yuvsplittoppm.c2
65 files changed, 5386 insertions, 5250 deletions
diff --git a/converter/ppm/411toppm.c b/converter/ppm/411toppm.c
index a5b25ac1..6ece4c4b 100644
--- a/converter/ppm/411toppm.c
+++ b/converter/ppm/411toppm.c
@@ -58,6 +58,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "shhopt.h"
 #include "mallocvar.h"
diff --git a/converter/ppm/Makefile b/converter/ppm/Makefile
index 31ca826b..adc3a400 100644
--- a/converter/ppm/Makefile
+++ b/converter/ppm/Makefile
@@ -5,7 +5,7 @@ endif
 SUBDIR = converter/ppm
 VPATH=.:$(SRCDIR)/$(SUBDIR)
 
-include $(BUILDDIR)/Makefile.config
+include $(BUILDDIR)/config.mk
 
 SUBDIRS = hpcdtoppm ppmtompeg
 
@@ -42,7 +42,7 @@ MERGE_OBJECTS = $(BINARIES:%=%.o2)
 .PHONY: all
 all: $(BINARIES) $(SUBDIRS:%=%/all)
 
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
 
 ppmtobmp.o ppmtobmp.o2: bmp.h
 
diff --git a/converter/ppm/eyuvtoppm.c b/converter/ppm/eyuvtoppm.c
index dcbb9547..33d57409 100644
--- a/converter/ppm/eyuvtoppm.c
+++ b/converter/ppm/eyuvtoppm.c
@@ -34,6 +34,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "shhopt.h"
 #include "mallocvar.h"
diff --git a/converter/ppm/hpcdtoppm/Makefile b/converter/ppm/hpcdtoppm/Makefile
index 9a7c67d0..ddf79ee5 100644
--- a/converter/ppm/hpcdtoppm/Makefile
+++ b/converter/ppm/hpcdtoppm/Makefile
@@ -5,21 +5,21 @@ endif
 SUBDIR = converter/ppm/hpcdtoppm
 VPATH=.:$(SRCDIR)/$(SUBDIR)
 
-include $(BUILDDIR)/Makefile.config
+include $(BUILDDIR)/config.mk
 
 all: hpcdtoppm
 
 SCRIPTS = hpcdtoppm pcdovtoppm
 MERGE_OBJECTS =
 
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
 
 install: install.bin.local
 .PHONY: install.bin.local
 install.bin.local: $(PKGDIR)/bin
 # In June 2002, pcdovtoppm replaced pcdindex
 	cd $(PKGDIR)/bin ; \
-	$(SYMLINK) pcdindex$(EXE) pcdovtoppm
+	$(SYMLINK) pcdindex$(EXE) pcdovtoppm$(EXE)
 
 
 FORCE:
diff --git a/converter/ppm/ilbmtoppm.c b/converter/ppm/ilbmtoppm.c
index 5001741a..5ceb70b6 100644
--- a/converter/ppm/ilbmtoppm.c
+++ b/converter/ppm/ilbmtoppm.c
@@ -1,4 +1,4 @@
-/* ilbmtoppm.c - read an IFF ILBM file and produce a portable pixmap
+/* ilbmtoppm.c - read an IFF ILBM file and produce a PPM
 **
 ** Copyright (C) 1989 by Jef Poskanzer.
 **
@@ -43,11 +43,10 @@
 #include <string.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
-#include "ilbm.h"
 #include "mallocvar.h"
-
-/*#define DEBUG*/
+#include "intcode.h"
+#include "ilbm.h"
+#include "ppm.h"
 
 typedef struct {
     int reg;            /* color register to change */
@@ -764,10 +763,15 @@ multi_free(cmap)
  ****************************************************************************/
 
 static void
-check_cmap(bmhd, cmap)
-    BitMapHeader *bmhd;
-    ColorMap *cmap;
-{
+prepareCmap(const BitMapHeader * const bmhd,
+            ColorMap *           const cmap) {
+/*----------------------------------------------------------------------------
+   This is a really ugly subroutine that 1) analyzes a colormap and its
+   context (returning the analysis in global variables); and 2) modifies that
+   color map, because it's really one type of data structure as input and
+   another as output.
+
+-----------------------------------------------------------------------------*/
     pixval colmaxval = 0;
     int shifted = 1;
     int i, r, g, b;
@@ -990,6 +994,8 @@ std_to_ppm(FILE *         const ifp,
            ColorMap *     const cmap, 
            long           const viewportmodes);
 
+
+
 static void
 ham_to_ppm(FILE *         const ifp, 
            long           const chunksize, 
@@ -1255,7 +1261,7 @@ dcol_to_ppm(FILE *         const ifP,
     unsigned int const greenplanes = dcol->g;
     unsigned int const blueplanes  = dcol->b;
     
-    int col, row, i;
+    int col, row;
     rawtype *Rrow, *Grow, *Brow;
     pixval maxval, redmaxval, greenmaxval, bluemaxval;
     pixval *redtable, *greentable, *bluetable;
@@ -1301,13 +1307,15 @@ dcol_to_ppm(FILE *         const ifP,
     MALLOCARRAY_NOFAIL(greentable, greenmaxval +1);
     MALLOCARRAY_NOFAIL(bluetable,  bluemaxval  +1);
 
-    for( i = 0; i <= redmaxval; i++ )
-        redtable[i] = (i * maxval + redmaxval/2)/redmaxval;
-    for( i = 0; i <= greenmaxval; i++ )
-        greentable[i] = (i * maxval + greenmaxval/2)/greenmaxval;
-    for( i = 0; i <= bluemaxval; i++ )
-        bluetable[i] = (i * maxval + bluemaxval/2)/bluemaxval;
-
+    {
+        unsigned int i;
+        for (i = 0; i <= redmaxval; ++i)
+            redtable[i] = ROUNDDIV(i * maxval, redmaxval);
+        for (i = 0; i <= greenmaxval; ++i)
+            greentable[i] = ROUNDDIV(i * maxval, greenmaxval);
+        for (i = 0; i <= bluemaxval; ++i)
+            bluetable[i] = ROUNDDIV(i * maxval, bluemaxval);
+    }
     if( transpName ) {
         MALLOCVAR_NOFAIL(transpColor);
         *transpColor = ppm_parsecolor(transpName, maxval);
@@ -1343,16 +1351,10 @@ dcol_to_ppm(FILE *         const ifP,
 
 
 static void
-cmap_to_ppm(cmap)
-    ColorMap *cmap;
-{
-    ppm_colorrowtomapfile(stdout, cmap->color, cmap->ncolors, MAXCOLVAL);
-#if 0
-    int i;
-    ppm_writeppminit(stdout, cmap->ncolors, 1, MAXCOLVAL, 1);
-    for( i = 0; i < cmap->ncolors; i++ )
-        ppm_writeppmrow(stdout, &(cmap->color[i]), 1, MAXCOLVAL, 1);
-#endif
+cmapToPpm(FILE *     const ofP,
+            ColorMap * const cmapP) {
+
+    ppm_colorrowtomapfile(ofP, cmapP->color, cmapP->ncolors, MAXCOLVAL);
 }
 
 
@@ -1657,39 +1659,41 @@ PCHG_DecompHuff(src, dest, tree, origsize)
 }
 
 
+
 static void
-PCHG_Decompress(PCHG, CompHdr, compdata, compsize, comptree, data)
-    PCHGHeader *PCHG;
-    PCHGCompHeader *CompHdr;
-    unsigned char *compdata;
-    unsigned long compsize;
-    unsigned char *comptree;
-    unsigned char *data;
-{
-    short *hufftree;
-    unsigned long huffsize, i;
-    unsigned long treesize = CompHdr->CompInfoSize;
+PCHG_Decompress(PCHGHeader *     const PCHG,
+                PCHGCompHeader * const CompHdr,
+                unsigned char *  const compdata,
+                unsigned long    const compsize,
+                unsigned char *  const comptree,
+                unsigned char *  const data) {
 
-    switch( PCHG->Compression ) {
-        case PCHG_COMP_HUFFMAN:
+    switch(PCHG->Compression) {
+    case PCHG_COMP_HUFFMAN: {
+        unsigned long const treesize = CompHdr->CompInfoSize;
+        unsigned long const huffsize = treesize / 2;
+        const bigend16 * const bigendComptree = (const void *)comptree;
 
-#ifdef DEBUG
-            pm_message("PCHG Huffman compression");
-#endif
-            /* turn big-endian 2-byte shorts into native format */
-            huffsize = treesize/2;
-            MALLOCARRAY_NOFAIL(hufftree, huffsize);
-            for( i = 0; i < huffsize; i++ ) {
-                hufftree[i] = (short)BIG_WORD(comptree);
-                comptree += 2;
-            }
+        short * hufftree;
+        unsigned long i;
 
-            /* decompress the change structure data */
-            PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1], 
-                            CompHdr->OriginalDataSize);
+        /* Convert big-endian 2-byte shorts to C shorts */
 
-            free(hufftree);
-            break;
+        MALLOCARRAY(hufftree, huffsize);
+
+        if (!hufftree)
+            pm_error("Couldn't get memory for %lu-byte Huffman tree",
+                     huffsize);
+
+        for (i = 0; i < huffsize; ++i)
+            hufftree[i] = pm_uintFromBigend16(bigendComptree[i]);
+
+        /* decompress the change structure data */
+        PCHG_DecompHuff(compdata, data, &hufftree[huffsize-1], 
+                        CompHdr->OriginalDataSize);
+        
+        free(hufftree);
+    } break;
         default:
             pm_error("unknown PCHG compression type %d", PCHG->Compression);
     }
@@ -1798,94 +1802,119 @@ fail2:
 }
 
 
+
 static void
-PCHG_ConvertBig(PCHG, cmap, mask, datasize)
-    PCHGHeader *PCHG;
-    ColorMap *cmap;
-    unsigned char *mask;
-    unsigned long datasize;
-{
-    unsigned char *data;
+PCHG_ConvertBig(PCHGHeader *    const PCHG,
+                ColorMap *      const cmap,
+                unsigned char * const maskStart,
+                unsigned long   const datasize) {
+
+    unsigned char * data;
     unsigned char thismask;
-    int bits, row, i, changes, masklen, reg;
-    unsigned long totalchanges = 0;
-    int changedlines = PCHG->ChangedLines;
+    int bits;
+    unsigned int row;
+    int changes;
+    int masklen;
+    int reg;
+    unsigned long totalchanges;
+    int changedlines;
+    unsigned long dataRemaining;
+    unsigned char * mask;
+
+    mask = maskStart;  /* initial value */
+    dataRemaining = datasize;  /* initial value */
+    changedlines = PCHG->ChangedLines;  /* initial value */
+    totalchanges = 0;  /* initial value */
 
     masklen = 4 * MaskLongWords(PCHG->LineCount);
-    data = mask + masklen; datasize -= masklen;
+    data = mask + masklen; dataRemaining -= masklen;
 
-    bits = 0;
-    for( row = PCHG->StartLine; changedlines && row < 0; row++ ) {
-        if( bits == 0 ) {
-            if( masklen == 0 ) goto fail2;
+    for (row = PCHG->StartLine, bits = 0; changedlines && row < 0; ++row) {
+        if (bits == 0) {
+            if (masklen == 0)
+                pm_error("insufficient data in line mask");
             thismask = *mask++;
             --masklen;
             bits = 8;
         }
-        if( thismask & (1<<7) ) {
-            if( datasize < 2 ) goto fail;
-            changes = BIG_WORD(data); data += 2; datasize -= 2;
+        if (thismask & (1<<7)) {
+            unsigned int i;
+
+            if (dataRemaining < 2)
+                pm_error("insufficient data in BigLineChanges structures");
+
+            changes = BIG_WORD(data); data += 2; dataRemaining -= 2;
+
+            for (i = 0; i < changes; ++i) {
+                if (totalchanges >= PCHG->TotalChanges)
+                    pm_error("insufficient data in BigLineChanges structures");
+
+                if (dataRemaining < 6)
+                    pm_error("insufficient data in BigLineChanges structures");
 
-            for( i = 0; i < changes; i++ ) {
-                if( totalchanges >= PCHG->TotalChanges ) goto fail;
-                if( datasize < 6 ) goto fail;
                 reg = BIG_WORD(data); data += 2;
                 cmap->mp_init[reg - PCHG->MinReg].reg = reg;
                 ++data; /* skip alpha */
                 cmap->mp_init[reg - PCHG->MinReg].r = *data++;
                 cmap->mp_init[reg - PCHG->MinReg].b = *data++;  /* yes, RBG */
                 cmap->mp_init[reg - PCHG->MinReg].g = *data++;
-                datasize -= 6;
+                dataRemaining -= 6;
                 ++totalchanges;
             }
             --changedlines;
         }
         thismask <<= 1;
-        bits--;
+        --bits;
     }
 
-    for( row = PCHG->StartLine; changedlines && row < cmap->mp_rows; row++ ) {
-        if( bits == 0 ) {
-            if( masklen == 0 ) goto fail2;
+    for (row = PCHG->StartLine; changedlines && row < cmap->mp_rows; ++row) {
+        if (bits == 0) {
+            if (masklen == 0)
+                pm_error("insufficient data in line mask");
+
             thismask = *mask++;
             --masklen;
             bits = 8;
         }
-        if( thismask & (1<<7) ) {
-            if( datasize < 2 ) goto fail;
-            changes = BIG_WORD(data); data += 2; datasize -= 2;
+        if (thismask & (1<<7)) {
+            unsigned int i;
+
+            if (dataRemaining < 2)
+                pm_error("insufficient data in BigLineChanges structures");
+
+            changes = BIG_WORD(data); data += 2; dataRemaining -= 2;
 
             MALLOCARRAY_NOFAIL(cmap->mp_change[row], changes + 1);
-            for( i = 0; i < changes; i++ ) {
-                if( totalchanges >= PCHG->TotalChanges ) goto fail;
-                if( datasize < 6 ) goto fail;
+            for (i = 0; i < changes; ++i) {
+                if (totalchanges >= PCHG->TotalChanges)
+                    pm_error("insufficient data in BigLineChanges structures");
+
+                if (dataRemaining < 6)
+                    pm_error("insufficient data in BigLineChanges structures");
+
                 reg = BIG_WORD(data); data += 2;
                 cmap->mp_change[row][i].reg = reg;
                 ++data; /* skip alpha */
                 cmap->mp_change[row][i].r = *data++;
                 cmap->mp_change[row][i].b = *data++;    /* yes, RBG */
                 cmap->mp_change[row][i].g = *data++;
-                datasize -= 6;
+                dataRemaining -= 6;
                 ++totalchanges;
             }
             cmap->mp_change[row][changes].reg = MP_REG_END;
             --changedlines;
         }
         thismask <<= 1;
-        bits--;
+        --bits;
     }
-    if( totalchanges != PCHG->TotalChanges )
+    if (totalchanges != PCHG->TotalChanges)
         pm_message("warning - got %ld change structures, "
                    "chunk header reports %ld", 
                    totalchanges, PCHG->TotalChanges);
-    return;
-fail:
-    pm_error("insufficient data in BigLineChanges structures");
-fail2:
-    pm_error("insufficient data in line mask");
 }
 
 
+
 static void
 read_pchg(FILE *     const ifp,
           IFF_ID     const iffid,
@@ -1939,7 +1968,7 @@ read_pchg(FILE *     const ifp,
             read_bytes(ifp, treesize, comptree, iffid, &remainingChunksize);
 
             compsize = remainingChunksize;
-            MALLOCARRAY_NOFAIL(compdata, remainingChunksize);
+            MALLOCARRAY_NOFAIL(compdata, compsize);
             read_bytes(ifp, compsize, compdata, iffid, &remainingChunksize);
 
             datasize = CompHdr.OriginalDataSize;
@@ -2033,7 +2062,7 @@ process_body( FILE *          const ifp,
         pm_error("%s chunk without %s chunk", 
                  ID2string(ID_BODY), ID2string(ID_BMHD));
 
-    check_cmap(bmhdP, cmap);
+    prepareCmap(bmhdP, cmap);
 
     pixelrow = ppm_allocrow(bmhdP->w);
     if( maskfile ) {
@@ -2081,21 +2110,21 @@ process_body( FILE *          const ifp,
 
 
 static void 
-process_chunk(FILE *          const ifp,
-              long            const formsize,
-              IFF_ID          const ignorelist[],
-              unsigned int    const ignorecount,
-              int             const fakeviewport,
-              int             const viewportmask,
-              int             const isdeepopt,
-              bool            const cmaponly,
-              bool *          const bodyChunkProcessedP,
-              bool *          const endchunkP,
-              BitMapHeader ** const bmhdP,
-              ColorMap *      const cmap,
-              DirectColor **  const dcolP,
-              int *           const viewportmodesP,
-              long *          const bytesReadP
+processChunk(FILE *          const ifP,
+             long            const formsize,
+             IFF_ID          const ignorelist[],
+             unsigned int    const ignorecount,
+             int             const fakeviewport,
+             int             const viewportmask,
+             int             const isdeepopt,
+             bool            const cmaponly,
+             bool *          const bodyChunkProcessedP,
+             bool *          const endchunkP,
+             BitMapHeader ** const bmhdP,
+             ColorMap *      const cmap,
+             DirectColor **  const dcolP,
+             int *           const viewportmodesP,
+             long *          const bytesReadP
     ) {
 
     IFF_ID iffid;
@@ -2104,129 +2133,168 @@ process_chunk(FILE *          const ifp,
 
     bytesread = 0;
 
-    iffid = get_big_long(ifp, ID_FORM, NULL);
-    chunksize = get_big_long(ifp, iffid, NULL);
+    iffid = get_big_long(ifP, ID_FORM, NULL);
+    chunksize = get_big_long(ifP, iffid, NULL);
     bytesread += 8;
 
     if (debug)
-        pm_message("reading %s chunk: %ld bytes", 
-                   ID2string(iffid), chunksize);
+        pm_message("reading %s chunk: %ld bytes", ID2string(iffid), chunksize);
 
-    if( ignored_iffid(iffid, ignorelist, ignorecount) ) {
+    if (ignored_iffid(iffid, ignorelist, ignorecount)) {
         pm_message("ignoring %s chunk", ID2string(iffid));
-        skip_chunk(ifp, iffid, chunksize);
-    } else if( iffid == ID_END ) {
+        skip_chunk(ifP, iffid, chunksize);
+    } else if (iffid == ID_END) {
         /* END chunks are not officially valid in IFF, but
            suggested as a future expansion for stream-writing,
            see Amiga RKM Devices, 3rd Ed, page 376 
         */
-        if( chunksize != 0 ) {
+        if (chunksize != 0 ) {
             pm_message("warning - non-0 %s chunk", ID2string(iffid));
-            skip_chunk(ifp, iffid, chunksize);
+            skip_chunk(ifP, iffid, chunksize);
         }
-        if( formsize != 0xffffffff )
+        if (formsize != 0xffffffff)
             pm_message("warning - %s chunk with FORM size 0x%08lx "
                        "(should be 0x%08x)",
                        ID2string(iffid), formsize, 0xffffffff);
         *endchunkP = 1;
-    } else if( *bodyChunkProcessedP ) {
+    } else if (*bodyChunkProcessedP) {
         pm_message("%s chunk found after %s chunk - skipping", 
                    ID2string(iffid), ID2string(ID_BODY));
-        skip_chunk(ifp, iffid, chunksize);
+        skip_chunk(ifP, iffid, chunksize);
     } else
-        switch( iffid ) {
+        switch (iffid) {
         case ID_BMHD:
-            *bmhdP = read_bmhd(ifp, iffid, chunksize);
+            *bmhdP = read_bmhd(ifP, iffid, chunksize);
             break;
         case ID_CMAP:
-            read_cmap(ifp, iffid, chunksize, cmap);
+            read_cmap(ifP, iffid, chunksize, cmap);
             break;
         case ID_CMYK:
-            read_cmyk(ifp, iffid, chunksize, cmap);
+            read_cmyk(ifP, iffid, chunksize, cmap);
             break;
         case ID_CLUT:
-            read_clut(ifp, iffid, chunksize, cmap);
+            read_clut(ifP, iffid, chunksize, cmap);
             break;
         case ID_CAMG:
-            if( chunksize != CAMGChunkSize )
+            if (chunksize != CAMGChunkSize)
                 pm_error("%s chunk size mismatch", ID2string(iffid));
-            *viewportmodesP = get_big_long(ifp, ID_CAMG, NULL);
+            *viewportmodesP = get_big_long(ifP, ID_CAMG, NULL);
             *viewportmodesP &= viewportmask;      /* -isnotham/-isnotehb */
             break;
         case ID_PCHG:
-            read_pchg(ifp, iffid, chunksize, cmap);
+            read_pchg(ifP, iffid, chunksize, cmap);
             break;
         case ID_CTBL:
         case ID_SHAM:
-            read_4bit_mp(ifp, iffid, chunksize, cmap);
+            read_4bit_mp(ifP, iffid, chunksize, cmap);
             break;
         case ID_DCOL:
-            if( chunksize != DirectColorSize )
+            if (chunksize != DirectColorSize)
                 pm_error("%s chunk size mismatch", ID2string(iffid));
             MALLOCVAR_NOFAIL(*dcolP);
-            (*dcolP)->r = get_byte(ifp, iffid, NULL);
-            (*dcolP)->g = get_byte(ifp, iffid, NULL);
-            (*dcolP)->b = get_byte(ifp, iffid, NULL);
-            (void)get_byte(ifp, iffid, NULL);       /* skip pad byte */
+            (*dcolP)->r = get_byte(ifP, iffid, NULL);
+            (*dcolP)->g = get_byte(ifP, iffid, NULL);
+            (*dcolP)->b = get_byte(ifP, iffid, NULL);
+            get_byte(ifP, iffid, NULL);       /* skip pad byte */
             break;
         case ID_BODY: 
-            if( cmaponly || (*bmhdP && (*bmhdP)->nPlanes == 0 )) {
-                skip_chunk(ifp, ID_BODY,  chunksize);
-                return;
-            }
-    
-            process_body(ifp, chunksize, *bmhdP, cmap, 
-                         maskfile, fakeviewport, isdeepopt, *dcolP,
-                         viewportmodesP);
-
-            *bodyChunkProcessedP = TRUE;
+            if (cmaponly || (*bmhdP && (*bmhdP)->nPlanes == 0))
+                skip_chunk(ifP, ID_BODY,  chunksize);
+            else {
+                process_body(ifP, chunksize, *bmhdP, cmap, 
+                             maskfile, fakeviewport, isdeepopt, *dcolP,
+                             viewportmodesP);
 
-            break;
+                *bodyChunkProcessedP = TRUE;
+            } break;
         case ID_GRAB:   case ID_DEST:   case ID_SPRT:   case ID_CRNG:
         case ID_CCRT:   case ID_DYCP:   case ID_DPPV:   case ID_DRNG:
         case ID_EPSF:   case ID_JUNK:   case ID_CNAM:   case ID_PRVW:
         case ID_TINY:   case ID_DPPS:
-            skip_chunk(ifp, iffid, chunksize);
+            skip_chunk(ifP, iffid, chunksize);
             break;
         case ID_copy:   case ID_AUTH:   case ID_NAME:   case ID_ANNO:
         case ID_TEXT:   case ID_FVER:
-            if( verbose )
-                display_chunk(ifp, iffid, chunksize);
+            if (verbose)
+                display_chunk(ifP, iffid, chunksize);
             else
-                skip_chunk(ifp, iffid, chunksize);
+                skip_chunk(ifP, iffid, chunksize);
             break;
-        case ID_DPI:
-        {
+        case ID_DPI: {
             int x, y;
 
-            x = get_big_short(ifp, ID_DPI, NULL);
-            y = get_big_short(ifp, ID_DPI, NULL);
-            if( verbose )
+            x = get_big_short(ifP, ID_DPI, NULL);
+            y = get_big_short(ifP, ID_DPI, NULL);
+            if (verbose)
                 pm_message("%s chunk:  dpi_x = %d    dpi_y = %d", 
                            ID2string(ID_DPI), x, y);
-        }
-        break;
+        } break;
         default:
             pm_message("unknown chunk type %s - skipping", 
                        ID2string(iffid));
-            skip_chunk(ifp, iffid, chunksize);
+            skip_chunk(ifP, iffid, chunksize);
             break;
         }
 
     bytesread += chunksize;
 
-    if( ODD(chunksize) ) {
-        (void) get_byte(ifp, iffid, NULL);
+    if (ODD(chunksize)) {
+        get_byte(ifP, iffid, NULL);
         bytesread += 1;
     } 
     *bytesReadP = bytesread;
 }
 
 
+
+static void
+maybeWriteColorMap(FILE *               const ofP,
+                   const BitMapHeader * const bmhdP,
+                   ColorMap *           const cmapP,
+                   bool                 const bodyChunkProcessed,
+                   bool                 const cmaponly) {
+/*----------------------------------------------------------------------------
+   Write to file *ofP the color map *cmapP as a PPM, if appropriate.
+
+   The logic (not just here -- in the program as a whole) for deciding whether
+   to write the image or the colormap is quite twisted.  If I thought anyone
+   was actually using this program, I would take the time to straighten it
+   out.
+
+   What's really sick about this subroutine is that in choosing to write
+   a color map, it has to know that Caller hasn't already written
+   the image.  Huge modularity violation.
+-----------------------------------------------------------------------------*/
+    if (cmaponly) {
+        if (HAS_COLORMAP(cmapP)) {
+            prepareCmap(bmhdP, cmapP);
+            cmapToPpm(ofP, cmapP);
+        } else
+            pm_error("You specified -cmaponly, but the ILBM "
+                     "has no colormap");
+    } else if (bmhdP && bmhdP->nPlanes == 0) {
+        if (HAS_COLORMAP(cmapP)) {
+            prepareCmap(bmhdP, cmapP);
+            cmapToPpm(ofP, cmapP);
+        } else
+            pm_error("ILBM has neither a color map nor color planes");
+    } else if (!bodyChunkProcessed) {
+        if (HAS_COLORMAP(cmapP)) {
+            pm_message("input is a colormap file");
+            prepareCmap(bmhdP, cmapP);
+            cmapToPpm(ofP, cmapP);
+        } else
+            pm_error("ILBM has neither %s or %s chunk", 
+                     ID2string(ID_BODY), ID2string(ID_CMAP));
+    }
+}
+
+
+
 int
 main(int argc, char *argv[]) {
 
-    FILE *ifp;
+    FILE * ifP;
     int argn;
     short cmaponly = 0, isdeepopt = 0;
     bool endchunk;
@@ -2300,25 +2368,25 @@ main(int argc, char *argv[]) {
     }    
 
     if( argn < argc ) {
-        ifp = pm_openr( argv[argn] );
+        ifP = pm_openr( argv[argn] );
         argn++;
     } else
-        ifp = stdin;
+        ifP = stdin;
 
     if( argn != argc )
         pm_usage(usage);
 
     /* Read in the ILBM file. */
 
-    firstIffid = get_big_long(ifp, ID_FORM, NULL);
-    if( firstIffid != ID_FORM )
+    firstIffid = get_big_long(ifP, ID_FORM, NULL);
+    if (firstIffid != ID_FORM)
         pm_error("input is not a FORM type IFF file");
-    formsize = get_big_long(ifp, ID_FORM, NULL);
-    typeid = get_big_long(ifp, ID_FORM, NULL);
-    if( typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 && 
-        typeid != ID_PBM )
-        pm_error( "input is not an ILBM, RGBN, RGB8 or PBM "
-                  "type FORM IFF file" );
+    formsize = get_big_long(ifP, ID_FORM, NULL);
+    typeid = get_big_long(ifP, ID_FORM, NULL);
+    if (typeid != ID_ILBM && typeid != ID_RGBN && typeid != ID_RGB8 && 
+        typeid != ID_PBM)
+        pm_error("input is not an ILBM, RGBN, RGB8 or PBM "
+                 "type FORM IFF file");
     bytesread = 4;  /* FORM and formsize do not count */
 
     cmap = alloc_cmap();
@@ -2326,55 +2394,41 @@ main(int argc, char *argv[]) {
     /* Main loop, parsing the IFF FORM. */
     bodyChunkProcessed = FALSE;
     endchunk = FALSE;
-    while( !endchunk && formsize-bytesread >= 8 ) {
-        long bytes_read_for_chunk;
+    while (!endchunk && formsize-bytesread >= 8) {
+        long bytesReadForChunk;
 
-        process_chunk(ifp, formsize, ignorelist, ignorecount,
-                      fakeviewport, viewportmask,
-                      isdeepopt, cmaponly,
-                      &bodyChunkProcessed,
-                      &endchunk, &bmhdP, cmap, &dcol,
-                      &viewportmodes, &bytes_read_for_chunk);
+        processChunk(ifP, formsize, ignorelist, ignorecount,
+                     fakeviewport, viewportmask,
+                     isdeepopt, cmaponly,
+                     &bodyChunkProcessed,
+                     &endchunk, &bmhdP, cmap, &dcol,
+                     &viewportmodes, &bytesReadForChunk);
 
-        bytesread += bytes_read_for_chunk;
+        bytesread += bytesReadForChunk;
     }
 
-    if( maskfile ) {
+    if (maskfile) {
         pm_close(maskfile);
-        if( !wrotemask )
+        if (!wrotemask)
             remove(maskname);
         pbm_freerow(maskrow);
     }
 
-    if( cmaponly || (bmhdP && bmhdP->nPlanes == 0 )) {
-        if( HAS_COLORMAP(cmap) ) {
-            check_cmap(bmhdP, cmap);
-            cmap_to_ppm(cmap);
-        } else
-            pm_error("no colormap");
-    } else if( !bodyChunkProcessed ) {
-        if( HAS_COLORMAP(cmap) ) {
-            pm_message("input is a colormap file");
-            check_cmap(bmhdP, cmap);
-            cmap_to_ppm(cmap);
-        } else
-            pm_error("no %s or %s chunk found", 
-                     ID2string(ID_BODY), ID2string(ID_CMAP));
-    }
+    maybeWriteColorMap(stdout, bmhdP, cmap, bodyChunkProcessed, cmaponly);
 
     {
         unsigned int skipped;
         
-        for( skipped = 0; fgetc(ifp) != EOF; ++skipped )
-            bytesread++;
+        for (skipped = 0; fgetc(ifP) != EOF; ++skipped)
+            ++bytesread;
 
-        if( skipped > 0 )
+        if (skipped > 0)
             pm_message("skipped %u extraneous byte%s after last chunk",
                        skipped, (skipped == 1 ? "" : "s"));
     }
-    pm_close(ifp);
+    pm_close(ifP);
 
-    if( !endchunk && bytesread != formsize ) {
+    if (!endchunk && bytesread != formsize) {
         pm_message("warning - file length/FORM size field mismatch "
                    "(%ld != %ld+8)",
                    bytesread+8 /* FORM+size */, formsize);
diff --git a/converter/ppm/mitsu.h b/converter/ppm/mitsu.h
index 8676a39d..bca4fbdf 100644
--- a/converter/ppm/mitsu.h
+++ b/converter/ppm/mitsu.h
@@ -1,7 +1,6 @@
 #ifndef MITSU_H_INCLUDED
 #define MITSU_H_INCLUDED
 
-/* static char SCCSid[] = "@(#)mitsu.h\t\t1.3\t(SPZ)\t3/11/92\n"; */
 #define MAXLUTCOL   255
 
 #define A4_MAXCOLS  1184
diff --git a/converter/ppm/pcxtoppm.c b/converter/ppm/pcxtoppm.c
index 9f403538..25a81531 100644
--- a/converter/ppm/pcxtoppm.c
+++ b/converter/ppm/pcxtoppm.c
@@ -31,6 +31,7 @@
  *  - moved check of 16-color-palette into pcx_16col_to_ppm(),
  *    now checks if it contains only a single color
  */
+#include "pm_c_util.h"
 #include "mallocvar.h"
 #include "shhopt.h"
 #include "ppm.h"
diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c
index d52963fc..9a7d8e7c 100644
--- a/converter/ppm/picttoppm.c
+++ b/converter/ppm/picttoppm.c
@@ -94,16 +94,16 @@ struct rgbPlanes {
     word * blu;
 };
 
+struct canvas {
+    struct rgbPlanes planes;
+};
+
 typedef void (*transfer_func) (struct RGBColor* src, struct RGBColor* dst);
 
-static const char* stage;
+static const char * stage;
 static struct Rect picFrame;
-static word* red;
-static word* green;
-static word* blue;
 static word rowlen;
 static word collen;
-static longword planelen;
 static int verbose;
 static int fullres;
 static int recognize_comment;
@@ -142,13 +142,6 @@ static int ps_cent_x;
 static int ps_cent_y;
 static int ps_cent_set;
 
-struct opdef {
-    const char* name;
-    int len;
-    void (*impl) (int);
-    const char* description;
-};
-
 struct raster {
 /*----------------------------------------------------------------------------
    An image raster.  May be either truecolor or paletted.
@@ -178,13 +171,28 @@ struct raster {
 };
 
 
+
 static void
 allocateRaster(struct raster * const rasterP,
                unsigned int    const width,
                unsigned int    const height,
                unsigned int    const bitsPerPixel) {
+/*----------------------------------------------------------------------------
+   Allocate storage for a raster that can contain a 'width' x 'height'
+   pixel rectangle read from a PICT image with 'bitsPerPixel' bits
+   per pixel.
+
+   Make the space large enough to round the number of pixels up to a
+   multiple of 16, because we've seen many images in which the PICT raster
+   does contain that much padding on the right.  I don't know why; I could
+   understand a multiple of 8, since in 1 bpp image, the smallest unit
+   expressable in PICT is 8 pixels.  But why 16?  The images we saw came
+   from Adobe Illustrator 10 in March 2007, supplied by
+   Guillermo Gómez Valcárcel.
+-----------------------------------------------------------------------------*/
+    unsigned int const allocWidth = ROUNDUP(width, 16);
 
-    if (width > UINT_MAX/4)
+    if (width > UINT_MAX/4 - 16)
         pm_error("Width %u pixels too large for arithmetic", width);
 
     rasterP->rowCount = height;
@@ -209,16 +217,16 @@ allocateRaster(struct raster * const rasterP,
            We have yet to see if we can properly interpret the data.
         */
 
-        rasterP->rowSize = width * 4;
+        rasterP->rowSize = allocWidth * 4;
         break;
     case 16:
-        rasterP->rowSize = width * 2;
+        rasterP->rowSize = allocWidth * 2;
         break;
     case 8:
     case 4:
     case 2:
     case 1:
-        rasterP->rowSize = width * 1;
+        rasterP->rowSize = allocWidth * 1;
         break;
     default:
         pm_error("INTERNAL ERROR: impossible bitsPerPixel value in "
@@ -248,13 +256,30 @@ struct blit_info {
     struct raster      srcplane;
     int                pixSize;
     struct Rect        dstRect;
-    struct RGBColor *  color_map;
+    struct RGBColor *  colorMap;
     int                mode;
     struct blit_info * next;
 };
 
-static struct blit_info* blit_list = 0;
-static struct blit_info** last_bl = &blit_list;
+typedef struct {
+    struct blit_info * firstP;
+    struct blit_info ** connectorP;
+    bool unblittableText;
+        /* The image contains text opcodes, and we don't know how to put that
+           in a blit list (I really don't even know what a blit _is_), so
+           the image information here is incomplete.
+        */
+} blitList;
+
+
+typedef void (drawFn)(struct canvas *, blitList *, int);
+
+struct opdef {
+    const char* name;
+    int len;
+    drawFn * impl;
+    const char* description;
+};
 
 #define WORD_LEN (-1)
 
@@ -589,15 +614,25 @@ picComment(word const type,
 
 
 
+static drawFn ShortComment;
+
 static void
-ShortComment(int const version) {
+ShortComment(struct canvas * const canvasP,
+             blitList *      const blitListP,
+             int             const version) {
+
     picComment(read_word(), 0);
 }
 
 
 
+static drawFn LongComment;
+
 static void
-LongComment(int const version) {
+LongComment(struct canvas * const canvasP,
+            blitList *      const blitListP,
+            int             const version) {
+
     word type;
 
     type = read_word();
@@ -606,8 +641,13 @@ LongComment(int const version) {
 
 
 
+static drawFn skip_poly_or_region;
+
 static void
-skip_poly_or_region(int const version) {
+skip_poly_or_region(struct canvas * const canvasP,
+                    blitList *      const blitListP,
+                    int             const version) {
+
     stage = "skipping polygon or region";
     skip(read_word() - 2);
 }
@@ -639,56 +679,98 @@ static struct fontinfo** fontlist_ins = &fontlist;
 
 
 
+static void
+tokenize(char *         const s,
+         const char **  const vec,
+         unsigned int   const vecSize,
+         unsigned int * const nTokenP) {
+
+    unsigned int nToken;
+    char * p;
+
+    p = &s[0];   /* start at beginning of string */
+    nToken = 0;  /* no tokens yet */
+
+    while (*p && nToken < vecSize - 1) {
+        if (ISSPACE(*p))
+            *p++ = '\0';
+        else {
+            vec[nToken++] = p;
+            /* Skip to next non-space character or end */
+            while (*p && !ISSPACE(*p))
+                ++p;
+        }
+    }
+    vec[nToken] = NULL;
+
+    *nTokenP = nToken;
+}
+
+
+
+static void
+parseFontLine(const char **      const token,
+              struct fontinfo ** const fontinfoPP) {
+
+    struct fontinfo * fontinfoP;
+
+    MALLOCVAR(fontinfoP);
+    if (fontinfoP == NULL)
+        pm_error("out of memory for font information");
+    MALLOCARRAY(fontinfoP->filename, strlen(token[3] + 1));
+    if (fontinfoP->filename == NULL)
+        pm_error("out of memory for font information file name");
+
+    fontinfoP->font  = atoi(token[0]);
+    fontinfoP->size  = atoi(token[1]);
+    fontinfoP->style = atoi(token[2]);
+    strcpy(fontinfoP->filename, token[3]);
+    fontinfoP->loaded = 0;
+
+    *fontinfoPP = fontinfoP;
+}
+
+
+
 static int 
 load_fontdir(const char * const dirfile) {
 /*----------------------------------------------------------------------------
    Load the font directory from file named 'dirfile'.  Add its contents
    to the global list of fonts 'fontlist'.
 -----------------------------------------------------------------------------*/
-    FILE* fp;
-    int n, nfont;
-    char* arg[5], line[1024];
-    struct fontinfo* fontinfo;
+    FILE * ifP;
+    unsigned int nFont;
+    char line[1024]; 
 
-    if (!(fp = fopen(dirfile, "rb")))
-        return -1;
-    
-    nfont = 0;
-    while (fgets(line, 1024, fp)) {
-        if ((n = mk_argvn(line, arg, 5)) == 0 || arg[0][0] == '#')
-            continue;
-        if (n != 4)
-            continue;
-        MALLOCVAR(fontinfo);
-        if (fontinfo == NULL)
-            pm_error("out of memory for font information");
-        MALLOCARRAY(fontinfo->filename, strlen(arg[3] + 1));
-        if (fontinfo->filename == NULL)
-            pm_error("out of memory for font information file name");
+    ifP = pm_openr(dirfile);
 
-        fontinfo->font = atoi(arg[0]);
-        fontinfo->size = atoi(arg[1]);
-        fontinfo->style = atoi(arg[2]);
-        strcpy(fontinfo->filename, arg[3]);
-        fontinfo->loaded = 0;
+    nFont = 0;
+    while (fgets(line, 1024, ifP) && nFont < INT_MAX) {
+        const char * token[10];
+        unsigned int nToken;
 
-        fontinfo->next = 0;
-        *fontlist_ins = fontinfo;
-        fontlist_ins = &fontinfo->next;
-        nfont++;
-    }
+        tokenize(line, token, ARRAY_SIZE(token), &nToken);
 
-    return nfont;
-}
+        if (nToken == 0) {
+            /* blank line - ignore */
+        } else if (token[0][0] == '#') {
+            /* comment - ignore */
+        } else if (nToken != 4) {
+            /* Unrecognized format - ignore */
+        } else {
+            struct fontinfo * fontinfoP;
 
+            parseFontLine(token, &fontinfoP);
 
+            fontinfoP->next = 0;
+            *fontlist_ins = fontinfoP;
+            fontlist_ins = &fontinfoP->next;
+            ++nFont;
+        }
+    }
+    pm_close(ifP);
 
-static void
-read_rect(struct Rect * const r) {
-    r->top = read_word();
-    r->left = read_word();
-    r->bottom = read_word();
-    r->right = read_word();
+    return nFont;
 }
 
 
@@ -705,6 +787,26 @@ dumpRect(const char * const label,
 
 
 
+static void
+read_rect(struct Rect * const r) {
+
+    r->top    = read_word();
+    r->left   = read_word();
+    r->bottom = read_word();
+    r->right  = read_word();
+
+    if (r->top > r->bottom || r->right < r->left)
+        dumpRect("Invalid rectangle", *r);
+
+    if (r->top > r->bottom)
+        pm_error("Invalid PICT: a rectangle has a top below its bottom");
+    if (r->right < r->left)
+        pm_error("Invalid PICT: a rectangle has a right edge "
+                 "left of its left edge");
+}
+
+
+
 static int
 rectwidth(const struct Rect * const r) {
     return r->right - r->left;
@@ -720,10 +822,10 @@ rectheight(const struct Rect * const r) {
 
 
 static bool
-rectsamesize(const struct Rect * const r1, 
-             const struct Rect * const r2) {
-    return r1->right - r1->left == r2->right - r2->left &&
-           r1->bottom - r1->top == r2->bottom - r2->top ;
+rectsamesize(struct Rect const r1, 
+             struct Rect const r2) {
+    return r1.right - r1.left == r2.right - r2.left &&
+           r1.bottom - r1.top == r2.bottom - r2.top ;
 }
 
 
@@ -753,20 +855,45 @@ rectscale(struct Rect * const r,
 
 
 
-static struct blit_info* 
-add_blit_list(void) {
+static void
+    initBlitList(blitList * const blitListP) {
 
-    struct blit_info * bi;
+    blitListP->firstP          = NULL;
+    blitListP->connectorP      = &blitListP->firstP;
+    blitListP->unblittableText = false;
+}
+
+
+
+static void
+addBlitList(blitList *        const blitListP,
+            struct Rect       const srcRect,
+            struct Rect       const srcBounds,
+            struct raster     const srcplane,
+            int               const pixSize,
+            struct Rect       const dstRect,
+            struct RGBColor * const colorMap,
+            int               const mode) {
+
+    struct blit_info * biP;
     
-    MALLOCVAR(bi);
-    if (bi == NULL)
+    MALLOCVAR(biP);
+    if (biP == NULL)
         pm_error("out of memory for blit list");
-    
-    bi->next = 0;
-    *last_bl = bi;
-    last_bl = &bi->next;
-    
-    return bi;
+    else {
+        biP->srcRect   = srcRect;
+        biP->srcBounds = srcBounds;
+        biP->srcplane  = srcplane;
+        biP->pixSize   = pixSize;
+        biP->dstRect   = dstRect;
+        biP->colorMap  = colorMap;
+        biP->mode      = mode;
+
+        biP->next = NULL;
+
+        *blitListP->connectorP = biP;
+        blitListP->connectorP = &biP->next;
+    }
 }
 
 
@@ -1026,7 +1153,7 @@ static pixval
 redepth(pixval const c,
         pixval const oldMaxval) {
     
-    return (c * PPM_MAXMAXVAL + oldMaxval / 2) / oldMaxval;
+    return ROUNDDIV(c * PPM_MAXMAXVAL, oldMaxval);
 }
 
 
@@ -1245,8 +1372,6 @@ doSameSize(transfer_func           trf,
            struct rgbPlanes  const dst,
            unsigned int      const dstwid) {
 /*----------------------------------------------------------------------------
-   Generalized (but slow) blit.
-
    Transfer pixels from 'src' to 'dst', applying the transfer function
    'trf'.
 
@@ -1419,18 +1544,30 @@ blitIdempotent(unsigned int          const pixSize,
 
 
 static void
-generalBlit(struct Rect       const srcRect, 
-            struct Rect       const srcBounds, 
-            struct raster     const srcplane,
-            int               const pixSize, 
-            struct Rect       const dstRect, 
-            struct Rect       const dstBounds, 
-            int               const dstwid, 
-            struct RGBColor * const color_map, 
-            int               const mode,
-            struct Rect       const clipsrc,
-            struct Rect       const clipdst) {
-    
+doBlit(struct Rect       const srcRect, 
+       struct Rect       const dstRect, 
+       struct Rect       const srcBounds, 
+       struct raster     const srcplane,
+       struct Rect       const dstBounds, 
+       struct rgbPlanes  const canvasPlanes,
+       int               const pixSize, 
+       int               const dstwid, 
+       struct RGBColor * const color_map, 
+       int               const mode) {
+/*----------------------------------------------------------------------------
+   Transfer some pixels from 'srcplane' to 'canvasPlanes', applying the
+   transfer function 'trf'.
+
+   'srcplane' contains the rectangle 'srcBounds' of the image.
+   'canvasPlanes' contains the rectangle 'dstRect' of the image.
+
+   Take the rectangle 'srcRect' of the source image and copy it to the
+   rectangle 'dstRec' of the destination image.
+
+   Each plane of 'canvasPlanes' is one word per pixel and contains actual
+   colors, never a palette index.  It is an array in row-major order
+   with 'dstwid' words per row.
+-----------------------------------------------------------------------------*/
     unsigned char * src;
     struct rgbPlanes dst;
     int dstoff;
@@ -1440,31 +1577,31 @@ generalBlit(struct Rect       const srcRect,
     transfer_func trf;
 
     if (verbose) {
-        dumpRect("copying from:", clipsrc);
-        dumpRect("to:          ", clipdst);
+        dumpRect("copying from:", srcRect);
+        dumpRect("to:          ", dstRect);
         pm_message("a %u x %u area to a %u x %u area",
-                   rectwidth(&clipsrc), rectheight(&clipsrc),
-                   rectwidth(&clipdst), rectheight(&clipdst));
+                   rectwidth(&srcRect), rectheight(&srcRect),
+                   rectwidth(&dstRect), rectheight(&dstRect));
     }
 
     {
         unsigned int const pkpixsize = pixSize == 16 ? 2 : 1;
-        unsigned int const srcRowNumber = clipsrc.top - srcBounds.top;
+        unsigned int const srcRowNumber = srcRect.top - srcBounds.top;
         unsigned int const srcRowOffset =
-            (clipsrc.left - srcBounds.left) * pkpixsize;
+            (srcRect.left - srcBounds.left) * pkpixsize;
         assert(srcRowNumber < srcplane.rowCount);
         assert(srcRowOffset < srcplane.rowSize);
         src = srcplane.bytes + srcRowNumber * srcplane.rowSize + srcRowOffset;
-        xsize = clipsrc.right - clipsrc.left;
-        ysize = clipsrc.bottom - clipsrc.top;
+        xsize = rectwidth(&srcRect);
+        ysize = rectheight(&srcRect);
         srcadd = srcplane.rowSize - xsize * pkpixsize;
     }
 
-    dstoff = (clipdst.top - dstBounds.top) * dstwid +
-        (clipdst.left - dstBounds.left);
-    dst.red = red + dstoff;
-    dst.grn = green + dstoff;
-    dst.blu = blue + dstoff;
+    dstoff = (dstRect.top - dstBounds.top) * dstwid +
+        (dstRect.left - dstBounds.left);
+    dst.red = canvasPlanes.red + dstoff;
+    dst.grn = canvasPlanes.grn + dstoff;
+    dst.blu = canvasPlanes.blu + dstoff;
 
     /* get rid of Text mask mode bit, if (erroneously) set */
     if ((mode & ~64) == 0)
@@ -1472,8 +1609,8 @@ generalBlit(struct Rect       const srcRect,
     else
         trf = transfer(mode & ~64);
 
-    if (!rectsamesize(&clipsrc, &clipdst))
-        doDiffSize(clipsrc, clipdst, pixSize, xsize, ysize,
+    if (!rectsamesize(srcRect, dstRect))
+        doDiffSize(srcRect, dstRect, pixSize, xsize, ysize,
                    trf, color_map, src, srcplane.rowSize, dst, dstwid);
     else {
         if (trf == NULL)
@@ -1491,12 +1628,22 @@ static int
 blit(struct Rect       const srcRect, 
      struct Rect       const srcBounds, 
      struct raster     const srcplane,
+     struct canvas *   const canvasP,
+     blitList *        const blitListP,
      int               const pixSize, 
      struct Rect       const dstRect, 
      struct Rect       const dstBounds, 
      int               const dstwid, 
      struct RGBColor * const color_map, 
      int               const mode) {
+/*----------------------------------------------------------------------------
+   'srcplane' contains the rectangle 'srcBounds' of the image.
+
+   We transfer rectangle 'srcRect' from that.
+
+   if 'blitListP' is non-null, we don't draw anything on 'canvasP'; instead,
+   we add to the list *blitlistP a description of what needs to be drawn.
+-----------------------------------------------------------------------------*/
 
     /* I can't tell what the result value of this function is supposed to mean,
        but I found several return statements that did not set it to anything,
@@ -1511,9 +1658,7 @@ blit(struct Rect       const srcRect,
         retval = 1;
     else {
         /* Almost got it.  Clip source rect with source bounds.
-           clip dest rect with dest bounds.  If source and
-           destination are not the same size, use Pnmscale
-           to get a nicely sized rectangle.
+           clip dest rect with dest bounds.
         */
         struct Rect clipsrc;
         struct Rect clipdst;
@@ -1521,22 +1666,16 @@ blit(struct Rect       const srcRect,
         rectinter(srcBounds, srcRect, &clipsrc);
         rectinter(dstBounds, dstRect, &clipdst);
 
-        if (fullres) {
-            struct blit_info * bi;
-            bi = add_blit_list();
-            bi->srcRect   = clipsrc;
-            bi->srcBounds = srcBounds;
-            bi->srcplane  = srcplane;
-            bi->pixSize   = pixSize;
-            bi->dstRect   = clipdst;
-            bi->color_map = color_map;
-            bi->mode      = mode;
+        if (blitListP) {
+            addBlitList(blitListP,
+                        clipsrc, srcBounds, srcplane, pixSize,
+                        clipdst, color_map, mode);
 
             retval = 0;
         } else {
-            generalBlit(srcRect, srcBounds, srcplane, pixSize,
-                        dstRect, dstBounds, dstwid, color_map, mode,
-                        clipsrc, clipdst);
+            doBlit(clipsrc, clipdst,
+                   srcBounds, srcplane, dstBounds, canvasP->planes,
+                   pixSize, dstwid, color_map, mode);
 
             retval = 1;
         }
@@ -1553,17 +1692,15 @@ blit(struct Rect       const srcRect,
  */
 
 static void 
-allocPlanes(struct rgbPlanes * const planesP) {
-
-    struct rgbPlanes planes;
+allocPlanes(unsigned int       const width,
+            unsigned int       const height,
+            struct rgbPlanes * const planesP) {
 
-    rowlen = picFrame.right - picFrame.left;
-    collen = picFrame.bottom - picFrame.top;
+    unsigned int const planelen = width * height;
 
-    clip_rect = picFrame;
+    struct rgbPlanes planes;
 
-    planelen = rowlen * collen;
-    MALLOCARRAY(planes.red,  planelen);
+    MALLOCARRAY(planes.red, planelen);
     MALLOCARRAY(planes.grn, planelen);
     MALLOCARRAY(planes.blu, planelen);
     if (planes.red == NULL || planes.grn == NULL || planes.blu == NULL)
@@ -1575,14 +1712,6 @@ allocPlanes(struct rgbPlanes * const planesP) {
     memset(planes.blu, 255, planelen * sizeof(word));
 
     *planesP = planes;
-
-    /* Until we wean this program off of global variables, we have to
-       set these:
-    */
-
-    red   = planes.red;
-    green = planes.grn;
-    blue  = planes.blu;
 }
 
 
@@ -1606,9 +1735,31 @@ compact(word const input) {
 
 
 static void
-do_blits(struct rgbPlanes * const planesP) {
+reportBlitList(blitList * const blitListP) {
+
+    if (verbose) {
+        unsigned int count;
+        struct blit_info * biP;
+
+        for (count = 0, biP = blitListP->firstP; biP; biP = biP->next)
+            ++count;
+
+        pm_message("# blits: %u", count);
+    }
+}
+
+
+
+static void
+doBlitList(struct canvas * const canvasP,
+           blitList *      const blitListP) {
+/*----------------------------------------------------------------------------
+   Do the list of blits *blitListP, drawing on canvas *canvasP.
 
-    struct blit_info* bi;
+   We allocate new plane data structures in *canvasP.  We assume it doesn't
+   have them already.
+-----------------------------------------------------------------------------*/
+    struct blit_info * bi;
     int srcwidth, dstwidth, srcheight, dstheight;
     double  scale, scalelow, scalehigh;
     double  xscale = 1.0;
@@ -1616,9 +1767,11 @@ do_blits(struct rgbPlanes * const planesP) {
     double  lowxscale, highxscale, lowyscale, highyscale;
     int     xscalecalc = 0, yscalecalc = 0;
 
+    reportBlitList(blitListP);
+
     fullres = 0;
 
-    for (bi = blit_list; bi; bi = bi->next) {
+    for (bi = blitListP->firstP; bi; bi = bi->next) {
         srcwidth = rectwidth(&bi->srcRect);
         dstwidth = rectwidth(&bi->dstRect);
         srcheight = rectheight(&bi->srcRect);
@@ -1694,29 +1847,34 @@ do_blits(struct rgbPlanes * const planesP) {
     }
 
     if (xscale != 1.0 || yscale != 1.0) {
-        for (bi = blit_list; bi; bi = bi->next)
-            rectscale(&bi->dstRect, xscale, yscale);
+        struct blit_info * biP;
+        
+        for (biP = blitListP->firstP; biP; biP = biP->next)
+            rectscale(&biP->dstRect, xscale, yscale);
 
-        pm_message("Scaling output by %f in X and %f in Y",
-                   xscale, yscale);
+        pm_message("Scaling output by %f in X and %f in Y", xscale, yscale);
         rectscale(&picFrame, xscale, yscale);
     }
 
-    allocPlanes(planesP);
+    rowlen = picFrame.right  - picFrame.left;
+    collen = picFrame.bottom - picFrame.top;
+
+    allocPlanes(rowlen, collen, &canvasP->planes);
 
-    for (bi = blit_list; bi; bi = bi->next) {
-        blit(bi->srcRect, bi->srcBounds, bi->srcplane,
-             bi->pixSize,
-             bi->dstRect, picFrame, rowlen,
-             bi->color_map,
-             bi->mode);
+    clip_rect = picFrame;
+
+    for (bi = blitListP->firstP; bi; bi = bi->next) {
+        doBlit(bi->srcRect, bi->dstRect,
+               bi->srcBounds, bi->srcplane, picFrame, canvasP->planes,
+               bi->pixSize, rowlen, bi->colorMap, bi->mode);
     }
 }
 
 
 
 static void
-outputPpm(struct rgbPlanes const planes) {
+outputPpm(FILE *           const ofP,
+          struct rgbPlanes const planes) {
 
     unsigned int width;
     unsigned int height;
@@ -1732,7 +1890,7 @@ outputPpm(struct rgbPlanes const planes) {
     width  = picFrame.right  - picFrame.left;
     height = picFrame.bottom - picFrame.top;
 
-    ppm_writeppminit(stdout, width, height, PPM_MAXMAXVAL, 0);
+    ppm_writeppminit(ofP, width, height, PPM_MAXMAXVAL, 0);
     pixelrow = ppm_allocrow(width);
     srcCursor = 0;
     for (row = 0; row < height; ++row) {
@@ -1745,9 +1903,8 @@ outputPpm(struct rgbPlanes const planes) {
                 );
             ++srcCursor;
         }
-        ppm_writeppmrow(stdout, pixelrow, width, PPM_MAXMAXVAL, 0);
+        ppm_writeppmrow(ofP, pixelrow, width, PPM_MAXMAXVAL, 0);
     }
-    pm_close(stdout);
 }
 
 
@@ -1773,8 +1930,13 @@ get_op(int const version) {
 
 
 
+static drawFn Clip;
+
 static void
-Clip(int const version) {
+Clip(struct canvas * const canvasP,
+     blitList *      const blitListP,
+     int             const version) {
+
     word len;
 
     len = read_word();
@@ -1791,8 +1953,13 @@ Clip(int const version) {
 
 
 
+static drawFn OpColor;
+
 static void
-OpColor(int const version) {
+OpColor(struct canvas * const canvasP,
+        blitList *      const blitListP,
+        int             const version) {
+
     op_color.red = read_word();
     op_color.grn = read_word();
     op_color.blu = read_word();
@@ -1806,17 +1973,17 @@ read_pixmap(struct pixMap * const p) {
     stage = "getting pixMap header";
 
     read_rect(&p->Bounds);
-    p->version = read_word();
-    p->packType = read_word();
-    p->packSize = read_long();
-    p->hRes = read_long();
-    p->vRes = read_long();
-    p->pixelType = read_word();
-    p->pixelSize = read_word();
-    p->cmpCount = read_word();
-    p->cmpSize = read_word();
+    p->version    = read_word();
+    p->packType   = read_word();
+    p->packSize   = read_long();
+    p->hRes       = read_long();
+    p->vRes       = read_long();
+    p->pixelType  = read_word();
+    p->pixelSize  = read_word();
+    p->cmpCount   = read_word();
+    p->cmpSize    = read_word();
     p->planeBytes = read_long();
-    p->pmTable = read_long();
+    p->pmTable    = read_long();
     p->pmReserved = read_long();
 
     if (verbose) {
@@ -1824,6 +1991,8 @@ read_pixmap(struct pixMap * const p) {
         pm_message("pixelSize: %d", p->pixelSize);
         pm_message("cmpCount:  %d", p->cmpCount);
         pm_message("cmpSize:   %d", p->cmpSize);
+        if (verbose)
+            dumpRect("Bounds:", p->Bounds);
     }
 
     if (p->pixelType != 0)
@@ -1878,7 +2047,7 @@ read_color_table(void) {
         color_table[val].blu = read_word();
 
         if (verbose > 1)
-            pm_message("%d: [%d,%d,%d]", val,
+            pm_message("Color %3u: [%u,%u,%u]", val,
                 color_table[val].red,
                 color_table[val].grn,
                 color_table[val].blu);
@@ -2084,6 +2253,42 @@ unpackUncompressedBits(FILE *          const ifP,
 
 
 static void
+reportValidateCompressedLineLen(unsigned int const row,
+                                unsigned int const linelen,
+                                unsigned int const rowSize) {
+/*----------------------------------------------------------------------------
+   'row' is a row number in the raster.
+
+   'linelen' is the number of bytes of PICT that the PICT says hold the
+   compressed version of that row.
+
+   'rowSize' is the number of bytes we expect the uncompressed line to
+   be (includes pad pixels on the right).
+-----------------------------------------------------------------------------*/
+    if (verbose > 1)
+        pm_message("Row %u: %u-byte compressed line", row, linelen);
+
+    /* When the line length value is garbage, it often causes the program to
+       try to read beyond EOF.  To make that failure easier to diagnose,
+       we sanity check the line length now.
+    */
+
+    /* In the worst case, a pixel is represented by two bytes: a one byte
+       repeat count of one followed by a one byte pixel value (the byte could
+       be up to 8 pixels) or a one byte block length of one followed by the
+       pixel value.  So expansion factor two.
+    */
+
+    if (linelen > rowSize * 2)
+        pm_error("Invalid PICT: compressed line of %u bytes for Row %u "
+                 "is too big "
+                 "to represent a %u-byte padded row, even with worse case "
+                 "compression.", linelen, row, rowSize);
+}
+
+
+
+static void
 expandRun(unsigned char * const block,
           unsigned int    const blockLimit,
           unsigned int    const bitsPerPixel,
@@ -2099,6 +2304,9 @@ expandRun(unsigned char * const block,
    returned.
 -----------------------------------------------------------------------------*/
     unsigned int const pkpixsize = bitsPerPixel == 16 ? 2 : 1;
+        /* The repetition unit size, in bytes.  The run consists of this many
+           bytes of packed data repeated the specified number of times.
+        */
 
     if (1 + pkpixsize > blockLimit)
         pm_error("PICT run block runs off the end of its line.  "
@@ -2114,14 +2322,28 @@ expandRun(unsigned char * const block,
         assert(block[0] & 0x80);  /* It's a run */
 
         if (verbose > 1)
-            pm_message("Block: run of %u pixels or plane samples", runLength);
-        
+            pm_message("Block: run of %u packed %u-byte units",
+                       runLength, pkpixsize);
+
         unpackBuf(&block[1], pkpixsize, bitsPerPixel,
                   &bytePixels, &expandedByteCount);
+
+        /* I assume in a legal PICT the run never has padding for the
+           case that the run is at the right edge of a row and the
+           remaining columns in the row don't fill whole bytes.
+           E.g. if there are 25 columns left in the row and 1 bit per
+           pixel, we won't see a run of 4 bytes and have to ignore the
+           last 7 pixels.  Instead, we'll see a run of 3 bytes
+           followed by a non-run block for the remaining pixel.
+
+           That is what I saw in a test image.
+        */
         
-        if (expandedByteCount > expandedSize)
+        if (expandedByteCount * runLength > expandedSize)
             pm_error("Invalid PICT image.  It contains a row with more pixels "
-                     "than the width of the image");
+                     "than the width of the rectangle containing it, "
+                     "even padded up to a "
+                     "multiple of 16 pixels.  Use -verbose to see details.");
         
         outputCursor = 0;
         for (i = 0; i < runLength; ++i) {
@@ -2146,9 +2368,23 @@ copyPixelGroup(unsigned char * const block,
                unsigned int *  const rasterBytesGeneratedP) {
 /*----------------------------------------------------------------------------
    Copy a group of pixels (the data says, "take the following N pixels").
+
+   Copy them (unpacked) from block block[] to dest[].
+
+   block[] self-describes its length.  Return that length as
+   *blockLengthP.
+
+   block[] contains at most 'blockLimit' valid array elements, so if
+   the length information in block[] indicates the block is larger
+   than that, the block is corrupt.
+
+   Return the number of pixels placed in dest[] as *rasterBytesGeneratedP.
+
+   The output array dest[] has 'destSize' elements of space.  Ignore
+   any pixels on the right that won't fit in that.
 -----------------------------------------------------------------------------*/
-    unsigned int const pkpixsize = bitsPerPixel == 16 ? 2 : 1;
-    unsigned int const groupLen = block[0] + 1;
+    unsigned int const pkpixsize   = bitsPerPixel == 16 ? 2 : 1;
+    unsigned int const groupLen    = block[0] + 1;
     unsigned int const blockLength = 1 + groupLen * pkpixsize;
 
     if (blockLength > blockLimit)
@@ -2159,22 +2395,35 @@ copyPixelGroup(unsigned char * const block,
         unsigned int i;
         unsigned char * bytePixels;  /* Points to static storage */
         unsigned int bytePixelLen;
+        unsigned int rasterBytesGenerated;
         
         assert(blockLimit >= 1);  /* block[0] exists */
         assert((block[0] & 0x80) == 0);  /* It's not a run */
         
         if (verbose > 1)
-            pm_message("Block: %u individual pixels or plane samples",
-                       groupLen);
+            pm_message("Block: %u explicit packed %u-byte units",
+                       groupLen, pkpixsize);
         
         unpackBuf(&block[1], groupLen * pkpixsize, bitsPerPixel,
                   &bytePixels, &bytePixelLen);
-        
-        for (i = 0; i < MIN(bytePixelLen, destSize); ++i)
+
+        /* It is normal for the above to return more pixels than there
+           are left in the row, because of padding.  E.g. there is one
+           pixel left in the row, at one bit per pixel.  But a block
+           contains full bytes, so it must contain at least 8 pixels.
+           7 of them are padding, which we should ignore.
+
+           BUT: I saw an image in which the block had _two_ data bytes
+           (16 pixels) when only 1 pixel remained in the row.  I don't
+           understand why, but ignoring the 15 extra seemed to work.
+        */
+        rasterBytesGenerated = MIN(bytePixelLen, destSize);
+
+        for (i = 0; i < rasterBytesGenerated; ++i)
             dest[i] = bytePixels[i];
         
         *blockLengthP = blockLength;
-        *rasterBytesGeneratedP = MIN(bytePixelLen, destSize);
+        *rasterBytesGeneratedP = rasterBytesGenerated;
     }
 }
 
@@ -2218,12 +2467,83 @@ static unsigned int const maxPixelBytesPerBlock = 1024;
 
 
 static void
+interpretCompressedLine(unsigned char * const linebuf,
+                        unsigned int    const linelen,
+                        unsigned char * const rowRaster,
+                        unsigned int    const rowSize,
+                        unsigned int    const bitsPerPixel) {
+/*----------------------------------------------------------------------------
+   linebuf[] contains 'linelen' bytes from the PICT image that represents
+   one row of the image, in compressed format.  Return the
+   uncompressed pixels of that row as rowRaster[].
+
+   rowRaster[] has 'rowSize' bytes of space.  Caller ensures that
+   linebuf[] does not contain more pixels than that, unless the PICT
+   image from which it comes is corrupt.
+-----------------------------------------------------------------------------*/
+    unsigned int lineCursor;
+        /* Cursor into linebuf[] -- the compressed data */
+    unsigned int rasterCursor;
+        /* Cursor into rowRaster[] -- the uncompressed data */
+
+    for (lineCursor = 0, rasterCursor = 0; lineCursor < linelen; ) {
+        unsigned int blockLength, rasterBytesGenerated;
+        
+        assert(lineCursor <= linelen);
+            
+        if (verbose > 2)
+            pm_message("At Byte %u of line, Column %u of row",
+                       lineCursor, rasterCursor);
+
+        interpretOneRasterBlock(
+            &linebuf[lineCursor], linelen - lineCursor,
+            bitsPerPixel,
+            &rowRaster[rasterCursor], rowSize - rasterCursor,
+            &blockLength, &rasterBytesGenerated);
+        
+        lineCursor += blockLength;
+        rasterCursor += rasterBytesGenerated;
+        assert(rasterCursor <= rowSize);
+    }
+    if (verbose > 1)
+        pm_message("Got %u pixels for row", rasterCursor);
+}
+
+
+/* There is some confusion about when, in PICT, a line length is one byte and
+  when it is two.  An Apple document says it is two bytes when the number of
+  pixels in the row, padded, is > 250.  Ppmtopict generated PICTs that way
+  until January 2009.  Picttoppm assumed something similar until March 2004:
+  It assumed the line length is two bytes when the number of pixels > 250 _or_
+  bits per pixel > 8.  But in March 2004, Steve Summit did a bunch of
+  experiments on existing PICT files and found that they all worked with the
+  rule "pixels per row > 200 => 2 byte line length" and some did not work
+  with the original rule.
+
+  So in March 2004, Picttoppm changed to pixels per row > 200.  Ppmtopict
+  didn't catch up until January 2009.
+
+  http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-460.html#HEADING460-0
+
+  Of course, neither 200 nor 250 make any logical sense.  In the worst case,
+  you can represent 254 pixels of 8 bpp or less in a 255 byte line.
+  In the worst case, you can represent 127 16bpp pixels in a 255 byte line.
+  So with 200 being the cutoff, it's actually impossible to represent some 
+  16 bpp images with 200 pixels per row.
+
+  We have not been able to find an offical spec for PICT.
+
+  Some day, we may have to make a user option for this.
+*/
+
+
+static void
 unpackCompressedBits(FILE *          const ifP,
                      struct raster   const raster,
                      unsigned int    const rowBytes,
                      unsigned int    const bitsPerPixel) {
 /*----------------------------------------------------------------------------
-   Read the raster of on file *ifP and place it in 'raster'.
+   Read the raster on file *ifP and place it in 'raster'.
 
    The data in the file is compressed with run length encoding and
    possibly packed multiple pixels per byte as well.
@@ -2232,11 +2552,13 @@ unpackCompressedBits(FILE *          const ifP,
    "packing" and I don't know what packing is called.  But we don't
    use that confusing terminology in this program, except when talking
    to the user.
-
-   *boundsP describes the rectangle.
 -----------------------------------------------------------------------------*/
     unsigned int const llsize = rowBytes > 200 ? 2 : 1;
-    unsigned int rowOfRect;
+        /* Width in bytes of the field at the beginning of a line that tells
+           how long (in bytes) the line is.  See notes above about this
+           computation.
+        */
+    unsigned int row;
     unsigned char * linebuf;
     unsigned int linebufSize;
 
@@ -2245,20 +2567,17 @@ unpackCompressedBits(FILE *          const ifP,
     if (linebuf == NULL)
         pm_error("can't allocate memory for line buffer");
 
-    for (rowOfRect = 0; rowOfRect < raster.rowCount; ++rowOfRect) {
+    for (row = 0; row < raster.rowCount; ++row) {
         unsigned char * const rowRaster =
-            &raster.bytes[rowOfRect * raster.rowSize];
+            &raster.bytes[row * raster.rowSize];
         unsigned int linelen;
-        unsigned int lineCursor;
-        unsigned int rasterCursor;
 
         if (llsize == 2)
             linelen = read_word();
         else
             linelen = read_byte();
 
-        if (verbose > 1)
-            pm_message("linelen: %u", linelen);
+        reportValidateCompressedLineLen(row, linelen, raster.rowSize);
 
         if (linelen > linebufSize) {
             linebufSize = linelen;
@@ -2268,23 +2587,8 @@ unpackCompressedBits(FILE *          const ifP,
         }
         readBytes(ifP, linelen, linebuf);
 
-        for (lineCursor = 0, rasterCursor = 0; lineCursor < linelen; ) {
-            unsigned int blockLength, rasterBytesGenerated;
-
-            assert(lineCursor <= linelen);
-            
-            interpretOneRasterBlock(
-                &linebuf[lineCursor], linelen - lineCursor,
-                bitsPerPixel,
-                &rowRaster[rasterCursor], raster.rowSize - rasterCursor,
-                &blockLength, &rasterBytesGenerated);
-
-            lineCursor += blockLength;
-            rasterCursor += rasterBytesGenerated;
-            assert(rasterCursor <= raster.rowSize);
-        }
-        if (verbose > 1)
-            pm_message("row %u: got %u", rowOfRect, rasterCursor);
+        interpretCompressedLine(linebuf, linelen, rowRaster, raster.rowSize,
+                                bitsPerPixel);
     }
     free(linebuf);
 }
@@ -2386,21 +2690,42 @@ read_pattern(void) {
 
 /* these 3 do nothing but skip over their data! */
 
+static drawFn BkPixPat;
+
 static void
-BkPixPat(int const version) {
+BkPixPat(struct canvas * const canvasP,
+         blitList *      const blitListP,
+         int             const version) {
+
     read_pattern();
 }
 
+
+
+static drawFn PnPixPat;
+
 static void
-PnPixPat(int const version) {
+PnPixPat(struct canvas * const canvasP,
+         blitList *      const blitListP,
+         int             const version) {
+
     read_pattern();
 }
 
+
+
+static drawFn FillPixPat;
+
 static void
-FillPixPat(int const version) {
+FillPixPat(struct canvas * const canvasP,
+           blitList *      const blitListP,
+           int             const version) {
+
     read_pattern();
 }
 
+
+
 static void
 read_8x8_pattern(struct Pattern * const pat) {
     unsigned char buf[8];
@@ -2424,29 +2749,49 @@ read_8x8_pattern(struct Pattern * const pat) {
 
 
 
+static drawFn BkPat;
+
 static void 
-BkPat(int const version) {
+BkPat(struct canvas * const canvasP,
+      blitList *      const blitListP,
+      int             const version) {
+
     read_8x8_pattern(&bkpat);
 }
 
 
 
+static drawFn PnPat;
+
 static void 
-PnPat(int const version) {
+PnPat(struct canvas * const canvasP,
+      blitList *      const blitListP,
+      int             const version) {
+
     read_8x8_pattern(&pen_pat);
 }
 
 
 
+static drawFn FillPat;
+
 static void 
-FillPat(int const version) {
+FillPat(struct canvas * const canvasP,
+        blitList *      const blitListP,
+        int             const version) {
+
     read_8x8_pattern(&fillpat);
 }
 
 
 
+static drawFn PnSize;
+
 static void 
-PnSize(int const version) {
+PnSize(struct canvas * const canvasP,
+       blitList *      const blitListP,
+       int             const version) {
+
     pen_height = read_word();
     pen_width = read_word();
     if (verbose)
@@ -2455,8 +2800,12 @@ PnSize(int const version) {
 
 
 
+static drawFn PnSize;
+
 static void 
-PnMode(int const version) {
+PnMode(struct canvas * const canvasP,
+       blitList *      const blitListP,
+       int             const version) {
 
     pen_mode = read_word();
 
@@ -2480,8 +2829,13 @@ read_rgb(struct RGBColor * const rgb) {
 
 
 
+static drawFn RGBFgCol;
+
 static void 
-RGBFgCol(int const v) {
+RGBFgCol(struct canvas * const canvasP,
+         blitList *      const blitListP,
+         int             const version) {
+
     read_rgb(&foreground);
     if (verbose)
         pm_message("foreground now [%d,%d,%d]", 
@@ -2490,8 +2844,13 @@ RGBFgCol(int const v) {
 
 
 
+static drawFn RGBBkCol;
+
 static void 
-RGBBkCol(int const v) {
+RGBBkCol(struct canvas * const canvasP,
+         blitList *      const blitListP,
+         int             const version) {
+
     read_rgb(&background);
     if (verbose)
         pm_message("background now [%d,%d,%d]", 
@@ -2503,34 +2862,37 @@ RGBBkCol(int const v) {
 #define PIXEL_INDEX(x,y) ((y) - picFrame.top) * rowlen + (x) - picFrame.left
 
 static void 
-draw_pixel(int                const x, 
-           int                const y, 
+draw_pixel(struct canvas *   const canvasP,
+           int               const x, 
+           int               const y, 
            struct RGBColor * const clr, 
-           transfer_func            trf) {
-
-    int i;
-    struct RGBColor dst;
+           transfer_func           trf) {
 
     if (x < clip_rect.left || x >= clip_rect.right ||
-        y < clip_rect.top || y >= clip_rect.bottom)
-    {
-        return;
-    }
+        y < clip_rect.top || y >= clip_rect.bottom) {
+    } else {
+        unsigned int const i = PIXEL_INDEX(x, y);
+
+        struct RGBColor dst;
+
+        dst.red = canvasP->planes.red[i];
+        dst.grn = canvasP->planes.grn[i];
+        dst.blu = canvasP->planes.blu[i];
+ 
+        (*trf)(clr, &dst);
 
-    i = PIXEL_INDEX(x, y);
-    dst.red = red[i];
-    dst.grn = green[i];
-    dst.blu = blue[i];
-    (*trf)(clr, &dst);
-    red[i] = dst.red;
-    green[i] = dst.grn;
-    blue[i] = dst.blu;
+        canvasP->planes.red[i] = dst.red;
+        canvasP->planes.grn[i] = dst.grn;
+        canvasP->planes.blu[i] = dst.blu;
+    }
 }
 
 
 
 static void 
-draw_pen_rect(struct Rect * const r) {
+draw_pen_rect(struct canvas * const canvasP,
+              struct Rect *   const r) {
+
     int const rowadd = rowlen - (r->right - r->left);
 
     int i;
@@ -2541,16 +2903,18 @@ draw_pen_rect(struct Rect * const r) {
     
     for (y = r->top; y < r->bottom; y++) {
         for (x = r->left; x < r->right; x++) {
-            dst.red = red[i];
-            dst.grn = green[i];
-            dst.blu = blue[i];
+            dst.red = canvasP->planes.red[i];
+            dst.grn = canvasP->planes.grn[i];
+            dst.blu = canvasP->planes.blu[i];
+
             if (pen_pat.pix[(x & 7) + (y & 7) * 8])
                 (*pen_trf)(&black, &dst);
             else
                 (*pen_trf)(&white, &dst);
-            red[i] = dst.red;
-            green[i] = dst.grn;
-            blue[i] = dst.blu;
+
+            canvasP->planes.red[i] = dst.red;
+            canvasP->planes.grn[i] = dst.grn;
+            canvasP->planes.blu[i] = dst.blu;
 
             i++;
         }
@@ -2561,8 +2925,10 @@ draw_pen_rect(struct Rect * const r) {
 
 
 static void 
-draw_pen(int const x, 
-         int const y) {
+draw_pen(struct canvas * const canvasP,
+         int             const x, 
+         int             const y) {
+
     struct Rect penrect;
 
     penrect.left = x;
@@ -2572,7 +2938,7 @@ draw_pen(int const x,
 
     rectinter(penrect, clip_rect, &penrect);
 
-    draw_pen_rect(&penrect);
+    draw_pen_rect(canvasP, &penrect);
 }
 
 /*
@@ -2589,10 +2955,12 @@ draw_pen(int const x,
  * Paul Heckbert    3 Sep 85
  */
 static void 
-scan_line(short const x1, 
-          short const y1, 
-          short const x2, 
-          short const y2) {
+scan_line(struct canvas * const canvasP,
+          short           const x1, 
+          short           const y1, 
+          short           const x2, 
+          short           const y2) {
+
     int d, x, y, ax, ay, sx, sy, dx, dy;
 
     if (!(pen_width == 0 && pen_height == 0)) {
@@ -2605,7 +2973,7 @@ scan_line(short const x1,
         if (ax>ay) {        /* x dominant */
             d = ay-(ax>>1);
             for (;;) {
-                draw_pen(x, y);
+                draw_pen(canvasP, x, y);
                 if (x==x2) return;
                 if ((x > rowlen) && (sx > 0)) return;
                 if (d>=0) {
@@ -2619,7 +2987,7 @@ scan_line(short const x1,
         else {          /* y dominant */
             d = ax-(ay>>1);
             for (;;) {
-                draw_pen(x, y);
+                draw_pen(canvasP, x, y);
                 if (y==y2) return;
                 if ((y > collen) && (sy > 0)) return;
                 if (d>=0) {
@@ -2635,137 +3003,178 @@ scan_line(short const x1,
 
 
 
+static drawFn Line;
+
 static void 
-Line(int const v) {
+Line(struct canvas * const canvasP,
+     blitList *      const blitListP,
+     int             const version) {
+
   struct Point p1;
   read_point(&p1);
   read_point(&current);
   if (verbose)
     pm_message("(%d,%d) to (%d, %d)",
            p1.x,p1.y,current.x,current.y);
-  scan_line(p1.x,p1.y,current.x,current.y);
+  scan_line(canvasP, p1.x,p1.y,current.x,current.y);
 }
 
 
 
+static drawFn LineFrom;
+
 static void 
-LineFrom(int const v) {
-  struct Point p1;
-  read_point(&p1);
-  if (verbose)
-    pm_message("(%d,%d) to (%d, %d)",
-           current.x,current.y,p1.x,p1.y);
+LineFrom(struct canvas * const canvasP,
+         blitList *      const blitListP,
+         int             const version) {
+
+    struct Point p1;
+    read_point(&p1);
+    if (verbose)
+        pm_message("(%d,%d) to (%d, %d)", current.x, current.y, p1.x, p1.y);
 
-  if (!fullres)
-      scan_line(current.x,current.y,p1.x,p1.y);
+    if (!blitListP)
+        scan_line(canvasP, current.x, current.y, p1.x, p1.y);
 
-  current.x = p1.x;
-  current.y = p1.y;
+    current.x = p1.x;
+    current.y = p1.y;
 }
 
 
 
+static drawFn ShortLine;
+
 static void 
-ShortLine(int const v) {
-  struct Point p1;
-  read_point(&p1);
-  read_short_point(&current);
-  if (verbose)
-    pm_message("(%d,%d) delta (%d, %d)",
-           p1.x,p1.y,current.x,current.y);
-  current.x += p1.x;
-  current.y += p1.y;
+ShortLine(struct canvas * const canvasP,
+          blitList *      const blitListP,
+          int             const version) {
 
-  if (!fullres)
-      scan_line(p1.x,p1.y,current.x,current.y);
+    struct Point p1;
+    read_point(&p1);
+    read_short_point(&current);
+    if (verbose)
+        pm_message("(%d,%d) delta (%d, %d)", p1.x, p1.y, current.x, current.y);
+    current.x += p1.x;
+    current.y += p1.y;
+    
+    if (!blitListP)
+        scan_line(canvasP, p1.x, p1.y, current.x, current.y);
 }
 
 
 
+static drawFn ShortLineFrom;
+
 static void 
-ShortLineFrom(int const v) {
-  struct Point p1;
-  read_short_point(&p1);
-  if (verbose)
-    pm_message("(%d,%d) delta (%d, %d)",
-               current.x,current.y,p1.x,p1.y);
-  p1.x += current.x;
-  p1.y += current.y;
-  if (!fullres)
-      scan_line(current.x,current.y,p1.x,p1.y);
-  current.x = p1.x;
-  current.y = p1.y;
+ShortLineFrom(struct canvas * const canvasP,
+              blitList *      const blitListP,
+              int             const version) {
+
+    struct Point p1;
+    read_short_point(&p1);
+    if (verbose)
+        pm_message("(%d,%d) delta (%d, %d)",
+                   current.x,current.y,p1.x,p1.y);
+    p1.x += current.x;
+    p1.y += current.y;
+    if (!blitListP)
+        scan_line(canvasP, current.x, current.y, p1.x, p1.y);
+    current.x = p1.x;
+    current.y = p1.y;
 }
 
+
+
 static void 
-do_paintRect(struct Rect const prect) {
+do_paintRect(struct canvas * const canvasP,
+             struct Rect     const prect) {
+
     struct Rect rect;
   
-    if (fullres)
-        return;
-
     if (verbose)
         dumpRect("painting", prect);
 
     rectinter(clip_rect, prect, &rect);
 
-    draw_pen_rect(&rect);
+    draw_pen_rect(canvasP, &rect);
 }
 
 
 
+static drawFn paintRect;
+
 static void 
-paintRect(int const v) {
+paintRect(struct canvas * const canvasP,
+          blitList *      const blitListP,
+          int             const version) {
+
     read_rect(&cur_rect);
-    do_paintRect(cur_rect);
+    if (!blitListP)
+        do_paintRect(canvasP, cur_rect);
 }
 
 
 
+static drawFn paintSameRect;
+
 static void 
-paintSameRect(int const v) {
-    do_paintRect(cur_rect);
+paintSameRect(struct canvas * const canvasP,
+              blitList *      const blitListP,
+              int             const version) {
+
+    if (!blitListP)
+        do_paintRect(canvasP, cur_rect);
 }
 
 
 
 static void 
-do_frameRect(struct Rect const rect) {
-    int x, y;
+do_frameRect(struct canvas * const canvasP,
+             struct Rect     const rect) {
 
-    if (fullres)
-        return;
-  
     if (verbose)
         dumpRect("framing", rect);
 
-    if (pen_width == 0 || pen_height == 0)
-        return;
-
-    for (x = rect.left; x <= rect.right - pen_width; x += pen_width) {
-        draw_pen(x, rect.top);
-        draw_pen(x, rect.bottom - pen_height);
-    }
+    if (pen_width > 0 && pen_height > 0) {
+        unsigned int x, y;
 
-    for (y = rect.top; y <= rect.bottom - pen_height ; y += pen_height) {
-        draw_pen(rect.left, y);
-        draw_pen(rect.right - pen_width, y);
+        for (x = rect.left; x <= rect.right - pen_width; x += pen_width) {
+            draw_pen(canvasP, x, rect.top);
+            draw_pen(canvasP, x, rect.bottom - pen_height);
+        }
+        
+        for (y = rect.top; y <= rect.bottom - pen_height ; y += pen_height) {
+            draw_pen(canvasP, rect.left, y);
+            draw_pen(canvasP, rect.right - pen_width, y);
+        }
     }
 }
 
 
 
+static drawFn frameRect;
+
 static void 
-frameRect(int const v) {
+frameRect(struct canvas * const canvasP,
+          blitList *      const blitListP,
+          int             const version) {
+
     read_rect(&cur_rect);
-    do_frameRect(cur_rect);
+    if (!blitListP)
+        do_frameRect(canvasP, cur_rect);
 }
 
 
 
+static drawFn frameSameRect;
+
 static void 
-frameSameRect(int const v) {
-    do_frameRect(cur_rect);
+frameSameRect(struct canvas * const canvasP,
+              blitList *      const blitListP,
+              int             const version) {
+
+    if (!blitListP)
+        do_frameRect(canvasP, cur_rect);
 }
 
 
@@ -2806,8 +3215,10 @@ poly_sort(int const sort_index, struct Point points[]) {
 /* Watch out for the lack of error checking in the next two functions ... */
 
 static void 
-scan_poly(int          const np, 
-          struct Point       pts[]) {
+scan_poly(struct canvas * const canvasP,
+          int             const np, 
+          struct Point          pts[]) {
+
   int dx,dy,dxabs,dyabs,i,scan_index,j,k,px,py;
   int sdx,sdy,x,y,toggle,old_sdy,sy0;
 
@@ -2860,7 +3271,7 @@ scan_poly(int          const np,
         scan_index++;
       }
       px += sdx;
-      draw_pen(px, py);
+      draw_pen(canvasP, px, py);
     }
       }
     else
@@ -2876,7 +3287,7 @@ scan_poly(int          const np,
         old_sdy = sdy;
         if (sdy != 0) scan_index--;
       }
-      draw_pen(px,py);
+      draw_pen(canvasP, px,py);
       coord[scan_index].x = px;
       coord[scan_index].y = py;
       scan_index++;
@@ -2896,7 +3307,7 @@ scan_poly(int          const np,
     if ((coord[i].y == coord[i+1].y) && (toggle == 0))
       {
     for (j = coord[i].x; j <= coord[i+1].x; j++)
-      draw_pen(j, coord[i].y);
+      draw_pen(canvasP, j, coord[i].y);
     toggle = 1;
       }
     else
@@ -2905,9 +3316,14 @@ scan_poly(int          const np,
 }
   
 
+
+static drawFn paintPoly;
   
 static void 
-paintPoly(int const v) {
+paintPoly(struct canvas * const canvasP,
+          blitList *      const blitListP,
+          int             const version) {
+
   struct Rect bb;
   struct Point pts[100];
   int i, np = (read_word() - 10) >> 2;
@@ -2917,14 +3333,19 @@ paintPoly(int const v) {
     read_point(&pts[i]);
 
   /* scan convert poly ... */
-  if (!fullres)
-      scan_poly(np, pts);
+  if (!blitListP)
+      scan_poly(canvasP, np, pts);
 }
 
 
 
+static drawFn PnLocHFrac;
+
 static void 
-PnLocHFrac(int const version) {
+PnLocHFrac(struct canvas * const canvasP,
+           blitList *      const blitListP,
+           int             const version) {
+
     word frac = read_word();
 
     if (verbose)
@@ -2933,8 +3354,13 @@ PnLocHFrac(int const version) {
 
 
 
+static drawFn TxMode;
+
 static void 
-TxMode(int const version) {
+TxMode(struct canvas * const canvasP,
+       blitList *      const blitListP,
+       int             const version) {
+
     text_mode = read_word();
 
     if (text_mode >= 8 && text_mode < 15)
@@ -2949,8 +3375,13 @@ TxMode(int const version) {
 
 
 
+static drawFn TxFont;
+
 static void 
-TxFont(int const version) {
+TxFont(struct canvas * const canvasP,
+       blitList *      const blitListP,
+       int             const version) {
+
     text_font = read_word();
     if (verbose)
         pm_message("text font %s", const_name(font_name, text_font));
@@ -2958,8 +3389,13 @@ TxFont(int const version) {
 
 
 
+static drawFn TxFace;
+
 static void 
-TxFace(int const version) {
+TxFace(struct canvas * const canvasP,
+       blitList *      const blitListP,
+       int             const version) {
+
     text_face = read_byte();
     if (verbose)
         pm_message("text face %d", text_face);
@@ -2967,8 +3403,13 @@ TxFace(int const version) {
 
 
 
+static drawFn TxSize;
+
 static void 
-TxSize(int const version) {
+TxSize(struct canvas * const canvasP,
+       blitList *      const blitListP,
+       int             const version) {
+
     text_size = read_word();
     if (verbose)
         pm_message("text size %d", text_size);
@@ -2977,8 +3418,11 @@ TxSize(int const version) {
 
 
 static void
-skip_text(void) {
+skip_text(blitList * const blitListP) {
+
     skip(read_byte());
+
+    blitListP->unblittableText = true;
 }
 
 
@@ -2997,6 +3441,7 @@ static struct font*
 get_font(int const font, 
          int const size, 
          int const style) {
+
     int closeness, bestcloseness;
     struct fontinfo* fi, *best;
 
@@ -3058,8 +3503,10 @@ rotate(int * const x,
 
 
 static void
-do_ps_text(word const tx, 
-           word const ty) {
+do_ps_text(struct canvas * const canvasP,
+           word            const tx, 
+           word            const ty) {
+
     int len, width, i, w, h, x, y, rx, ry, o;
     byte str[256], ch;
     struct glyph* glyph;
@@ -3110,9 +3557,9 @@ do_ps_text(word const tx,
                 {
                     o = PIXEL_INDEX(rx, ry);
                     if (glyph->bmap[h * glyph->width + w]) {
-                        red[o] = foreground.red;
-                        green[o] = foreground.grn;
-                        blue[o] = foreground.blu;
+                        canvasP->planes.red[o] = foreground.red;
+                        canvasP->planes.grn[o] = foreground.grn;
+                        canvasP->planes.blu[o] = foreground.blu;
                     }
                 }
             }
@@ -3125,16 +3572,19 @@ do_ps_text(word const tx,
 
 
 static void
-do_text(word const startx, 
-        word const starty) {
-    if (fullres)
-        skip_text();
+do_text(struct canvas *  const canvasP,
+        blitList *       const blitListP,
+        word             const startx, 
+        word             const starty) {
+
+    if (blitListP)
+        skip_text(blitListP);
     else {
         if (!(tfont = get_font(text_font, text_size, text_face)))
             tfont = pbm_defaultfont("bdf");
 
         if (ps_text)
-            do_ps_text(startx, starty);
+            do_ps_text(canvasP, startx, starty);
         else {
             int len;
             word x, y;
@@ -3154,7 +3604,8 @@ do_text(word const startx,
                             struct RGBColor * const colorP = 
                                 glyph->bmap[h * glyph->width + w] ?
                                 &black : &white;
-                            draw_pixel(x + w + glyph->x, dy, colorP, text_trf);
+                            draw_pixel(canvasP,
+                                       x + w + glyph->x, dy, colorP, text_trf);
                         }
                     }
                     x += glyph->xadd;
@@ -3168,34 +3619,56 @@ do_text(word const startx,
 
 
 
+static drawFn LongText;
+
 static void
-LongText(int const version) {
+LongText(struct canvas * const canvasP,
+         blitList *      const blitListP,
+         int             const version) {
+
     struct Point p;
 
     read_point(&p);
-    do_text(p.x, p.y);
+
+    do_text(canvasP, blitListP, p.x, p.y);
 }
 
 
 
+static drawFn DHText;
+
 static void
-DHText(int const version) {
+DHText(struct canvas * const canvasP,
+       blitList *      const blitListP,
+       int             const version) {
+
     current.x += read_byte();
-    do_text(current.x, current.y);
+
+    do_text(canvasP, blitListP, current.x, current.y);
 }
 
 
 
+static drawFn DVText;
+
 static void
-DVText(int const version) {
+DVText(struct canvas * const canvasP,
+       blitList *      const blitListP,
+       int             const version) {
+
     current.y += read_byte();
-    do_text(current.x, current.y);
+
+    do_text(canvasP, blitListP, current.x, current.y);
 }
 
 
 
+static drawFn DHDVText;
+
 static void
-DHDVText(int const version) {
+DHDVText(struct canvas * const canvasP,
+         blitList *      const blitListP,
+         int             const version) {
     byte dh, dv;
 
     dh = read_byte();
@@ -3206,7 +3679,8 @@ DHDVText(int const version) {
 
     current.x += dh;
     current.y += dv;
-    do_text(current.x, current.y);
+
+    do_text(canvasP, blitListP, current.x, current.y);
 }
 
 
@@ -3216,8 +3690,10 @@ DHDVText(int const version) {
  */
 
 static void
-directBits(unsigned int const pictVersion, 
-           bool         const skipRegion) {
+directBits(struct canvas * const canvasP,
+           blitList *      const blitListP,
+           unsigned int    const pictVersion, 
+           bool            const skipRegion) {
 
     struct pixMap   p;
     struct Rect     srcRect;
@@ -3257,11 +3733,11 @@ directBits(unsigned int const pictVersion,
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
 
     if (skipRegion) 
-        skip_poly_or_region(pictVersion);
+        skip_poly_or_region(canvasP, blitListP, pictVersion);
 
     unpackbits(ifp, &p.Bounds, 0, p.pixelSize, &raster);
 
-    blit(srcRect, p.Bounds, raster, p.pixelSize,
+    blit(srcRect, p.Bounds, raster, canvasP, blitListP, p.pixelSize,
          dstRect, picFrame, rowlen, NULL, mode);
 
     freeRaster(raster);
@@ -3272,26 +3748,36 @@ directBits(unsigned int const pictVersion,
 #define SKIP_REGION_TRUE TRUE
 #define SKIP_REGION_FALSE FALSE
 
+static drawFn DirectBitsRect;
+
 static void
-DirectBitsRect(int const version) {
+DirectBitsRect(struct canvas * const canvasP,
+               blitList *      const blitListP,
+               int             const version) {
 
-    directBits(version, SKIP_REGION_FALSE);
+    directBits(canvasP, blitListP, version, SKIP_REGION_FALSE);
 }
 
 
 
+static drawFn DirectBitsRgn;
+
 static void
-DirectBitsRgn(int const version) {
+DirectBitsRgn(struct canvas * const canvasP,
+              blitList *      const blitListP,
+              int             const version) {
 
-    directBits(version, SKIP_REGION_TRUE);
+    directBits(canvasP, blitListP, version, SKIP_REGION_TRUE);
 }
 
 
 
 static void
-do_pixmap(int  const version, 
-          word const rowBytes, 
-          int  const is_region) {
+do_pixmap(struct canvas * const canvasP,
+          blitList *      const blitListP,
+          int             const version, 
+          word            const rowBytes, 
+          int             const is_region) {
 /*----------------------------------------------------------------------------
    Do a paletted image.
 -----------------------------------------------------------------------------*/
@@ -3327,13 +3813,13 @@ do_pixmap(int  const version,
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
 
     if (is_region)
-        skip_poly_or_region(version);
+        skip_poly_or_region(canvasP, blitListP, version);
 
     stage = "unpacking rectangle";
 
     unpackbits(ifp, &p.Bounds, rowBytes, p.pixelSize, &raster);
 
-    blit(srcRect, p.Bounds, raster, 8,
+    blit(srcRect, p.Bounds, raster, canvasP, blitListP, 8,
          dstRect, picFrame, rowlen, color_table, mode);
 
     free(color_table);
@@ -3343,17 +3829,25 @@ do_pixmap(int  const version,
 
 
 static void
-do_bitmap(int const version, 
-          int const rowBytes, 
-          int const is_region) {
+do_bitmap(FILE *          const ifP,
+          struct canvas * const canvasP,
+          blitList *      const blitListP,
+          int             const version, 
+          int             const rowBytes, 
+          int             const is_region) {
 /*----------------------------------------------------------------------------
    Do a bitmap.  That's one bit per pixel, 0 is white, 1 is black.
+
+   Read the raster from file 'ifP'.
 -----------------------------------------------------------------------------*/
     struct Rect Bounds;
     struct Rect srcRect;
     struct Rect dstRect;
     word mode;
     struct raster raster;
+        /* This raster contains padding on the right to make a multiple
+           of 16 pixels per row.
+        */
     static struct RGBColor color_table[] = { 
         {65535L, 65535L, 65535L}, {0, 0, 0} };
 
@@ -3365,13 +3859,13 @@ do_bitmap(int const version,
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
 
     if (is_region)
-        skip_poly_or_region(version);
+        skip_poly_or_region(canvasP, blitListP, version);
 
     stage = "unpacking rectangle";
 
-    unpackbits(ifp, &Bounds, rowBytes, 1, &raster);
+    unpackbits(ifP, &Bounds, rowBytes, 1, &raster);
 
-    blit(srcRect, Bounds, raster, 8,
+    blit(srcRect, Bounds, raster, canvasP, blitListP, 8,
          dstRect, picFrame, rowlen, color_table, mode);
 
     freeRaster(raster);
@@ -3379,8 +3873,12 @@ do_bitmap(int const version,
 
 
 
+static drawFn BitsRect;
+
 static void
-BitsRect(int const version) {
+BitsRect(struct canvas * const canvasP,
+         blitList *      const blitListP,
+         int             const version) {
 
     word rowBytesWord;
     bool pixMap;
@@ -3392,16 +3890,20 @@ BitsRect(int const version) {
     interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes);
 
     if (pixMap)
-        do_pixmap(version, rowBytes, 0);
+        do_pixmap(canvasP, blitListP, version, rowBytes, 0);
     else
-        do_bitmap(version, rowBytes, 0);
+        do_bitmap(ifp, canvasP, blitListP, version, rowBytes, 0);
 }
 
 
 
-static void
-BitsRegion(int const version) {
+static drawFn BitsRegion;
 
+static void
+BitsRegion(struct canvas * const canvasP,
+           blitList *      const blitListP,
+           int             const version) {
+    
     word rowBytesWord;
     bool pixMap;
     unsigned int rowBytes;
@@ -3412,9 +3914,9 @@ BitsRegion(int const version) {
     interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes);
 
     if (pixMap)
-        do_pixmap(version, rowBytes, 1);
+        do_pixmap(canvasP, blitListP, version, rowBytes, 1);
     else
-        do_bitmap(version, rowBytes, 1);
+        do_bitmap(ifp, canvasP, blitListP, version, rowBytes, 1);
 }
 
 
@@ -3597,14 +4099,85 @@ static struct opdef const optable[] = {
 
 
 static void
-interpret_pict(void) {
+processOpcode(word const opcode, 
+              struct canvas * const canvasP,
+              blitList *      const blitListP,
+              unsigned int    const version) {
+
+    if (opcode < 0xa2) {
+        stage = optable[opcode].name;
+        if (verbose) {
+            if (streq(stage, "reserved"))
+                pm_message("reserved opcode=0x%x", opcode);
+            else
+                pm_message("Opcode: %s", optable[opcode].name);
+        }
+
+        if (optable[opcode].impl != NULL)
+            (*optable[opcode].impl)(canvasP, blitListP, version);
+        else if (optable[opcode].len >= 0)
+            skip(optable[opcode].len);
+        else {
+            switch (optable[opcode].len) {
+            case WORD_LEN: {
+                word const len = read_word();
+                skip(len);
+                } break;
+            default:
+                pm_error("can't do length %u", optable[opcode].len);
+            }
+        }
+    } else if (opcode == 0xc00) {
+        if (verbose)
+            pm_message("HeaderOp");
+        stage = "HeaderOp";
+        skip(24);
+    } else if (opcode >= 0xa2 && opcode <= 0xaf) {
+        stage = "skipping reserved";
+        if (verbose)
+            pm_message("%s 0x%x", stage, opcode);
+        skip(read_word());
+    } else if (opcode >= 0xb0 && opcode <= 0xcf) {
+        /* just a reserved opcode, no data */
+        if (verbose)
+            pm_message("reserved 0x%x", opcode);
+    } else if (opcode >= 0xd0 && opcode <= 0xfe) {
+        stage = "skipping reserved";
+        if (verbose)
+            pm_message("%s 0x%x", stage, opcode);
+        skip(read_long());
+    } else if (opcode >= 0x100 && opcode <= 0x7fff) {
+        stage = "skipping reserved";
+        if (verbose)
+            pm_message("%s 0x%x", stage, opcode);
+        skip((opcode >> 7) & 255);
+    } else if (opcode >= 0x8000 && opcode <= 0x80ff) {
+        /* just a reserved opcode */
+        if (verbose)
+            pm_message("reserved 0x%x", opcode);
+    } else if (opcode >= 0x8100) {
+        stage = "skipping reserved";
+        if (verbose)
+            pm_message("%s 0x%x", stage, opcode);
+        skip(read_long());
+    } else
+        pm_error("This program does not understand opcode 0x%04x", opcode);
+}
+
+
+
+static void
+interpret_pict(FILE * const ofP) {
+
     byte ch;
     word picSize;
     word opcode;
-    word len;
     unsigned int version;
     int i;
-    struct rgbPlanes planes;
+    struct canvas canvas;
+    blitList blitList;
+
+    initBlitList(&blitList);
 
     for (i = 0; i < 64; i++)
         pen_pat.pix[i] = bkpat.pix[i] = fillpat.pix[i] = 1;
@@ -3618,20 +4191,26 @@ interpret_pict(void) {
     picSize = read_word();
 
     if (verbose)
-        pm_message("picture size = %d (0x%x)", picSize, picSize);
+        pm_message("picture size = %u (0x%x)", picSize, picSize);
 
     stage = "reading picture frame";
     read_rect(&picFrame);
 
     if (verbose) {
         dumpRect("Picture frame:", picFrame);
-        pm_message("Picture size is %d x %d",
-            picFrame.right - picFrame.left,
-            picFrame.bottom - picFrame.top);
+        pm_message("Picture size is %u x %u",
+                   picFrame.right - picFrame.left,
+                   picFrame.bottom - picFrame.top);
     }
 
-    if (!fullres)
-        allocPlanes(&planes);
+    if (!fullres) {
+        rowlen = picFrame.right  - picFrame.left;
+        collen = picFrame.bottom - picFrame.top;
+
+        allocPlanes(rowlen, collen, &canvas.planes);
+
+        clip_rect = picFrame;
+    }
 
     while ((ch = read_byte()) == 0)
         ;
@@ -3657,71 +4236,35 @@ interpret_pict(void) {
     if (verbose)
         pm_message("PICT version %u", version);
 
-    while((opcode = get_op(version)) != 0xff) {
-        if (opcode < 0xa2) {
-            stage = optable[opcode].name;
-            if (verbose) {
-                if (STREQ(stage, "reserved"))
-                    pm_message("reserved opcode=0x%x", opcode);
-                else
-                    pm_message("Opcode: %s", optable[opcode].name);
-            }
-
-            if (optable[opcode].impl != NULL)
-                (*optable[opcode].impl)(version);
-            else if (optable[opcode].len >= 0)
-                skip(optable[opcode].len);
-            else switch (optable[opcode].len) {
-            case WORD_LEN:
-                len = read_word();
-                skip(len);
-                break;
-            default:
-                pm_error("can't do length %u", optable[opcode].len);
-            }
-        } else if (opcode == 0xc00) {
-            if (verbose)
-                pm_message("HeaderOp");
-            stage = "HeaderOp";
-            skip(24);
-        } else if (opcode >= 0xa2 && opcode <= 0xaf) {
-            stage = "skipping reserved";
-            if (verbose)
-                pm_message("%s 0x%x", stage, opcode);
-            skip(read_word());
-        } else if (opcode >= 0xb0 && opcode <= 0xcf) {
-            /* just a reserved opcode, no data */
-            if (verbose)
-                pm_message("reserved 0x%x", opcode);
-        } else if (opcode >= 0xd0 && opcode <= 0xfe) {
-            stage = "skipping reserved";
-            if (verbose)
-                pm_message("%s 0x%x", stage, opcode);
-            skip(read_long());
-        } else if (opcode >= 0x100 && opcode <= 0x7fff) {
-            stage = "skipping reserved";
-            if (verbose)
-                pm_message("%s 0x%x", stage, opcode);
-            skip((opcode >> 7) & 255);
-        } else if (opcode >= 0x8000 && opcode <= 0x80ff) {
-            /* just a reserved opcode */
-            if (verbose)
-                pm_message("reserved 0x%x", opcode);
-        } else if (opcode >= 0x8100) {
-            stage = "skipping reserved";
-            if (verbose)
-                pm_message("%s 0x%x", stage, opcode);
-            skip(read_long());
-        } else
-            pm_error("This program does not understand opcode 0x%04x", opcode);
-    }
+    while((opcode = get_op(version)) != 0xff)
+        processOpcode(opcode, &canvas, fullres ? &blitList : NULL, version);
     
-    if (fullres)
-        do_blits(&planes);
+    if (fullres) {
+        if (blitList.unblittableText)
+            pm_message("Warning: text is omitted from the output because "
+                       "we don't know how to do text with -fullres.");
+        doBlitList(&canvas, &blitList);
+    }
+    outputPpm(ofP, canvas.planes);
+
+    freePlanes(canvas.planes);
+}
+
+
 
-    outputPpm(planes);
+static void
+loadDefaultFontDir(void) {
+/*----------------------------------------------------------------------------
+   Load the fonts from the font directory file "fontdir" (in the current
+   directory), if it exists.
+-----------------------------------------------------------------------------*/
+    struct stat statbuf;
+    int rc;
 
-    freePlanes(planes);
+    rc = stat("fontdir", &statbuf);
+    
+    if (rc == 0)
+        load_fontdir("fontdir");
 }
 
 
@@ -3762,8 +4305,6 @@ main(int argc, char * argv[]) {
         ++argn;
     }
 
-    load_fontdir("fontdir");
-
     if (argn < argc) {
         ifp = pm_openr(argv[argn]);
         ++argn;
@@ -3773,12 +4314,17 @@ main(int argc, char * argv[]) {
     if (argn != argc)
         pm_usage(usage);
 
+    loadDefaultFontDir();
+
     if (header) {
         stage = "Reading 512 byte header";
+        /* Note that the "header" in PICT is entirely comment! */
         skip(512);
     }
 
-    interpret_pict();
+    interpret_pict(stdout);
+
+    pm_close(stdout);
 
     return 0;
 }
diff --git a/converter/ppm/ppmtoarbtxt.c b/converter/ppm/ppmtoarbtxt.c
index fe466ea5..df859c84 100644
--- a/converter/ppm/ppmtoarbtxt.c
+++ b/converter/ppm/ppmtoarbtxt.c
@@ -24,6 +24,10 @@ typedef enum {
     WIDTH, HEIGHT, POSX, POSY
 } SKL_OBJ_TYP;
 
+typedef enum {
+    OBJTYP_ICOLOR, OBJTYP_FCOLOR, OBJTYP_INT, OBJTYP_BDATA
+} SKL_OBJ_CLASS;
+
 /* Maximum size for a format string ("%d" etc.) */
 #define MAXFORMAT 16
 
@@ -158,257 +162,328 @@ save_bin_data(int    const ndat,
 
 
 
+static SKL_OBJ *
+save_icol_data(SKL_OBJ_TYP  const ctyp,
+               const char * const format,
+               int          const icolmin,
+               int          const icolmax) {
 /* Save integer color data in Object */
-static SKL_OBJ *save_icol_data (ctyp,format,icolmin,icolmax)
-SKL_OBJ_TYP ctyp;
-char *format;
-int icolmin, icolmax;
 
-{SKL_OBJ *obj;
+    SKL_OBJ * objP;
 
- obj = (SKL_OBJ *)malloc (sizeof (SKL_OBJ));
- if (obj != NULL)
- {
-   obj->otyp = ctyp;
-   strcpy (obj->odata.icol_data.icformat,format);
-   obj->odata.icol_data.icolmin = icolmin;
-   obj->odata.icol_data.icolmax = icolmax;
- }
- return (obj);
+    MALLOCVAR(objP);
+
+    if (objP) {
+        objP->otyp = ctyp;
+        strcpy(objP->odata.icol_data.icformat, format);
+        objP->odata.icol_data.icolmin = icolmin;
+        objP->odata.icol_data.icolmax = icolmax;
+    }
+    return objP;
 }
 
 
+
+static SKL_OBJ *
+save_fcol_data(SKL_OBJ_TYP  const ctyp,
+               const char * const format,
+               double       const fcolmin,
+               double       const fcolmax) {
 /* Save float color data in Object */
-static SKL_OBJ *save_fcol_data (ctyp,format,fcolmin,fcolmax)
-SKL_OBJ_TYP ctyp;
-char *format;
-double fcolmin, fcolmax;
 
-{SKL_OBJ *obj;
+    SKL_OBJ * objP;
 
- obj = (SKL_OBJ *)malloc (sizeof (SKL_OBJ));
- if (obj != NULL)
- {
-   obj->otyp = ctyp;
-   strcpy (obj->odata.fcol_data.fcformat,format);
-   obj->odata.fcol_data.fcolmin = fcolmin;
-   obj->odata.fcol_data.fcolmax = fcolmax;
- }
- return (obj);
+    MALLOCVAR(objP);
+
+    if (objP) {
+        objP->otyp = ctyp;
+        strcpy(objP->odata.fcol_data.fcformat, format);
+        objP->odata.fcol_data.fcolmin = fcolmin;
+        objP->odata.fcol_data.fcolmax = fcolmax;
+    }
+    return objP;
 }
 
 
+
+static SKL_OBJ *
+save_i_data(SKL_OBJ_TYP  const ctyp,
+            const char * const format) {
+
 /* Save universal data in Object */
-static SKL_OBJ *save_i_data (ctyp,format)
-SKL_OBJ_TYP ctyp;
-char *format;
 
-{SKL_OBJ *obj;
+    SKL_OBJ * objP;
 
- obj = (SKL_OBJ *)malloc (sizeof (SKL_OBJ));
- if (obj != NULL)
- {
-   obj->otyp = ctyp;
-   strcpy (obj->odata.i_data.iformat,format);
- }
- return (obj);
+    MALLOCVAR(objP);
+    if (objP) {
+        objP->otyp = ctyp;
+        strcpy(objP->odata.i_data.iformat, format);
+    }
+    return objP;
 }
 
 
-/* Read skeleton file */
-static int read_skeleton (filename,maxskl,nskl,skl)
-char *filename;
-int maxskl,*nskl;
-SKL_OBJ **skl;
 
-{FILE *sklfile;
- int slen, objlen, chr, n_odata;
- int icolmin,icolmax;
- double fcolmin,fcolmax;
- SKL_OBJ_TYP otyp;
- char line[MAX_LINE_BUF+MAX_OBJ_BUF+16];
- char objstr[MAX_OBJ_BUF],typstr[MAX_OBJ_BUF];
- char formstr[MAX_OBJ_BUF];
- char meta1 = '#', meta2 = '(', meta3 = ')';
+static char const escape = '#';
 
-#define SAVE_BIN(slen,line) \
- { if ((skl[*nskl] = save_bin_data (slen,line)) != NULL) (*nskl)++; \
-   slen = 0; }
 
-#define ADD_STR(slen,line,addlen,addstr) \
- {int count=0; line[slen++] = meta1; line[slen++] = meta2; \
-  while (count++ < addlen) line[slen++] = addstr[count]; }
 
- if ((sklfile = fopen (filename,"r")) == NULL)
-   return (-1);
+static SKL_OBJ_TYP
+interpretObjType(const char * const typstr) {
 
- /* Parse skeleton file */
- *nskl = 0;
+    SKL_OBJ_TYP otyp;
 
- slen = 0;
- while ((chr = getc (sklfile)) != EOF)   /* Up to end of skeleton file */
- {
-   if (*nskl >= maxskl) return (-1);
+    /* Check for integer colors */
+    if      (streq(typstr, "ired")  ) otyp = IRED;
+    else if (streq(typstr, "igreen")) otyp = IGREEN;
+    else if (streq(typstr, "iblue") ) otyp = IBLUE;
+    else if (streq(typstr, "ilum")  ) otyp = ILUM;
+    /* Check for real colors */
+    else if (streq(typstr, "fred")  ) otyp = FRED;
+    else if (streq(typstr, "fgreen")) otyp = FGREEN;
+    else if (streq(typstr, "fblue") ) otyp = FBLUE;
+    else if (streq(typstr, "flum")  ) otyp = FLUM;
+    /* Check for integer data */
+    else if (streq(typstr, "width") ) otyp = WIDTH;
+    else if (streq(typstr, "height")) otyp = HEIGHT;
+    else if (streq(typstr, "posx")  ) otyp = POSX;
+    else if (streq(typstr, "posy")  ) otyp = POSY;
+    else                              otyp = BDATA;
 
-   if (slen+1 >= MAX_LINE_BUF)   /* Buffer finished ? Save as binary object */
-   {
-     SAVE_BIN (slen,line);
-   }
+    return otyp;
+}
 
-   if (chr != meta1)      /* Look for start of replacement string */
-   {
-     line[slen++] = chr;
-     continue;
-   }
 
-   if ((chr = getc (sklfile)) == EOF)
-   {
-     line[slen++] = meta1;
-     break;
-   }
-   if (chr != meta2) /* '(' ? Otherwise no replacement */
-   {
-     line[slen++] = meta1;
-     line[slen++] = chr;
-     continue;
-   }
 
-   objlen = 0;
-   for (;;)   /* Read replacement string up to ')' */
-   {
-     if (objlen == sizeof (objstr)-1) break; /* ')' not found */
-     if ((chr = getc (sklfile)) == EOF) break;
-     if (chr == meta3) break;
-     objstr[objlen++] = chr;
-   }
-   objstr[objlen] = '\0'; /* Now objstr keeps data without metas */
+static SKL_OBJ_CLASS
+objClass(SKL_OBJ_TYP const otyp) {
 
-   if (chr != meta3)    /* Object not found ? */
-   {
-     ADD_STR (slen,line,objlen,objstr);   /* Save what we already read */
-     if (chr == EOF) break;
-     continue;
-   }
+    switch (otyp) {
+    case IRED:
+    case IGREEN:
+    case IBLUE:
+    case ILUM:
+        return OBJTYP_ICOLOR;
 
-   typstr[0] = '\0';           /* Get typ of data */
-   sscanf (objstr,"%s",typstr);
-
-                   /* Check for integer colors */
-   if      (STREQ(typstr,"ired")  ) otyp = IRED;
-   else if (STREQ(typstr,"igreen")) otyp = IGREEN;
-   else if (STREQ(typstr,"iblue") ) otyp = IBLUE;
-   else if (STREQ(typstr,"ilum")  ) otyp = ILUM;
-                   /* Check for real colors */
-   else if (STREQ(typstr,"fred")  ) otyp = FRED;
-   else if (STREQ(typstr,"fgreen")) otyp = FGREEN;
-   else if (STREQ(typstr,"fblue") ) otyp = FBLUE;
-   else if (STREQ(typstr,"flum")  ) otyp = FLUM;
-                   /* Check for integer data */
-   else if (STREQ(typstr,"width") ) otyp = WIDTH;
-   else if (STREQ(typstr,"height")) otyp = HEIGHT;
-   else if (STREQ(typstr,"posx")  ) otyp = POSX;
-   else if (STREQ(typstr,"posy")  ) otyp = POSY;
-   else                                    otyp = BDATA;
-
-   if ((otyp == IRED) || (otyp == IGREEN) || (otyp == IBLUE) || (otyp == ILUM))
-   {
-     n_odata = sscanf (objstr,"%*s%s%d%d",formstr,&icolmin,&icolmax);
-
-     if (n_odata == EOF)  /* No arguments specified ? Use defaults */
-     {
-       strcpy (formstr,"%d"); icolmin = 0; icolmax = 255;
-     }
-     else if (n_odata != 3)  /* Wrong specification */
-     {
-       otyp = BDATA;
-     }
-   }
+    case FRED:
+    case FGREEN:
+    case FBLUE:
+    case FLUM:
+        return OBJTYP_FCOLOR;
 
-   if ((otyp == FRED) || (otyp == FGREEN) || (otyp == FBLUE) || (otyp == FLUM))
-   {
-     n_odata = sscanf (objstr,"%*s%s%lf%lf",formstr,&fcolmin,&fcolmax);
-
-     if (n_odata == EOF)  /* No arguments specified ? Use defaults */
-     {
-       strcpy (formstr,"%f"); fcolmin = 0.0; fcolmax = 1.0;
-     }
-     else if (n_odata != 3)  /* Wrong specification */
-     {
-       otyp = BDATA;
-     }
-   }
+    case WIDTH:
+    case HEIGHT:
+    case POSX:
+    case POSY:
+        return OBJTYP_INT;
+    case BDATA:
+        return OBJTYP_BDATA;
+    }
+    return 999; /* quiet compiler warning */
+}
 
-   if (   (otyp == WIDTH) || (otyp == HEIGHT)
-       || (otyp == POSX) || (otyp == POSY))
-   {
-     n_odata = sscanf (objstr,"%*s%s",formstr);
-
-     if (n_odata == EOF)  /* No arguments specified ? Use defaults */
-     {
-       strcpy (formstr,"%d");
-     }
-     else if (n_odata != 1)  /* Wrong specification */
-     {
-       otyp = BDATA;
-     }
-   }
 
-   if (otyp != BDATA)   /* Got an object definition ? */
-   {
-     if (slen > 0)      /* Save what we already found */
-     {
-       SAVE_BIN (slen,line);
-     }
-   }
 
-   /* Now process the object in objstr */
-   switch (otyp)
-   {
-     case BDATA:   /* Bad object definition ? Save as text */
-       ADD_STR (slen,line,objlen,objstr);
-       break;
+static void
+addImpostorReplacementSeq(char *         const line,
+                          unsigned int   const startCursor,
+                          const char *   const seqContents,
+                          unsigned int   const seqContentsLen,
+                          unsigned int * const newCursorP) {
+/*----------------------------------------------------------------------------
+   Add to line line[], at position 'startCursor', text that looks like a
+   replacement sequence but doesn't have the proper contents (the
+   stuff between the parentheses) to be one.  For example,
 
-     case IRED:
-     case IGREEN:
-     case IBLUE:
-     case ILUM:
-       skl[*nskl] = save_icol_data (otyp,formstr,icolmin,icolmax);
-       if (skl[*nskl] != NULL) (*nskl)++;
-       break;
+     "#(fread x)"
 
-     case FRED:
-     case FGREEN:
-     case FBLUE:
-     case FLUM:
-       skl[*nskl] = save_fcol_data (otyp,formstr,fcolmin,fcolmax);
-       if (skl[*nskl] != NULL) (*nskl)++;
-       break;
+   seqContents[] is the contents; 'seqContentsLen' its length.
 
-     case WIDTH:
-     case HEIGHT:
-     case POSX:
-     case POSY:
-       skl[*nskl] = save_i_data (otyp,formstr);
-       if (skl[*nskl] != NULL) (*nskl)++;
-       break;
-   }
- } /* EOF of skeleton file */
+   Return as *newCursorP where the line[] cursor ends up after adding
+   the sequence.
+-----------------------------------------------------------------------------*/
+    unsigned int cursor;
+    unsigned int i;
 
- if (slen > 0)      /* Drop finishing newline character */
- {
-   if (line[slen-1] == '\n') slen--;
- }
+    cursor = startCursor;
 
- if (slen > 0)      /* Something left ? */
- {
-   SAVE_BIN (slen,line);   /* Save it */
- }
+    line[cursor++] = escape;
+    line[cursor++] = '(';
 
- fclose (sklfile);
- return (0);
+    for (i = 0; i < seqContentsLen; ++i)
+        line[cursor++] = seqContents[i];
+
+    line[cursor++] = ')';
+
+    *newCursorP = cursor;
 }
 
 
+
+static int
+read_skeleton(const char *   const filename,
+              unsigned int   const maxskl,
+              unsigned int * const nsklP,
+              SKL_OBJ **     const skl) {
+/*----------------------------------------------------------------------------
+  Read skeleton file
+-----------------------------------------------------------------------------*/
+    FILE * sklfile;
+    unsigned int slen;
+    unsigned int objlen;
+    int chr;
+    SKL_OBJ_TYP otyp;
+    char line[MAX_LINE_BUF+MAX_OBJ_BUF+16];
+    char objstr[MAX_OBJ_BUF],typstr[MAX_OBJ_BUF];
+    unsigned int nskl;
+
+#define SAVE_BIN(slen,line) \
+    { if (slen > 0 && (skl[nskl] = save_bin_data(slen,line)) != NULL) ++nskl; \
+      slen = 0; }
+
+    sklfile = pm_openr(filename);
+
+    /* Parse skeleton file */
+    nskl = 0;  /* initial value */
+
+    slen = 0;
+    while ((chr = getc (sklfile)) != EOF) {  /* Up to end of skeleton file */
+        if (nskl >= maxskl)
+            return -1;
+
+        if (slen+1 >= MAX_LINE_BUF) {
+            /* Buffer finished.  Save as binary object */
+            SAVE_BIN(slen,line);
+        }
+
+        if (chr != escape) {
+            /* Not a replacement sequence; just a literal character */
+            line[slen++] = chr;
+            continue;
+        }
+
+        chr = getc(sklfile);
+        if (chr == EOF) {
+            /* Not a valid replacement sequence */
+            line[slen++] = escape;
+            break;
+        }
+        if (chr != '(') {
+            /* Not a valid replacement sequence */
+            line[slen++] = escape;
+            line[slen++] = chr;
+            continue;
+        }
+        /* Read replacement string up through ')'.  Put contents of
+           parentheses in objstr[].
+        */
+        for (objlen = 0; objlen < sizeof(objstr)-1; ++objlen) {
+            chr = getc(sklfile);
+            if (chr == EOF) break;
+            if (chr == ')') break;
+            objstr[objlen] = chr;
+        }
+        objstr[objlen] = '\0';
+
+        if (chr != ')') {
+            /* Not valid replacement sequence */
+            unsigned int i;
+            line[slen++] = escape;
+            line[slen++] = chr;
+            for (i = 0; i < objlen; ++i)
+                line[slen++] = objstr[i];
+            if (chr == EOF)
+                break;
+            continue;
+        }
+
+        typstr[0] = '\0';           /* Get typ of data */
+        sscanf(objstr, "%s", typstr);
+
+        otyp = interpretObjType(typstr);
+
+        switch (objClass(otyp)) {
+        case OBJTYP_ICOLOR: {
+            int icolmin, icolmax;
+            char formstr[MAX_OBJ_BUF];
+            int n_odata;
+
+            n_odata = sscanf(objstr, "%*s%s%d%d", formstr, &icolmin, &icolmax);
+
+            if (n_odata == 3) {
+                SAVE_BIN(slen, line);
+                skl[nskl] = save_icol_data(otyp, formstr, icolmin, icolmax);
+                if (skl[nskl] != NULL)
+                    ++nskl;
+            } else if (n_odata == EOF) {
+                /* No arguments specified.  Use defaults */
+                SAVE_BIN(slen, line);
+                skl[nskl] = save_icol_data(otyp, "%d", 0, 255);
+                if (skl[nskl] != NULL)
+                    ++nskl;
+            } else
+                addImpostorReplacementSeq(line, slen, objstr, objlen, &slen);
+        } break;
+        case OBJTYP_FCOLOR: {
+            double fcolmin, fcolmax;
+            char formstr[MAX_OBJ_BUF];
+            int n_odata;
+
+            n_odata = sscanf(objstr, "%*s%s%lf%lf", formstr,
+                             &fcolmin, &fcolmax);
+
+            if (n_odata == 3) {
+                SAVE_BIN(slen, line);
+                skl[nskl] = save_fcol_data(otyp, formstr, fcolmin, fcolmax);
+                if (skl[nskl] != NULL)
+                    ++nskl;
+            } else if (n_odata == EOF) {
+                /* No arguments specified.  Use defaults */
+                SAVE_BIN(slen, line);
+                skl[nskl] = save_fcol_data(otyp, "%f", 0.0, 1.0);
+                if (skl[nskl] != NULL)
+                    ++nskl;
+            } else
+                addImpostorReplacementSeq(line, slen, objstr, objlen, &slen);
+        } break;
+
+        case OBJTYP_INT: {
+            char formstr[MAX_OBJ_BUF];
+            int const n_odata = sscanf(objstr, "%*s%s", formstr);
+
+            if (n_odata == 1) {
+                SAVE_BIN(slen, line);
+                skl[nskl] = save_i_data(otyp, formstr);
+                if (skl[nskl] != NULL)
+                    ++nskl;
+            } else if (n_odata == EOF) {
+                /* No arguments specified.  Use defaults */
+                SAVE_BIN(slen, line);
+                skl[nskl] = save_i_data(otyp, "%d");
+                if (skl[nskl] != NULL)
+                    ++nskl;
+            } else
+                addImpostorReplacementSeq(line, slen, objstr, objlen, &slen);
+        } break;
+        case OBJTYP_BDATA:
+            addImpostorReplacementSeq(line, slen, objstr, objlen, &slen);
+        }
+    } /* EOF of skeleton file */
+
+    if (slen >= 1 && line[slen-1] == '\n')
+        /* Drop finishing newline character */
+        --slen;
+
+    SAVE_BIN(slen, line);  /* Save whatever is left */
+
+    *nsklP = nskl;
+
+    fclose(sklfile);
+    return 0;
+}
+
+
+
 int main( argc, argv )
 int argc;
 char* argv[];
@@ -419,7 +494,7 @@ char* argv[];
  pixval maxval,red,green,blue;
  double dmaxval;
  int argn, rows, cols, format, row;
- int head_nskl,body_nskl,tail_nskl;
+ unsigned int head_nskl,body_nskl,tail_nskl;
  SKL_OBJ *head_skl[MAX_SKL_HEAD_OBJ];
  SKL_OBJ *body_skl[MAX_SKL_BODY_OBJ];
  SKL_OBJ *tail_skl[MAX_SKL_TAIL_OBJ];
diff --git a/converter/ppm/ppmtobmp.c b/converter/ppm/ppmtobmp.c
index 635464dd..c295f70c 100644
--- a/converter/ppm/ppmtobmp.c
+++ b/converter/ppm/ppmtobmp.c
@@ -18,15 +18,24 @@
 
 #include <assert.h>
 #include <string.h>
-#include "bmp.h"
-#include "ppm.h"
+
+#include "pm_c_util.h"
+#include "mallocvar.h"
 #include "shhopt.h"
+#include "bmp.h"
 #include "bitio.h"
+#include "ppm.h"
 
 #define MAXCOLORS 256
 
 enum colortype {TRUECOLOR, PALETTE};
 
+struct rgb {
+    unsigned char red;
+    unsigned char grn;
+    unsigned char blu;
+};
+
 typedef struct {
 /*----------------------------------------------------------------------------
    A color map for a BMP file.
@@ -34,13 +43,13 @@ typedef struct {
     unsigned int count;
         /* Number of colors in the map.  The first 'count' elements of these
            arrays are defined; all others are not.
+
+           At most MAXCOLORS.
         */
     colorhash_table cht;
 
-    /* Indices in the following arrays are the same as in 'cht', above. */
-    unsigned char red[MAXCOLORS];
-    unsigned char grn[MAXCOLORS];
-    unsigned char blu[MAXCOLORS];
+    /* Indices in the following array are the same as in 'cht', above. */
+    struct rgb bmpMap[MAXCOLORS];
 } colorMap;
 
 
@@ -54,7 +63,7 @@ freeColorMap(const colorMap * const colorMapP) {
 
 
 
-static struct cmdline_info {
+struct cmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
@@ -62,63 +71,71 @@ static struct cmdline_info {
     int class;  /* C_WIN or C_OS2 */
     unsigned int bppSpec;
     unsigned int bpp;
-} cmdline;
+    const char * mapfile;
+};
 
 
 static void
-parse_command_line(int argc, char ** argv,
-                   struct cmdline_info *cmdline_p) {
+parseCommandLine(int argc, const char ** argv,
+                 struct cmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that many of the strings that this function returns in the
    *cmdline_p structure are actually in the supplied argv array.  And
    sometimes, one of these strings is actually just a suffix of an entry
    in argv!
 -----------------------------------------------------------------------------*/
-    optEntry *option_def = malloc(100*sizeof(optEntry));
+    optEntry * option_def;
         /* Instructions to OptParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
 
-    unsigned int windowsSpec, os2Spec;
+    unsigned int windowsSpec, os2Spec, mapfileSpec;
 
     unsigned int option_def_index;
+    
+    MALLOCARRAY(option_def, 100);
 
     option_def_index = 0;   /* incremented by OPTENTRY */
     OPTENT3('w', "windows",   OPT_FLAG, NULL, &windowsSpec,            0);
     OPTENT3('o', "os2",       OPT_FLAG, NULL, &os2Spec,                0);
-    OPTENT3(0,   "bpp",       OPT_UINT, &cmdline_p->bpp, 
-            &cmdline_p->bppSpec,      0);
+    OPTENT3(0,   "bpp",       OPT_UINT, &cmdlineP->bpp, 
+            &cmdlineP->bppSpec,      0);
+    OPTENT3(0,   "mapfile",   OPT_STRING, &cmdlineP->mapfile, 
+            &mapfileSpec,             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);
+    optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
 
     if (windowsSpec && os2Spec) 
         pm_error("Can't specify both -windows and -os2 options.");
     else if (windowsSpec) 
-        cmdline_p->class = C_WIN;
+        cmdlineP->class = C_WIN;
     else if (os2Spec)
-        cmdline_p->class = C_OS2;
+        cmdlineP->class = C_OS2;
     else 
-        cmdline_p->class = C_WIN;
+        cmdlineP->class = C_WIN;
 
 
-    if (cmdline_p->bppSpec) {
-        if (cmdline_p->bpp != 1 && cmdline_p->bpp != 4 && 
-            cmdline_p->bpp != 8 && cmdline_p->bpp != 24)
-        pm_error("Invalid -bpp value specified: %u.  The only values valid\n"
+    if (cmdlineP->bppSpec) {
+        if (cmdlineP->bpp != 1 && cmdlineP->bpp != 4 && 
+            cmdlineP->bpp != 8 && cmdlineP->bpp != 24)
+        pm_error("Invalid -bpp value specified: %u.  The only values valid "
                  "in the BMP format are 1, 4, 8, and 24 bits per pixel",
-                 cmdline_p->bpp);
+                 cmdlineP->bpp);
     }
 
+    if (!mapfileSpec)
+        cmdlineP->mapfile = NULL;
+
     if (argc - 1 == 0)
-        cmdline_p->input_filename = strdup("-");  /* he wants stdin */
+        cmdlineP->input_filename = strdup("-");  /* he wants stdin */
     else if (argc - 1 == 1)
-        cmdline_p->input_filename = strdup(argv[1]);
+        cmdlineP->input_filename = strdup(argv[1]);
     else 
-        pm_error("Too many arguments.  The only argument accepted\n"
+        pm_error("Too many arguments.  The only argument accepted "
                  "is the input file specificaton");
 
 }
@@ -243,7 +260,7 @@ BMPwriteinfoheader(FILE *        const fp,
 
 
 static int
-BMPwritergb(FILE * const fp, 
+BMPwriteRgb(FILE * const fp, 
             int    const class, 
             pixval const R, 
             pixval const G, 
@@ -264,7 +281,7 @@ BMPwritergb(FILE * const fp,
         PutByte(fp, R);
         return 3;
     default:
-        pm_error(er_internal, "BMPwritergb");
+        pm_error(er_internal, "BMPwriteRgb");
     }
     return -1;
 }
@@ -272,101 +289,118 @@ BMPwritergb(FILE * const fp,
 
 
 static int
-BMPwritecolormap(FILE *           const ifP, 
+BMPwriteColormap(FILE *           const ifP, 
                  int              const class, 
                  int              const bpp,
                  const colorMap * const colorMapP) {
 /*----------------------------------------------------------------------------
   Return the number of bytes written, or -1 on error.
 -----------------------------------------------------------------------------*/
-    long const ncolors = (1 << bpp);
+    unsigned int const ncolors = (1 << bpp);
 
-    unsigned int  nbyte;
-    unsigned int  i;
+    unsigned int nbyte;
+    unsigned int i;
 
-    nbyte = 0;
-    for (i = 0; i < colorMapP->count; ++i)
-        nbyte += BMPwritergb(ifP, class,
-                             colorMapP->red[i],
-                             colorMapP->grn[i],
-                             colorMapP->blu[i]);
+    assert(ncolors <= MAXCOLORS);
+    assert(ncolors <= ARRAY_SIZE(colorMapP->bmpMap));
 
+    nbyte = 0;
+    for (i = 0; i < colorMapP->count; ++i) {
+        const struct rgb * const mapEntryP = &colorMapP->bmpMap[i];
+        nbyte += BMPwriteRgb(ifP, class,
+                             mapEntryP->red, mapEntryP->grn, mapEntryP->blu);
+    }
     for (; i < ncolors; ++i)
-        nbyte += BMPwritergb(ifP, class, 0, 0, 0);
+        nbyte += BMPwriteRgb(ifP, class, 0, 0, 0);
 
     return nbyte;
 }
 
 
 
-static int
-BMPwriterow_palette(FILE *          const fp, 
+static void
+lookupColor(colorhash_table const cht,
+            pixel           const color,
+            unsigned int *  const colorIndexP) {
+
+    int rc;
+
+    rc = ppm_lookupcolor(cht, &color);
+
+    if (rc < 0)
+        pm_error("Color (%u,%u,%u) is not in the provided palette",
+                 PPM_GETR(color), PPM_GETG(color), PPM_GETB(color));
+    else
+        *colorIndexP = rc;
+}
+
+
+
+static void
+bmpWriteRow_palette(FILE *          const fp, 
                     const pixel *   const row, 
-                    unsigned long   const cx, 
+                    unsigned int    const cols,
                     unsigned short  const bpp, 
-                    colorhash_table const cht) {
+                    colorhash_table const cht,
+                    unsigned int *  const nBytesP) {
 /*----------------------------------------------------------------------------
-  Return the number of bytes written, or -1 on error.
+   Write a row to the raster in paletted format.
+
+   Return the number of bytes written as *nBytesP.
 -----------------------------------------------------------------------------*/
-    BITSTREAM    b;
-    int retval;
+    BITSTREAM b;
     
     b = pm_bitinit(fp, "w");
     if (b == NULL)
-        retval = -1;
+        pm_error("Failed to initialize output file for output");
     else {
+        int rc;
         unsigned int nbyte;
-        unsigned int x;
-        bool         error;
+        unsigned int col;
         
         nbyte = 0;      /* initial value */
-        error = FALSE;  /* initial value */
         
-        for (x = 0; x < cx && !error; ++x) {
+        for (col = 0; col < cols; ++col) {
+            unsigned int colorIndex;
             int rc;
-            rc = pm_bitwrite(b, bpp, ppm_lookupcolor(cht, &row[x]));
+
+            lookupColor(cht, row[col], &colorIndex);
+
+            rc = pm_bitwrite(b, bpp, colorIndex);
             if (rc == -1)
-                error = TRUE;
+                pm_error("Failed in writing a pixel "
+                         "to the raster in the output file");
             else
                 nbyte += rc;
         }
-        if (error)
-            retval = -1;
-        else {
-            int rc;
 
-            rc = pm_bitfini(b);
-            if (rc == -1)
-                retval = -1;
-            else {
-                nbyte += rc;
+        rc = pm_bitfini(b);
+
+        nbyte += rc;
                 
-                /* Make sure we write a multiple of 4 bytes.  */
-                while (nbyte % 4 != 0) {
-                    PutByte(fp, 0);
-                    ++nbyte;
-                }
-                retval = nbyte;
-            }
+        /* Make sure we write a multiple of 4 bytes.  */
+        while (nbyte % 4 != 0) {
+            PutByte(fp, 0);
+            ++nbyte;
         }
+        *nBytesP = nbyte;
     }
-    return retval;
 }
 
 
 
-static int
-BMPwriterow_truecolor(FILE *        const fp, 
-                      const pixel * const row, 
-                      unsigned long const cols,
-                      pixval        const maxval) {
+static void
+bmpWriteRow_truecolor(FILE *         const fp, 
+                      const pixel *  const row, 
+                      unsigned long  const cols,
+                      pixval         const maxval,
+                      unsigned int * const nBytesP) {
 /*----------------------------------------------------------------------------
   Write a row of a truecolor BMP image to the file 'fp'.  The row is 
   'row', which is 'cols' columns long.
 
-  Return the number of bytes written.
 
-  On error, issue error message and exit program.
+  Return the number of bytes written as *nBytesP.
 -----------------------------------------------------------------------------*/
     /* This works only for 24 bits per pixel.  To implement this for the
        general case (which is only hypothetical -- this program doesn't
@@ -380,7 +414,7 @@ BMPwriterow_truecolor(FILE *        const fp,
     int col;  
         
     nbyte = 0;  /* initial value */
-    for (col = 0; col < cols; col++) {
+    for (col = 0; col < cols; ++col) {
         /* We scale to the BMP maxval, which is always 255. */
         PutByte(fp, PPM_GETB(row[col]) * 255 / maxval);
         PutByte(fp, PPM_GETG(row[col]) * 255 / maxval);
@@ -393,18 +427,18 @@ BMPwriterow_truecolor(FILE *        const fp,
      */
     while (nbyte % 4) {
         PutByte(fp, 0);
-        nbyte++;
+        ++nbyte;
     }
     
-    return nbyte;
+    *nBytesP = nbyte;
 }
 
 
 
 static int
 BMPwritebits(FILE *          const fp, 
-             unsigned long   const cx, 
-             unsigned long   const cy, 
+             unsigned long   const cols, 
+             unsigned long   const rows,
              enum colortype  const colortype,
              unsigned short  const cBitCount, 
              const pixel **  const pixels, 
@@ -413,29 +447,29 @@ BMPwritebits(FILE *          const fp,
 /*----------------------------------------------------------------------------
   Return the number of bytes written, or -1 on error.
 -----------------------------------------------------------------------------*/
-    int  nbyte;
-    long y;
+    unsigned int nbyte;
+    int row;
 
     if (cBitCount > 24)
-        pm_error("cannot handle cBitCount: %d", cBitCount);
+        pm_error("cannot handle cBitCount: %hu", cBitCount);
 
     nbyte = 0;  /* initial value */
 
     /* The picture is stored bottom line first, top line last */
 
-    for (y = cy - 1; y >= 0; --y) {
-        int rc;
+    for (row = rows - 1; row >= 0; --row) {
+        unsigned int nBytesThisRow;
+
         if (colortype == PALETTE)
-            rc = BMPwriterow_palette(fp, pixels[y], cx, 
-                                     cBitCount, cht);
+            bmpWriteRow_palette(fp, pixels[row], cols, 
+                                cBitCount, cht, &nBytesThisRow);
         else 
-            rc = BMPwriterow_truecolor(fp, pixels[y], cx, maxval);
+            bmpWriteRow_truecolor(fp, pixels[row], cols, maxval,
+                                  &nBytesThisRow);
 
-        if (rc == -1)
-            pm_error("couldn't write row %ld", y);
-        if (rc % 4 != 0)
-            pm_error("row had bad number of bytes: %d", rc);
-        nbyte += rc;
+        if (nBytesThisRow % 4 != 0)
+            pm_error("row had bad number of bytes: %u", nBytesThisRow);
+        nbyte += nBytesThisRow;
     }
 
     return nbyte;
@@ -444,10 +478,10 @@ BMPwritebits(FILE *          const fp,
 
 
 static void
-BMPEncode(FILE *           const ifP, 
+bmpEncode(FILE *           const ifP, 
           int              const class, 
           enum colortype   const colortype,
-          int              const bpp,
+          unsigned int     const bpp,
           int              const x, 
           int              const y, 
           const pixel **   const pixels, 
@@ -459,25 +493,25 @@ BMPEncode(FILE *           const ifP,
     unsigned long nbyte;
 
     if (colortype == PALETTE)
-        pm_message("Writing %d bits per pixel with a color palette", bpp);
+        pm_message("Writing %u bits per pixel with a color palette", bpp);
     else
-        pm_message("Writing %d bits per pixel truecolor (no palette)", bpp);
+        pm_message("Writing %u bits per pixel truecolor (no palette)", bpp);
 
     nbyte = 0;  /* initial value */
     nbyte += BMPwritefileheader(ifP, class, bpp, x, y);
     nbyte += BMPwriteinfoheader(ifP, class, bpp, x, y);
     if (colortype == PALETTE)
-        nbyte += BMPwritecolormap(ifP, class, bpp, colorMapP);
+        nbyte += BMPwriteColormap(ifP, class, bpp, colorMapP);
 
     if (nbyte != (BMPlenfileheader(class)
                   + BMPleninfoheader(class)
                   + BMPlencolormap(class, bpp, 0)))
-        pm_error(er_internal, "BMPEncode 1");
+        pm_error(er_internal, "BmpEncode 1");
 
     nbyte += BMPwritebits(ifP, x, y, colortype, bpp, pixels, maxval,
                           colorMapP->cht);
     if (nbyte != BMPlenfile(class, bpp, -1, x, y))
-        pm_error(er_internal, "BMPEncode 2");
+        pm_error(er_internal, "BmpEncode 2");
 }
 
 
@@ -487,18 +521,18 @@ makeBilevelColorMap(colorMap * const colorMapP) {
 
     colorMapP->count  = 2;
     colorMapP->cht    = NULL;
-    colorMapP->red[0] = 0;
-    colorMapP->grn[0] = 0;
-    colorMapP->blu[0] = 0;
-    colorMapP->red[1] = 255;
-    colorMapP->grn[1] = 255;
-    colorMapP->blu[1] = 255;
+    colorMapP->bmpMap[0].red = 0;
+    colorMapP->bmpMap[0].grn = 0;
+    colorMapP->bmpMap[0].blu = 0;
+    colorMapP->bmpMap[1].red = 255;
+    colorMapP->bmpMap[1].grn = 255;
+    colorMapP->bmpMap[1].blu = 255;
 }
 
 
 
 static void
-BMPEncodePBM(FILE *           const ifP, 
+bmpEncodePbm(FILE *           const ifP, 
              int              const class, 
              int              const cols, 
              int              const rows, 
@@ -508,7 +542,7 @@ BMPEncodePBM(FILE *           const ifP,
 -----------------------------------------------------------------------------*/
     /* Note:
        Only PBM input uses this routine.  Color images represented by 1 bpp via
-       color palette use the general BMPEncode().
+       color palette use the general bmpEncode().
     */
     unsigned int const adjustedCols = (cols + 31) / 32 * 32;
     unsigned int const packedBytes  = adjustedCols / 8;
@@ -526,12 +560,12 @@ BMPEncodePBM(FILE *           const ifP,
 
     makeBilevelColorMap(&bilevelColorMap);
 
-    nbyte += BMPwritecolormap(ifP, class, 1, &bilevelColorMap);
+    nbyte += BMPwriteColormap(ifP, class, 1, &bilevelColorMap);
 
     if (nbyte != (BMPlenfileheader(class)
                   + BMPleninfoheader(class)
                   + BMPlencolormap(class, 1, 0)))
-        pm_error(er_internal, "BMPEncodePBM 1");
+        pm_error(er_internal, "bmpEncodePBM 1");
    
     for (row = 0; row < rows; ++row){
         size_t bytesWritten;
@@ -548,23 +582,129 @@ BMPEncodePBM(FILE *           const ifP,
     }
 
     if (nbyte != BMPlenfile(class, 1, -1, cols, rows))
-        pm_error(er_internal, "BMPEncodePBM 2");
+        pm_error(er_internal, "bmpEncodePbm 2");
 }
 
 
 
 static void
-analyze_colors(const pixel **    const pixels, 
-               int               const cols, 
-               int               const rows, 
-               pixval            const maxval, 
-               int *             const minimum_bpp_p,
-               colorMap *        const colorMapP) {
+makeHashFromBmpMap(const struct rgb * const bmpMap,
+                   unsigned int       const nColors,
+                   colorhash_table *  const chtP) {
+
+    colorhist_vector chv;
+    unsigned int i;
+
+    MALLOCARRAY_NOFAIL(chv, nColors);
+
+    for (i = 0; i < nColors; ++i) {
+        const struct rgb * const mapEntryP = &bmpMap[i];
+
+        PPM_ASSIGN(chv[i].color,
+                   mapEntryP->red, mapEntryP->grn, mapEntryP->blu);
+    }
+
+    *chtP = ppm_colorhisttocolorhash(chv, nColors);
+
+    ppm_freecolorhist(chv);
+}
+
+
+
+static unsigned int
+minBmpBitsForColorCount(unsigned int const colorCount) {
+
+    unsigned int const minbits = pm_maxvaltobits(colorCount - 1);
+
+    /* Only 1, 4, 8, and 24 are defined in the BMP spec we
+       implement and other bpp's have in fact been seen to confuse
+       viewers.  There is an extended BMP format that has 16 bpp
+       too, but this program doesn't know how to generate that
+       (see Bmptopnm.c, though).  
+    */
+    if (minbits == 1)
+        return 1;
+    else if (minbits <= 4)
+        return 4;
+    else if (minbits <= 8)
+        return 8;
+    else
+        return 24;
+}
+
+
+
+static void
+getMapFile(const char *   const mapFileName,
+           unsigned int * const minimumBppP,
+           colorMap *     const colorMapP) {
+/*----------------------------------------------------------------------------
+   Get the color map (palette) for the BMP from file 'mapFileName'.
+
+   Return the color map as *colormapP.
+
+   Return as *minimumBppP the minimum number of bits per pixel it will
+   take to represent all the colors in the map in the BMP format.
+-----------------------------------------------------------------------------*/
+
+    FILE * mapFileP;
+    int cols, rows;
+    pixval maxval;
+    pixel ** pixels;
+    unsigned int row;
+    unsigned int count;
+
+    mapFileP = pm_openr(mapFileName);
+
+    pixels = ppm_readppm(mapFileP, &cols, &rows, &maxval);
+
+    if (cols * rows > MAXCOLORS)
+        pm_error("The colormap file you gave (-mapfile) has too "
+                 "many entries for a BMP.  A BMP can have at most "
+                 "%u colors; the file has %u pixels, each of which "
+                 "represents an entry in the color map.",
+                 MAXCOLORS, cols * rows);
+
+    count = 0; /* initial value */
+    
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        for (col = 0; col < cols; ++col) {
+            pixel        const color     = pixels[row][col];
+            struct rgb * const mapEntryP = &colorMapP->bmpMap[count++];
+
+            assert(count <= ARRAY_SIZE(colorMapP->bmpMap));
+
+            mapEntryP->red = PPM_GETR(color) * 255 / maxval;
+            mapEntryP->grn = PPM_GETG(color) * 255 / maxval;
+            mapEntryP->blu = PPM_GETB(color) * 255 / maxval;
+        }
+    }
+    ppm_freearray(pixels, rows);
+
+    colorMapP->count = count;
+
+    makeHashFromBmpMap(colorMapP->bmpMap, colorMapP->count, &colorMapP->cht);
+
+    *minimumBppP = minBmpBitsForColorCount(count);
+
+    pm_close(mapFileP);
+}
+
+
+
+static void
+analyzeColors(const pixel **    const pixels, 
+              int               const cols, 
+              int               const rows, 
+              pixval            const maxval, 
+              unsigned int *    const minimumBppP,
+              colorMap *        const colorMapP) {
 /*----------------------------------------------------------------------------
   Look at the colors in the image 'pixels' and compute values to use in
   representing those colors in a BMP image.  
 
-  First of all, count the distinct colors.  Return as *minimum_bpp_p
+  First of all, count the distinct colors.  Return as *minimumBppP
   the minimum number of bits per pixel it will take to represent all
   the colors in BMP format.
 
@@ -589,37 +729,23 @@ analyze_colors(const pixel **    const pixels,
     colorMapP->count = colorCount;
     if (chv == NULL) {
         pm_message("More than %u colors found", MAXCOLORS);
-        *minimum_bpp_p = 24;
+        *minimumBppP = 24;
         colorMapP->cht = NULL;
     } else {
-        unsigned int const minbits = pm_maxvaltobits(colorMapP->count - 1);
-
         unsigned int i;
 
         pm_message("%u colors found", colorMapP->count);
 
-        /* Only 1, 4, 8, and 24 are defined in the BMP spec we
-           implement and other bpp's have in fact been seen to confuse
-           viewers.  There is an extended BMP format that has 16 bpp
-           too, but this program doesn't know how to generate that
-           (see Bmptopnm.c, though).  
-        */
-        if (minbits == 1)
-            *minimum_bpp_p = 1;
-        else if (minbits <= 4)
-            *minimum_bpp_p = 4;
-        else if (minbits <= 8)
-            *minimum_bpp_p = 8;
-        else
-            *minimum_bpp_p = 24;
+        *minimumBppP = minBmpBitsForColorCount(colorMapP->count);
 
         /*
          * Now scale the maxval to 255 as required by BMP format.
          */
         for (i = 0; i < colorMapP->count; ++i) {
-            colorMapP->red[i] = (pixval) PPM_GETR(chv[i].color) * 255 / maxval;
-            colorMapP->grn[i] = (pixval) PPM_GETG(chv[i].color) * 255 / maxval;
-            colorMapP->blu[i] = (pixval) PPM_GETB(chv[i].color) * 255 / maxval;
+            struct rgb * const mapEntryP = &colorMapP->bmpMap[i];
+            mapEntryP->red = (pixval) PPM_GETR(chv[i].color) * 255 / maxval;
+            mapEntryP->grn = (pixval) PPM_GETG(chv[i].color) * 255 / maxval;
+            mapEntryP->blu = (pixval) PPM_GETB(chv[i].color) * 255 / maxval;
         }
     
         /* And make a hash table for fast lookup. */
@@ -631,38 +757,52 @@ analyze_colors(const pixel **    const pixels,
 
 
 static void
-choose_colortype_bpp(struct cmdline_info const cmdline,
-                     unsigned int        const colors, 
-                     unsigned int        const minimum_bpp,
-                     enum colortype *    const colortype_p, 
-                     unsigned int *      const bits_per_pixel_p) {
+chooseColortypeBpp(bool             const userRequestsBpp,
+                   unsigned int     const requestedBpp,
+                   unsigned int     const minimumBpp,
+                   enum colortype * const colortypeP, 
+                   unsigned int *   const bitsPerPixelP) {
+/*----------------------------------------------------------------------------
+   Determine whether the BMP raster should contain RGB values or palette
+   indices and how many bits is should have for each pixel.
 
-    if (!cmdline.bppSpec) {
+   'userRequestsBpp' says the user has requested a particular number of
+   bits per pixel.  'requestedBpp' is his request, and we assume it's a
+   valid value for a BMP.
+
+   'colors' is how many colors are in the image.
+
+   'minimumBpp' is the minimum number of bits it takes to represent all
+   the colors in the image.  We assume it is valid for a BMP.
+
+   We return our choices as *colortypeP and *bitsPerPixelP.
+-----------------------------------------------------------------------------*/
+    if (!userRequestsBpp) {
         /* User has no preference as to bits per pixel.  Choose the
            smallest number possible for this image.
         */
-        *bits_per_pixel_p = minimum_bpp;
+        *bitsPerPixelP = minimumBpp;
     } else {
-        if (cmdline.bpp < minimum_bpp)
+        if (requestedBpp < minimumBpp)
             pm_error("There are too many colors in the image to "
-                     "represent in the\n"
-                     "number of bits per pixel you requested: %d.\n"
-                     "You may use Ppmquant to reduce the number of "
+                     "represent in the "
+                     "number of bits per pixel you requested: %d.  "
+                     "You may use Pnmquant to reduce the number of "
                      "colors in the image.",
-                     cmdline.bpp);
+                     requestedBpp);
         else
-            *bits_per_pixel_p = cmdline.bpp;
+            *bitsPerPixelP = requestedBpp;
     }
 
-    assert(*bits_per_pixel_p == 1 || 
-           *bits_per_pixel_p == 4 || 
-           *bits_per_pixel_p == 8 || 
-           *bits_per_pixel_p == 24);
+    assert(*bitsPerPixelP == 1 || 
+           *bitsPerPixelP == 4 || 
+           *bitsPerPixelP == 8 || 
+           *bitsPerPixelP == 24);
 
-    if (*bits_per_pixel_p > 8) 
-        *colortype_p = TRUECOLOR;
+    if (*bitsPerPixelP > 8) 
+        *colortypeP = TRUECOLOR;
     else {
-        *colortype_p = PALETTE;
+        *colortypeP = PALETTE;
     }
 }
 
@@ -676,12 +816,12 @@ doPbm(FILE *       const ifP,
       int          const class,
       FILE *       const ofP) {
     
-    /*  In the PBM case the raster is read directly from the input by 
-        pbm_readpbmrow_packed.  The raster format is almost identical,
-        except that BMP specifies rows to be zero-filled to 32 bit borders 
-        and that in BMP the bottom row comes first in order.
+    /* We read the raster directly from the input with
+        pbm_readpbmrow_packed().  The raster format is almost
+        identical, except that BMP specifies rows to be zero-filled to
+        32 bit borders and that in BMP the bottom row comes first in
+        order.
     */
-
     int const CHARBITS = (sizeof(unsigned char)*8); 
     int const colChars = pbm_packed_bytes(cols);
     int const adjustedCols = (cols+31) /32 * 32;
@@ -709,7 +849,7 @@ doPbm(FILE *       const ifP,
                 thisRow[i] = ~thisRow[i]; /* flip all pixels */
         }
         /* This may seem unnecessary, because the color palette 
-           (RGB[] in BMPEncodePBM) can be inverted for the same effect.
+           (RGB[] in bmpEncodePbm) can be inverted for the same effect.
            However we take this precaution, for there is indication that
            some BMP viewers may get confused with that.
         */
@@ -721,25 +861,28 @@ doPbm(FILE *       const ifP,
         }
     }
 
-    BMPEncodePBM(ofP, class, cols, rows, bitrow);
+    bmpEncodePbm(ofP, class, cols, rows, bitrow);
 }            
 
 
 
 static void
-doPgmPpm(FILE * const ifP,
+doPgmPpm(FILE *       const ifP,
          unsigned int const cols,
          unsigned int const rows,
          pixval       const maxval,
          int          const ppmFormat,
          int          const class,
+         bool         const userRequestsBpp,
+         unsigned int const requestedBpp,
+         const char * const mapFileName,
          FILE *       const ofP) {
 
-    /* PGM and PPM.  The input image is read into a PPM array, scanned
-       for color analysis and converted to a BMP raster.
-       Logic works for PBM.
+    /* PGM and PPM.  We read the input image into a PPM array, scan it
+       to analyze the colors, and convert it to a BMP raster.  Logic
+       works for PBM.
     */
-    int minimumBpp;
+    unsigned int minimumBpp;
     unsigned int bitsPerPixel;
     enum colortype colortype;
     unsigned int row;
@@ -752,13 +895,16 @@ doPgmPpm(FILE * const ifP,
     for (row = 0; row < rows; ++row)
         ppm_readppmrow(ifP, pixels[row], cols, maxval, ppmFormat);
     
-    analyze_colors((const pixel**)pixels, cols, rows, maxval, 
-                   &minimumBpp, &colorMap);
+    if (mapFileName)
+        getMapFile(mapFileName, &minimumBpp, &colorMap);
+    else
+        analyzeColors((const pixel**)pixels, cols, rows, maxval, 
+                      &minimumBpp, &colorMap);
     
-    choose_colortype_bpp(cmdline, colorMap.count, minimumBpp, &colortype, 
-                         &bitsPerPixel);
+    chooseColortypeBpp(userRequestsBpp, requestedBpp, minimumBpp,
+                       &colortype, &bitsPerPixel);
     
-    BMPEncode(stdout, class, colortype, bitsPerPixel,
+    bmpEncode(ofP, class, colortype, bitsPerPixel,
               cols, rows, (const pixel**)pixels, maxval, &colorMap);
     
     freeColorMap(&colorMap);
@@ -767,17 +913,19 @@ doPgmPpm(FILE * const ifP,
 
 
 int
-main(int argc, char **argv) {
+main(int           argc,
+     const char ** argv) {
 
+    struct cmdlineInfo cmdline;
     FILE * ifP;
     int rows;
     int cols;
     pixval maxval;
     int ppmFormat;
 
-    ppm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
-    parse_command_line(argc, argv, &cmdline);
+    parseCommandLine(argc, argv, &cmdline);
 
     ifP = pm_openr(cmdline.input_filename);
     
@@ -786,7 +934,9 @@ main(int argc, char **argv) {
     if (PPM_FORMAT_TYPE(ppmFormat) == PBM_TYPE)
         doPbm(ifP, cols, rows, ppmFormat, cmdline.class, stdout);
     else
-        doPgmPpm(ifP, cols, rows, maxval, ppmFormat, cmdline.class, stdout);
+        doPgmPpm(ifP, cols, rows, maxval, ppmFormat,
+                 cmdline.class, cmdline.bppSpec, cmdline.bpp, cmdline.mapfile,
+                 stdout);
 
     pm_close(ifP);
     pm_close(stdout);
diff --git a/converter/ppm/ppmtogif.c b/converter/ppm/ppmtogif.c
index 21ac1989..93feaa95 100644
--- a/converter/ppm/ppmtogif.c
+++ b/converter/ppm/ppmtogif.c
@@ -1,101 +1,63 @@
-/* ppmtogif.c - read a portable pixmap and produce a GIF file
-**
-** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>.A
-** Lempel-Zim compression based on "compress".
-**
-** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
-**
-** The non-LZW GIF generation stuff was adapted from the Independent
-** JPEG Group's djpeg on 2001.09.29.  The uncompressed output subroutines
-** are derived directly from the corresponding subroutines in djpeg's
-** wrgif.c source file.  Its copyright notice say:
-
- * Copyright (C) 1991-1997, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
-   The reference README file is README.JPEG in the Netpbm package.
-**
-** 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.
-**
-** The Graphics Interchange Format(c) is the Copyright property of
-** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
-** CompuServe Incorporated.
-*/
+/* This is a backward compatibility interface to Pamtogif.
+
+   Pamtogif replaced Ppmtogif in Netpbm 10.37 (December 2006).
+
+   The only significant ways Pamtogif are not backward compatible with
+   old Ppmtogif are:
 
-/* TODO: merge the LZW and uncompressed subroutines.  They are separate
-   only because they had two different lineages and the code is too
-   complicated for me quickly to rewrite it.
+     - Pamtogif does not have a -alpha option.
+
+     - Pamtogif requires a user-specififed map file (-mapfile) to
+       match the input in depth.
 */
+#define _BSD_SOURCE   /* Make sure strdup() is in string.h */
+#define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
+
 #include <assert.h>
 #include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
+#include "pm_c_util.h"
 #include "mallocvar.h"
 #include "shhopt.h"
-#include "ppm.h"
+#include "nstring.h"
+#include "pam.h"
 
-#define MAXCMAPSIZE 256
 
-static unsigned int const gifMaxval = 255;
 
-static bool verbose;
-/*
- * a code_int must be able to hold 2**BITS values of type int, and also -1
- */
-typedef int code_int;
+static const char *
+dirname(const char * const fileName) {
 
-typedef long int          count_int;
+    char * buffer;
+    char * slashPos;
 
+    buffer = strdup(fileName);
+
+    slashPos = strchr(buffer, '/');
+
+    if (slashPos)
+        *slashPos = '\0';
+
+    return buffer;
+}
 
-struct cmap {
-    /* This is the information for the GIF colormap (aka palette). */
 
-    int red[MAXCMAPSIZE], green[MAXCMAPSIZE], blue[MAXCMAPSIZE];
-        /* These arrays arrays map a color index, as is found in
-           the raster part of the GIF, to an intensity value for the indicated
-           RGB component.
-        */
-    int perm[MAXCMAPSIZE], permi[MAXCMAPSIZE];
-        /* perm[i] is the position in the sorted colormap of the color which
-           is at position i in the unsorted colormap.  permi[] is the inverse
-           function of perm[].
-        */
-    int cmapsize;
-        /* Number of entries in the GIF colormap.  I.e. number of colors
-           in the image, plus possibly one fake transparency color.
-        */
-    int transparent;
-        /* color index number in GIF palette of the color that is to be
-           transparent.  -1 if no color is transparent.
-        */
-    colorhash_table cht;
-        /* A hash table that relates a PPM pixel value to to a pre-sort
-           GIF colormap index.
-        */
-    pixval maxval;
-        /* The maxval for the colors in 'cht'. */
-};
 
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *input_filespec;  /* Filespec of input file */
-    const char *alpha_filespec;  /* Filespec of alpha file; NULL if none */
-    const char *alphacolor;      /* -alphacolor option value or default */
-    unsigned int interlace; /* -interlace option value */
-    unsigned int sort;     /* -sort option value */
+    const char *inputFileName;  /* Name of input file */
+    const char *alpha_filespec; /* Filespec of alpha file; NULL if none */
+    const char *alphacolor;     /* -alphacolor option value or default */
+    unsigned int interlace;     /* -interlace option value */
+    unsigned int sort;          /* -sort option value */
     const char *mapfile;        /* -mapfile option value.  NULL if none. */
     const char *transparent;    /* -transparent option value.  NULL if none. */
     const char *comment;        /* -comment option value; NULL if none */
-    unsigned int nolzw;    /* -nolzw option */
+    unsigned int nolzw;         /* -nolzw option */
     unsigned int verbose;
 };
 
@@ -122,8 +84,8 @@ handleLatex2htmlHack(void) {
   -Bryan 2001.11.14
 -----------------------------------------------------------------------------*/
      pm_error("latex2html, you should just try the -interlace and "
-             "-transparent options to see if they work instead of "
-             "expecting a 'usage' message from -h");
+              "-transparent options to see if they work instead of "
+              "expecting a 'usage' message from -h");
 }
 
 
@@ -191,12 +153,12 @@ parseCommandLine(int argc, char ** argv,
         handleLatex2htmlHack();
 
     if (argc-1 == 0) 
-        cmdlineP->input_filespec = "-";
+        cmdlineP->inputFileName = "-";
     else if (argc-1 != 1)
         pm_error("Program takes zero or one argument (filename).  You "
                  "specified %d", argc-1);
     else
-        cmdlineP->input_filespec = argv[1];
+        cmdlineP->inputFileName = argv[1];
 
     if (cmdlineP->alpha_filespec && cmdlineP->transparent)
         pm_error("You cannot specify both -alpha and -transparent.");
@@ -204,1362 +166,257 @@ parseCommandLine(int argc, char ** argv,
 
 
 
-/*
- * Write out a word to the GIF file
- */
 static void
-Putword(int const w, FILE * const fp) {
-
-    fputc( w & 0xff, fp );
-    fputc( (w / 256) & 0xff, fp );
-}
-
-
-static int
-closestcolor(pixel         const color,
-             pixval        const maxval,
-             struct cmap * const cmapP) {
+openPnmremapStream(const char * const inputFileName,
+                   const char * const mapFileName,
+                   bool         const verbose,
+                   FILE **      const pnmremapPipeP) {
 /*----------------------------------------------------------------------------
-   Return the pre-sort colormap index of the color in the colormap *cmapP
-   that is closest to the color 'color', whose maxval is 'maxval'.
-
-   Also add 'color' to the colormap hash, with the colormap index we
-   are returning.  Caller must ensure that the color is not already in
-   there.
+   Create a process to run the image in file inputFileName[] through
+   Pnmremap, remapping it to the colors in mapFileName[].  Have it
+   write its output to a pipe and return as *pnmremapPipeP the other
+   end of that pipe.
 -----------------------------------------------------------------------------*/
-    unsigned int i;
-    unsigned int imin, dmin;
-
-    pixval const r = PPM_GETR(color) * gifMaxval / maxval;
-    pixval const g = PPM_GETG(color) * gifMaxval / maxval;
-    pixval const b = PPM_GETB(color) * gifMaxval / maxval;
-
-    dmin = SQR(255) * 3;
-    imin = 0;
-    for (i=0;i < cmapP->cmapsize; i++) {
-        int const d = SQR(r-cmapP->red[i]) + 
-            SQR(g-cmapP->green[i]) + 
-            SQR(b-cmapP->blue[i]);
-        if (d < dmin) {
-            dmin = d;
-            imin = i; 
-        } 
-    }
-    ppm_addtocolorhash(cmapP->cht, &color, cmapP->permi[imin]);
-
-    return cmapP->permi[imin];
-}
-
+    FILE * pnmremapPipe;
+    const char * pnmremapCommand;
 
+    assert(inputFileName != NULL);
+    assert(mapFileName != NULL);
 
-enum pass {MULT8PLUS0, MULT8PLUS4, MULT4PLUS2, MULT2PLUS1};
-
-
-struct pixelCursor {
-    unsigned int width;
-        /* Width of the image, in columns */
-    unsigned int height;
-        /* Height of the image, in rows */
-    bool interlace;
-        /* We're accessing the image in interlace fashion */
-    unsigned int nPixelsLeft;
-        /* Number of pixels left to be read */
-    unsigned int curCol;
-        /* Location of pointed-to pixel, column */
-    unsigned int curRow;
-        /* Location of pointed-to pixel, row */
-    enum pass pass;
-        /* The interlace pass.  Undefined if !interlace */
-};
+    asprintfN(&pnmremapCommand, "pnmremap -mapfile='%s' %s",
+              mapFileName, inputFileName);
 
+    if (verbose)
+        pm_message("Preprocessing Pamtogif input with shell command '%s'",
+                   pnmremapCommand);
 
+    pnmremapPipe = popen(pnmremapCommand, "r");
 
-static struct pixelCursor pixelCursor;
-    /* Current location in the input pixels.  */
-
+    if (pnmremapPipe == NULL)
+        pm_error("Shell command '%s', via popen(), to prepare the input "
+                 "for Pamtogif, failed.", pnmremapCommand);
+    else
+        *pnmremapPipeP = pnmremapPipe;
 
-static void
-initPixelCursor(unsigned int const width,
-                unsigned int const height,
-                bool         const interlace) {
-
-    pixelCursor.width       = width;
-    pixelCursor.height      = height;
-    pixelCursor.interlace   = interlace;
-    pixelCursor.pass        = MULT8PLUS0;
-    pixelCursor.curCol      = 0;
-    pixelCursor.curRow      = 0;
-    pixelCursor.nPixelsLeft = width * height;
+    strfree(pnmremapCommand);
 }
 
 
 
-static void
-getPixel(pixel **           const pixels,
-         pixval             const inputMaxval,
-         gray **            const alpha,
-         gray               const alphaThreshold, 
-         struct cmap *      const cmapP,
-         struct pixelCursor const pixelCursor,
-         int *              const retvalP) {
-/*----------------------------------------------------------------------------
-   Return as *retvalP the colormap index of the pixel at location
-   pointed to by 'pixelCursor' in the PPM raster 'pixels', using
-   colormap *cmapP.
------------------------------------------------------------------------------*/
-    unsigned int const x = pixelCursor.curCol;
-    unsigned int const y = pixelCursor.curRow;
+static const char *
+pamtogifCommand(const char *       const arg0,
+                struct cmdlineInfo const cmdline) {
 
-    int colorindex;
+    const char * const pamtogifName = "pamtogif";
 
-    if (alpha && alpha[y][x] < alphaThreshold)
-        colorindex = cmapP->transparent;
-    else {
-        int presortColorindex;
+    const char * retval;
 
-        presortColorindex = ppm_lookupcolor(cmapP->cht, &pixels[y][x]);
-        if (presortColorindex == -1)
-            presortColorindex = 
-                closestcolor(pixels[y][x], inputMaxval, cmapP);
-        colorindex = cmapP->perm[presortColorindex];
-    }
-    *retvalP = colorindex;
-}
+    const char * commandVerb;
+    const char * transparentOpt;
+    const char * commentOpt;
 
+    if (strchr(arg0, '/')) {
+        const char * const arg0DirName = dirname(arg0);
+        const char * progName;
 
+        struct stat statbuf;
 
-static void
-bumpRowInterlace(struct pixelCursor * const pixelCursorP) {
-/*----------------------------------------------------------------------------
-   Move *pixelCursorP to the next row in the interlace pattern.
------------------------------------------------------------------------------*/
-    /* There are 4 passes:
-       MULT8PLUS0: Rows 8, 16, 24, 32, etc.
-       MULT8PLUS4: Rows 4, 12, 20, 28, etc.
-       MULT4PLUS2: Rows 2, 6, 10, 14, etc.
-       MULT2PLUS1: Rows 1, 3, 5, 7, 9, etc.
-    */
-    
-    switch (pixelCursorP->pass) {
-    case MULT8PLUS0:
-        pixelCursorP->curRow += 8;
-        break;
-    case MULT8PLUS4:
-        pixelCursorP->curRow += 8;
-        break;
-    case MULT4PLUS2:
-        pixelCursorP->curRow += 4;
-        break;
-    case MULT2PLUS1:
-        pixelCursorP->curRow += 2;
-        break;
-    }
-    /* Set the proper pass for the next read.  Note that if there are
-       more than 4 rows, the sequence of passes is sequential, but
-       when there are fewer than 4, we may skip e.g. from MULT8PLUS0
-       to MULT4PLUS2.
-    */
-    while (pixelCursorP->curRow >= pixelCursorP->height) {
-        switch (pixelCursorP->pass) {
-        case MULT8PLUS0:
-            pixelCursorP->pass = MULT8PLUS4;
-            pixelCursorP->curRow = 4;
-            break;
-        case MULT8PLUS4:
-            pixelCursorP->pass = MULT4PLUS2;
-            pixelCursorP->curRow = 2;
-            break;
-        case MULT4PLUS2:
-            pixelCursorP->pass = MULT2PLUS1;
-            pixelCursorP->curRow = 1;
-            break;
-        case MULT2PLUS1:
-            /* We've read the entire image; pass and current row are
-               now undefined.
-            */
-            pixelCursorP->curRow = 0;
-            break;
-        }
-    }
-}
+        asprintfN(&progName, "%s/%s", arg0DirName, pamtogifName);
 
-
-
-static void
-bumpPixel(struct pixelCursor * const pixelCursorP) {
-/*----------------------------------------------------------------------------
-   Bump *pixelCursorP to point to the next pixel to go into the GIF
-
-   Must not call when there are no pixels left.
------------------------------------------------------------------------------*/
-    assert(pixelCursorP->nPixelsLeft > 0);
-
-    /* Move one column to the right */
-    ++pixelCursorP->curCol;
-    
-    if (pixelCursorP->curCol >= pixelCursorP->width) {
-        /* That pushed us past the end of a row. */
-        /* Reset to the left edge ... */
-        pixelCursorP->curCol = 0;
-        
-        /* ... of the next row */
-        if (!pixelCursorP->interlace)
-            /* Go to the following row */
-            ++pixelCursorP->curRow;
+        if (stat(progName, &statbuf) == 0)
+            commandVerb = progName;
         else
-            bumpRowInterlace(pixelCursorP);
-    }
-    --pixelCursorP->nPixelsLeft;
-}
-
-
-
-static int
-gifNextPixel(pixel **      const pixels,
-             pixval        const inputMaxval,
-             gray **       const alpha,
-             gray          const alphaThreshold, 
-             struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   Return the pre-sort color index (index into the unsorted GIF color map)
-   of the next pixel to be processed from the input image.
-
-   'alpha_threshold' is the gray level such that a pixel in the alpha
-   map whose value is less that that represents a transparent pixel
-   in the output.
------------------------------------------------------------------------------*/
-    int retval;
-
-    if (pixelCursor.nPixelsLeft == 0 )
-        retval = EOF;
-    else {
-        getPixel(pixels, inputMaxval, alpha, alphaThreshold, cmapP, 
-                 pixelCursor, &retval);
-
-        bumpPixel(&pixelCursor);
-    }
-    return retval;
-}
-
-
-
-static void
-write_transparent_color_index_extension(FILE *fp, const int Transparent) {
-/*----------------------------------------------------------------------------
-   Write out extension for transparent color index.
------------------------------------------------------------------------------*/
-
-    fputc( '!', fp );
-    fputc( 0xf9, fp );
-    fputc( 4, fp );
-    fputc( 1, fp );
-    fputc( 0, fp );
-    fputc( 0, fp );
-    fputc( Transparent, fp );
-    fputc( 0, fp );
-}
-
-
-
-static void
-write_comment_extension(FILE *fp, const char comment[]) {
-/*----------------------------------------------------------------------------
-   Write out extension for a comment
------------------------------------------------------------------------------*/
-    char *segment;
-    
-    fputc('!', fp);   /* Identifies an extension */
-    fputc(0xfe, fp);  /* Identifies a comment */
-
-    /* Write it out in segments no longer than 255 characters */
-    for (segment = (char *) comment; 
-         segment < comment+strlen(comment); 
-         segment += 255) {
+            commandVerb = strdup(pamtogifName);
 
-        const int length_this_segment = MIN(255, strlen(segment));
+        strfree(arg0DirName);
+    } else
+        commandVerb = strdup(pamtogifName);
 
-        fputc(length_this_segment, fp);
-
-        fwrite(segment, 1, length_this_segment, fp);
-    }
-
-    fputc(0, fp);   /* No more comment blocks in this extension */
-}
-
-
-
-/***************************************************************************
- *
- *  GIFCOMPR.C       - GIF Image compression routines
- *
- *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
- *  David Rowley (mgardi@watdcsu.waterloo.edu)
- *
- ***************************************************************************/
-
-/*
- * General DEFINEs
- */
-
-#define BITS    12
-
-#define HSIZE  5003            /* 80% occupancy */
-
-#ifdef NO_UCHAR
- typedef char   char_type;
-#else /*NO_UCHAR*/
- typedef        unsigned char   char_type;
-#endif /*NO_UCHAR*/
-
-/*
- *
- * GIF Image compression - modified 'compress'
- *
- * Based on: compress.c - File compression ala IEEE Computer, June 1984.
- *
- * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
- *              Jim McKie               (decvax!mcvax!jim)
- *              Steve Davies            (decvax!vax135!petsd!peora!srd)
- *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
- *              James A. Woods          (decvax!ihnp4!ames!jaw)
- *              Joe Orost               (decvax!vax135!petsd!joe)
- *
- */
-#include <ctype.h>
-
-#define ARGVAL() (*++(*argv) || (--argc && *++argv))
-
-static code_int const maxmaxcode = (code_int)1 << BITS;
-    /* should NEVER generate this code */
-#define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
-
-static long htab [HSIZE];
-static unsigned short codetab [HSIZE];
-#define HashTabOf(i)       htab[i]
-#define CodeTabOf(i)    codetab[i]
-
-/*
- * To save much memory, we overlay the table used by compress() with those
- * used by decompress().  The tab_prefix table is the same size and type
- * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
- * get this from the beginning of htab.  The output stack uses the rest
- * of htab, and contains characters.  There is plenty of room for any
- * possible stack (stack used to be 8000 characters).
- */
-
-#define tab_prefixof(i) CodeTabOf(i)
-#define tab_suffixof(i)        ((char_type*)(htab))[i]
-#define de_stack               ((char_type*)&tab_suffixof((code_int)1<<BITS))
-
-static code_int free_ent = 0;                  /* first unused entry */
-
-/*
- * block compression parameters -- after all codes are used up,
- * and compression rate changes, start over.
- */
-static int clear_flg = 0;
-
-static int offset;
-static long int in_count = 1;            /* length of input */
-static long int out_count = 0;           /* # of codes output (for debugging) */
-
-/*
- * compress stdin to stdout
- *
- * Algorithm:  use open addressing double hashing (no chaining) on the
- * prefix code / next character combination.  We do a variant of Knuth's
- * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- * secondary probe.  Here, the modular division first probe is gives way
- * to a faster exclusive-or manipulation.  Also do block compression with
- * an adaptive reset, whereby the code table is cleared when the compression
- * ratio decreases, but after the table fills.  The variable-length output
- * codes are re-sized at this point, and a special CLEAR code is generated
- * for the decompressor.  Late addition:  construct the table according to
- * file size for noticeable speed improvement on small files.  Please direct
- * questions about this implementation to ames!jaw.
- */
-
-static int ClearCode;
-static int EOFCode;
-
-/***************************************************************************
-*                          BYTE OUTPUTTER                 
-***************************************************************************/
-
-typedef struct {
-    FILE * fileP;  /* The file to which to output */
-    unsigned int count;
-        /* Number of bytes so far in the current data block */
-    unsigned char buffer[256];
-        /* The current data block, under construction */
-} byteBuffer;
-
-
-
-static byteBuffer *
-byteBuffer_create(FILE * const fileP) {
-
-    byteBuffer * byteBufferP;
-
-    MALLOCVAR_NOFAIL(byteBufferP);
-
-    byteBufferP->fileP = fileP;
-    byteBufferP->count = 0;
-
-    return byteBufferP;
-}
-
-
-
-static void
-byteBuffer_destroy(byteBuffer * const byteBufferP) {
-
-    free(byteBufferP);
-}
-
-
-
-static void
-byteBuffer_flush(byteBuffer * const byteBufferP) {
-/*----------------------------------------------------------------------------
-   Write the current data block to the output file, then reset the current 
-   data block to empty.
------------------------------------------------------------------------------*/
-    if (byteBufferP->count > 0 ) {
-        if (verbose)
-            pm_message("Writing %u byte block", byteBufferP->count);
-        fputc(byteBufferP->count, byteBufferP->fileP);
-        fwrite(byteBufferP->buffer, 1, byteBufferP->count, byteBufferP->fileP);
-        byteBufferP->count = 0;
-    }
-}
-
-
-
-static void
-byteBuffer_flushFile(byteBuffer * const byteBufferP) {
-    
-    fflush(byteBufferP->fileP);
-    
-    if (ferror(byteBufferP->fileP))
-        pm_error("error writing output file");
-}
-
-
-
-static void
-byteBuffer_out(byteBuffer *  const byteBufferP,
-               unsigned char const c) {
-/*----------------------------------------------------------------------------
-  Add a byte to the end of the current data block, and if it is now 254
-  characters, flush the data block to the output file.
------------------------------------------------------------------------------*/
-    byteBufferP->buffer[byteBufferP->count++] = c;
-    if (byteBufferP->count >= 254)
-        byteBuffer_flush(byteBufferP);
-}
-
-
-
-struct gif_dest {
-    /* This structure controls output of uncompressed GIF raster */
-
-    byteBuffer * byteBufferP;  /* Where the full bytes go */
-
-    /* State for packing variable-width codes into a bitstream */
-    int n_bits;         /* current number of bits/code */
-    int maxcode;        /* maximum code, given n_bits */
-    int cur_accum;      /* holds bits not yet output */
-    int cur_bits;       /* # of bits in cur_accum */
-
-    /* State for GIF code assignment */
-    int ClearCode;      /* clear code (doesn't change) */
-    int EOFCode;        /* EOF code (ditto) */
-    int code_counter;   /* counts output symbols */
-};
-
-
-
-static unsigned long const masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
-                                       0x001F, 0x003F, 0x007F, 0x00FF,
-                                       0x01FF, 0x03FF, 0x07FF, 0x0FFF,
-                                       0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
-
-typedef struct {
-    byteBuffer * byteBufferP;
-    unsigned int initBits;
-    unsigned int n_bits;                        /* number of bits/code */
-    code_int maxcode;                  /* maximum code, given n_bits */
-    unsigned long curAccum;
-    int curBits;
-} codeBuffer;
-
-
-
-static codeBuffer *
-codeBuffer_create(FILE *       const ofP,
-                  unsigned int const initBits) {
-
-    codeBuffer * codeBufferP;
-
-    MALLOCVAR_NOFAIL(codeBufferP);
-
-    codeBufferP->initBits    = initBits;
-    codeBufferP->n_bits      = codeBufferP->initBits;
-    codeBufferP->maxcode     = MAXCODE(codeBufferP->n_bits);
-    codeBufferP->byteBufferP = byteBuffer_create(ofP);
-    codeBufferP->curAccum    = 0;
-    codeBufferP->curBits     = 0;
-
-    return codeBufferP;
-}
-
-
-
-static void
-codeBuffer_destroy(codeBuffer * const codeBufferP) {
-
-    byteBuffer_destroy(codeBufferP->byteBufferP);
-
-    free(codeBufferP);
-}
-
-
-
-static void
-codeBuffer_output(codeBuffer * const codeBufferP,
-                  code_int     const code) {
-/*----------------------------------------------------------------------------
-   Output one GIF code to the file, through the code buffer.
-
-   The code is represented as n_bits bits in the file -- the lower
-   n_bits bits of 'code'.
-
-   If the code is EOF, flush the code buffer to the file.
-
-   In some cases, change n_bits and recalculate maxcode to go with it.
------------------------------------------------------------------------------*/
-    /*
-      Algorithm:
-      Maintain a BITS character long buffer (so that 8 codes will
-      fit in it exactly).  Use the VAX insv instruction to insert each
-      code in turn.  When the buffer fills up empty it and start over.
-    */
-    
-    codeBufferP->curAccum &= masks[codeBufferP->curBits];
-
-    if (codeBufferP->curBits > 0)
-        codeBufferP->curAccum |= ((long)code << codeBufferP->curBits);
+    if (cmdline.transparent)
+        asprintfN(&transparentOpt, "-transparent=%s", cmdline.transparent);
     else
-        codeBufferP->curAccum = code;
-
-    codeBufferP->curBits += codeBufferP->n_bits;
+        transparentOpt = strdup("");
 
-    while (codeBufferP->curBits >= 8) {
-        byteBuffer_out(codeBufferP->byteBufferP,
-                       codeBufferP->curAccum & 0xff);
-        codeBufferP->curAccum >>= 8;
-        codeBufferP->curBits -= 8;
-    }
-
-    if (clear_flg) {
-        codeBufferP->n_bits = codeBufferP->initBits;
-        codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits);
-        clear_flg = 0;
-    } else if (free_ent > codeBufferP->maxcode) {
-        /* The next entry is going to be too big for the code size, so
-           increase it, if possible.
-        */
-        ++codeBufferP->n_bits;
-        if (codeBufferP->n_bits == BITS)
-            codeBufferP->maxcode = maxmaxcode;
-        else
-            codeBufferP->maxcode = MAXCODE(codeBufferP->n_bits);
-    }
+    if (cmdline.comment)
+        asprintfN(&commentOpt, "-comment=%s", cmdline.comment);
+    else
+        commentOpt = strdup("");
+
+    asprintfN(&retval, "%s - -alphacolor=%s %s %s %s %s %s %s",
+              commandVerb,
+              cmdline.alphacolor,
+              cmdline.interlace ? "-interlace" : "",
+              cmdline.sort ? "-sort" : "",
+              transparentOpt,
+              commentOpt,
+              cmdline.nolzw ? "-nolzw" : "",
+              cmdline.verbose ? "-verbose" : "");
     
-    if (code == EOFCode) {
-        /* We're at EOF.  Output the possible partial byte in the buffer */
-        if (codeBufferP->curBits > 0) {
-            byteBuffer_out(codeBufferP->byteBufferP,
-                           codeBufferP->curAccum & 0xff);
-            codeBufferP->curBits = 0;
-        }
-        byteBuffer_flush(codeBufferP->byteBufferP);
-        
-        byteBuffer_flushFile(codeBufferP->byteBufferP);
-    }
-}
-
+    strfree(transparentOpt);
+    strfree(commentOpt);
 
-
-static void
-cl_hash(long const hsize) {
-    /* reset code table */
-
-    long const m1 = -1;
-
-    long * htab_p;
-    long i;
-
-    htab_p = htab + hsize;  /* initial value */
-
-    i = hsize - 16;
-    do {                            /* might use Sys V memset(3) here */
-        *(htab_p-16) = m1;
-        *(htab_p-15) = m1;
-        *(htab_p-14) = m1;
-        *(htab_p-13) = m1;
-        *(htab_p-12) = m1;
-        *(htab_p-11) = m1;
-        *(htab_p-10) = m1;
-        *(htab_p-9) = m1;
-        *(htab_p-8) = m1;
-        *(htab_p-7) = m1;
-        *(htab_p-6) = m1;
-        *(htab_p-5) = m1;
-        *(htab_p-4) = m1;
-        *(htab_p-3) = m1;
-        *(htab_p-2) = m1;
-        *(htab_p-1) = m1;
-        htab_p -= 16;
-    } while ((i -= 16) >= 0);
-
-    for (i += 16; i > 0; --i)
-        *--htab_p = m1;
+    return retval;
 }
 
 
 
 static void
-cl_block(codeBuffer * const codeBufferP) {
-/*----------------------------------------------------------------------------
-  Clear out the hash table
------------------------------------------------------------------------------*/
-    cl_hash(HSIZE);
-    free_ent = ClearCode + 2;
-    clear_flg = 1;
+feedPamtogifNoAlpha(struct pam * const inPamP,
+                    FILE *       const pipeToPamtogif) {
     
-    codeBuffer_output(codeBufferP, (code_int)ClearCode);
-}
+    unsigned int row;
+    struct pam outPam;
+    tuple * tuplerow;
 
+    tuplerow = pnm_allocpamrow(inPamP);
 
-
-static void
-write_raster_LZW(pixel **      const pixels,
-                 pixval        const input_maxval,
-                 gray **       const alpha,
-                 gray          const alpha_maxval, 
-                 struct cmap * const cmapP, 
-                 int           const initBits,
-                 FILE *        const ofP) {
-/*----------------------------------------------------------------------------
-   Write the raster to file 'ofP'.
-
-   The raster to write is 'pixels', which has maxval 'input_maxval',
-   modified by alpha mask 'alpha', which has maxval 'alpha_maxval'.
-
-   Use the colormap 'cmapP' to generate the raster ('pixels' is 
-   composed of RGB samples; the GIF raster is colormap indices).
-
-   Write the raster using LZW compression.
------------------------------------------------------------------------------*/
-    gray const alpha_threshold = (alpha_maxval + 1) / 2;
-        /* gray levels below this in the alpha mask indicate transparent
-           pixels in the output image.
-        */
-    code_int ent;
-    code_int disp;
-    int hshift;
-    bool eof;
-    codeBuffer * codeBufferP;
-    
-    codeBufferP = codeBuffer_create(ofP, initBits);
+    outPam = *inPamP;
+    outPam.file = pipeToPamtogif;
     
-    /*
-     * Set up the necessary values
-     */
-    offset = 0;
-    out_count = 0;
-    clear_flg = 0;
-    in_count = 1;
-
-    ClearCode = (1 << (initBits - 1));
-    EOFCode = ClearCode + 1;
-    free_ent = ClearCode + 2;
-
-    ent = gifNextPixel(pixels, input_maxval, alpha, alpha_threshold, cmapP);
-
-    {
-        long fcode;
-        hshift = 0;
-        for (fcode = HSIZE; fcode < 65536L; fcode *= 2L)
-            ++hshift;
-        hshift = 8 - hshift;                /* set hash code range bound */
-    }
-    cl_hash(HSIZE);            /* clear hash table */
-
-    codeBuffer_output(codeBufferP, (code_int)ClearCode);
-
-    eof = FALSE;
-    while (!eof) {
-        int gifpixel;
-            /* The value for the pixel in the GIF image.  I.e. the colormap
-               index.  Or -1 to indicate "no more pixels."
-            */
-        gifpixel = gifNextPixel(pixels, 
-                                input_maxval, alpha, alpha_threshold, cmapP);
-        if (gifpixel == EOF) eof = TRUE;
-        if (!eof) {
-            long const fcode = (long) (((long) gifpixel << BITS) + ent);
-            code_int i;
-                /* xor hashing */
-
-            ++in_count;
-
-            i = (((code_int)gifpixel << hshift) ^ ent);    
-
-            if (HashTabOf (i) == fcode) {
-                ent = CodeTabOf (i);
-                continue;
-            } else if ((long)HashTabOf(i) < 0)      /* empty slot */
-                goto nomatch;
-            disp = HSIZE - i;        /* secondary hash (after G. Knott) */
-            if (i == 0)
-                disp = 1;
-        probe:
-            if ((i -= disp) < 0)
-                i += HSIZE;
-
-            if (HashTabOf(i) == fcode) {
-                ent = CodeTabOf(i);
-                continue;
-            }
-            if ((long)HashTabOf(i) > 0)
-                goto probe;
-        nomatch:
-            codeBuffer_output(codeBufferP, (code_int)ent);
-            ++out_count;
-            ent = gifpixel;
-            if (free_ent < maxmaxcode) {
-                CodeTabOf(i) = free_ent++; /* code -> hashtable */
-                HashTabOf(i) = fcode;
-            } else
-                cl_block(codeBufferP);
-        }
-    }
-    /* Put out the final code. */
-    codeBuffer_output(codeBufferP, (code_int)ent);
-    ++out_count;
-    codeBuffer_output(codeBufferP, (code_int) EOFCode);
-
-    codeBuffer_destroy(codeBufferP);
-}
-
+    pnm_writepaminit(&outPam);
 
+    for (row = 0; row < inPamP->height; ++row) {
+        pnm_readpamrow(inPamP, tuplerow);
 
-/* Routine to convert variable-width codes into a byte stream */
-
-static void
-outputUncompressed(struct gif_dest * const dinfoP,
-                   int               const code) {
-
-    /* Emit a code of n_bits bits */
-    /* Uses cur_accum and cur_bits to reblock into 8-bit bytes */
-    dinfoP->cur_accum |= ((int) code) << dinfoP->cur_bits;
-    dinfoP->cur_bits += dinfoP->n_bits;
-
-    while (dinfoP->cur_bits >= 8) {
-        byteBuffer_out(dinfoP->byteBufferP, dinfoP->cur_accum & 0xFF);
-        dinfoP->cur_accum >>= 8;
-        dinfoP->cur_bits -= 8;
-    }
-}
-
-
-static void
-writeRasterUncompressedInit(FILE *            const ofP,
-                            struct gif_dest * const dinfoP, 
-                            int               const i_bits) {
-/*----------------------------------------------------------------------------
-   Initialize pseudo-compressor
------------------------------------------------------------------------------*/
-
-    /* init all the state variables */
-    dinfoP->n_bits = i_bits;
-    dinfoP->maxcode = MAXCODE(dinfoP->n_bits);
-    dinfoP->ClearCode = (1 << (i_bits - 1));
-    dinfoP->EOFCode = dinfoP->ClearCode + 1;
-    dinfoP->code_counter = dinfoP->ClearCode + 2;
-    /* init output buffering vars */
-    dinfoP->byteBufferP = byteBuffer_create(ofP);
-    dinfoP->cur_accum = 0;
-    dinfoP->cur_bits = 0;
-    /* GIF specifies an initial Clear code */
-    outputUncompressed(dinfoP, dinfoP->ClearCode);
-}
-
-
-
-static void
-writeRasterUncompressedPixel(struct gif_dest * const dinfoP, 
-                             unsigned int      const colormapIndex) {
-/*----------------------------------------------------------------------------
-   "Compress" one pixel value and output it as a symbol.
-
-   'colormapIndex' must be less than dinfoP->n_bits wide.
------------------------------------------------------------------------------*/
-    assert(colormapIndex >> dinfoP->n_bits == 0);
-
-    outputUncompressed(dinfoP, colormapIndex);
-    /* Issue Clear codes often enough to keep the reader from ratcheting up
-     * its symbol size.
-     */
-    if (dinfoP->code_counter < dinfoP->maxcode) {
-        ++dinfoP->code_counter;
-    } else {
-        outputUncompressed(dinfoP, dinfoP->ClearCode);
-        dinfoP->code_counter = dinfoP->ClearCode + 2;	/* reset the counter */
+        pnm_writepamrow(&outPam, tuplerow);
     }
+    pnm_freepamrow(tuplerow);
 }
 
 
 
 static void
-writeRasterUncompressedTerm(struct gif_dest * const dinfoP) {
-
-    outputUncompressed(dinfoP, dinfoP->EOFCode);
-
-    if (dinfoP->cur_bits > 0)
-        byteBuffer_out(dinfoP->byteBufferP, dinfoP->cur_accum & 0xFF);
-
-    byteBuffer_flush(dinfoP->byteBufferP);
-
-    byteBuffer_destroy(dinfoP->byteBufferP);
-}
-
-
-
-static void
-writeRasterUncompressed(FILE *         const ofP, 
-                        pixel **       const pixels,
-                        pixval         const inputMaxval,
-                        gray **        const alpha,
-                        gray           const alphaMaxval, 
-                        struct cmap *  const cmapP, 
-                        int            const initBits) {
-/*----------------------------------------------------------------------------
-   Write the raster to file 'ofP'.
-   
-   Same as write_raster_LZW(), except written out one code per
-   pixel (plus some clear codes), so no compression.  And no use
-   of the LZW patent.
------------------------------------------------------------------------------*/
-    gray const alphaThreshold = (alphaMaxval + 1) / 2;
-        /* gray levels below this in the alpha mask indicate transparent
-           pixels in the output image.
-        */
-    bool eof;
-
-    struct gif_dest gifDest;
-
-    writeRasterUncompressedInit(ofP, &gifDest, initBits);
-
-    eof = FALSE;
-    while (!eof) {
-        int gifpixel;
-            /* The value for the pixel in the GIF image.  I.e. the colormap
-               index.  Or -1 to indicate "no more pixels."
-            */
-        gifpixel = gifNextPixel(pixels, 
-                                inputMaxval, alpha, alphaThreshold, cmapP);
-        if (gifpixel == EOF)
-            eof = TRUE;
-        else
-            writeRasterUncompressedPixel(&gifDest, gifpixel);
-    }
-    writeRasterUncompressedTerm(&gifDest);
-}
-
-
-
-/******************************************************************************
- *
- * GIF Specific routines
- *
- *****************************************************************************/
-
-static void
-writeGifHeader(FILE * const fp,
-               int const Width, int const Height, 
-               int const GInterlace, int const Background, 
-               int const BitsPerPixel, struct cmap * const cmapP,
-               const char comment[]) {
-
-    int B;
-    int const Resolution = BitsPerPixel;
-    int const ColorMapSize = 1 << BitsPerPixel;
-
-    /* Write the Magic header */
-    if (cmapP->transparent != -1 || comment)
-        fwrite("GIF89a", 1, 6, fp);
-    else
-        fwrite("GIF87a", 1, 6, fp);
-
-    /* Write out the screen width and height */
-    Putword( Width, fp );
-    Putword( Height, fp );
-
-    /* Indicate that there is a global color map */
-    B = 0x80;       /* Yes, there is a color map */
-
-    /* OR in the resolution */
-    B |= (Resolution - 1) << 4;
-
-    /* OR in the Bits per Pixel */
-    B |= (BitsPerPixel - 1);
-
-    /* Write it out */
-    fputc( B, fp );
-
-    /* Write out the Background color */
-    fputc( Background, fp );
-
-    /* Byte of 0's (future expansion) */
-    fputc( 0, fp );
-
-    {
-        /* Write out the Global Color Map */
-        /* Note that the Global Color Map is always a power of two colors
-           in size, but *cmapP could be smaller than that.  So we pad with
-           black.
-        */
-        int i;
-        for ( i=0; i < ColorMapSize; ++i ) {
-            if ( i < cmapP->cmapsize ) {
-                fputc( cmapP->red[i], fp );
-                fputc( cmapP->green[i], fp );
-                fputc( cmapP->blue[i], fp );
-            } else {
-                fputc( 0, fp );
-                fputc( 0, fp );
-                fputc( 0, fp );
-            }
+copyRasterWithAlpha(struct pam * const inPamP,
+                    struct pam * const alphaPamP,
+                    struct pam * const outPamP,
+                    unsigned int const alphaPlane) {
+
+    tuple * tuplerow;
+    tuple * alpharow;
+    unsigned int row;
+
+    inPamP->allocation_depth = outPamP->depth;
+
+    tuplerow = pnm_allocpamrow(inPamP);
+    alpharow = pnm_allocpamrow(alphaPamP);
+
+    for (row = 0; row < inPamP->height; ++row) {
+        unsigned int col;
+            
+        pnm_readpamrow(inPamP, tuplerow);
+        pnm_readpamrow(alphaPamP, alpharow);
+
+        for (col = 0; col < inPamP->width; ++col) {
+            tuplerow[col][alphaPlane] = pnm_scalesample(alpharow[col][0],
+                                                        alphaPamP->maxval,
+                                                        inPamP->maxval);
         }
+        pnm_writepamrow(outPamP, tuplerow);
     }
-        
-    if ( cmapP->transparent >= 0 ) 
-        write_transparent_color_index_extension(fp, cmapP->transparent);
-
-    if ( comment )
-        write_comment_extension(fp, comment);
-}
-
-
-
-static void
-writeImageHeader(FILE *       const ofP,
-                 unsigned int const leftOffset,
-                 unsigned int const topOffset,
-                 unsigned int const gWidth,
-                 unsigned int const gHeight,
-                 unsigned int const gInterlace,
-                 unsigned int const initCodeSize) {
-
-    Putword(leftOffset, ofP);
-    Putword(topOffset,  ofP);
-    Putword(gWidth,     ofP);
-    Putword(gHeight,    ofP);
-
-    /* Write out whether or not the image is interlaced */
-    if (gInterlace)
-        fputc(0x40, ofP);
-    else
-        fputc(0x00, ofP);
-
-    /* Write out the initial code size */
-    fputc(initCodeSize, ofP);
-}
-
-
-
-static void
-gifEncode(FILE *        const ofP, 
-          pixel **      const pixels,
-          pixval        const inputMaxval,
-          int           const gWidth,
-          int           const gHeight, 
-          gray **       const alpha,
-          gray          const alphaMaxval,
-          int           const gInterlace,
-          int           const background, 
-          int           const bitsPerPixel,
-          struct cmap * const cmapP,
-          char          const comment[],
-          bool          const nolzw) {
-
-    unsigned int const leftOffset = 0;
-    unsigned int const topOffset  = 0;
-
-    unsigned int const initCodeSize = bitsPerPixel <= 1 ? 2 : bitsPerPixel;
-        /* The initial code size */
-
-    if (gWidth > 65535)
-        pm_error("Image width %u too large for GIF format.  (Max 65535)",
-                 gWidth);  
-    
-    if (gHeight > 65535)
-        pm_error("Image height %u too large for GIF format.  (Max 65535)",
-                 gHeight);  
-
-    writeGifHeader(ofP, gWidth, gHeight, gInterlace, background,
-                   bitsPerPixel, cmapP, comment);
-
-    /* Write an Image separator */
-    fputc(',', ofP);
-
-    writeImageHeader(ofP, leftOffset, topOffset, gWidth, gHeight, gInterlace,
-                     initCodeSize);
-
-    initPixelCursor(gWidth, gHeight, gInterlace);
-
-    /* Write the actual raster */
-    if (nolzw)
-        writeRasterUncompressed(ofP, pixels, 
-                                inputMaxval, alpha, alphaMaxval, cmapP, 
-                                initCodeSize + 1);
-    else
-        write_raster_LZW(pixels, 
-                         inputMaxval, alpha, alphaMaxval, cmapP, 
-                         initCodeSize + 1, ofP);
-
-    /* Write out a zero length data block (to end the series) */
-    fputc(0, ofP);
-
-    /* Write the GIF file terminator */
-    fputc(';', ofP);
-}
-
-
-
-static int
-compute_transparent(const char colorarg[], 
-                    struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   Figure out the color index (index into the colormap) of the color
-   that is to be transparent in the GIF.
-
-   colorarg[] is the string that specifies the color the user wants to
-   be transparent (e.g. "red", "#fefefe").  Its maxval is the maxval
-   of the colormap.  'cmap' is the full colormap except that its
-   'transparent' component isn't valid.
-
-   colorarg[] is a standard Netpbm color specification, except that
-   may have a "=" prefix, which means it specifies a particular exact
-   color, as opposed to without the "=", which means "the color that
-   is closest to this and actually in the image."
-
-   Return -1 if colorarg[] specifies an exact color and that color is not
-   in the image.  Also issue an informational message.
------------------------------------------------------------------------------*/
-    int retval;
-
-    const char *colorspec;
-    bool exact;
-    int presort_colorindex;
-    pixel transcolor;
-
-    if (colorarg[0] == '=') {
-        colorspec = &colorarg[1];
-        exact = TRUE;
-    } else {
-        colorspec = colorarg;
-        exact = FALSE;
-    }
-        
-    transcolor = ppm_parsecolor((char*)colorspec, cmapP->maxval);
-    presort_colorindex = ppm_lookupcolor(cmapP->cht, &transcolor);
-    
-    if (presort_colorindex != -1)
-        retval = cmapP->perm[presort_colorindex];
-    else if (!exact)
-        retval = cmapP->perm[closestcolor(transcolor, cmapP->maxval, cmapP)];
-    else {
-        retval = -1;
-        pm_message(
-            "Warning: specified transparent color does not occur in image.");
-    }
-    return retval;
+    pnm_freepamrow(alpharow);
+    pnm_freepamrow(tuplerow);
 }
 
 
 
 static void
-sort_colormap(int const sort, struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   Sort (in place) the colormap *cmapP.
-
-   Create the perm[] and permi[] mappings for the colormap.
-
-   'sort' is logical:  true means to sort the colormap by red intensity,
-   then by green intensity, then by blue intensity.  False means a null
-   sort -- leave it in the same order in which we found it.
------------------------------------------------------------------------------*/
-    int * const Red = cmapP->red;
-    int * const Blue = cmapP->blue;
-    int * const Green = cmapP->green;
-    int * const perm = cmapP->perm;
-    int * const permi = cmapP->permi;
-    unsigned int const cmapsize = cmapP->cmapsize;
-    
-    int i;
-
-    for (i=0; i < cmapsize; i++)
-        permi[i] = i;
-
-    if (sort) {
-        pm_message("sorting colormap");
-        for (i=0; i < cmapsize; i++) {
-            int j;
-            for (j=i+1; j < cmapsize; j++)
-                if (((Red[i]*MAXCMAPSIZE)+Green[i])*MAXCMAPSIZE+Blue[i] >
-                    ((Red[j]*MAXCMAPSIZE)+Green[j])*MAXCMAPSIZE+Blue[j]) {
-                    int tmp;
-                    
-                    tmp=permi[i]; permi[i]=permi[j]; permi[j]=tmp;
-                    tmp=Red[i]; Red[i]=Red[j]; Red[j]=tmp;
-                    tmp=Green[i]; Green[i]=Green[j]; Green[j]=tmp;
-                    tmp=Blue[i]; Blue[i]=Blue[j]; Blue[j]=tmp; } }
+feedPamtogifWithAlpha(struct pam * const inPamP,
+                      struct pam * const alphaPamP,
+                      FILE *       const pipeToPamtogif) {
+
+    unsigned int alphaPlane;
+    struct pam outPam;
+
+    if (inPamP->width != alphaPamP->width ||
+        inPamP->height != alphaPamP->height)
+        pm_error("-alpha image dimensions (%u w x %u h) do not match "
+                 "the input image dimensions (%u x %u)",
+                 alphaPamP->width, alphaPamP->height,
+                 inPamP->width, inPamP->height);
+
+    outPam = *inPamP;
+    outPam.file        = pipeToPamtogif;
+    outPam.format      = PAM_FORMAT;
+    outPam.plainformat = 0;
+
+    if (inPamP->depth == 1) {
+        alphaPlane = 1;
+        strcpy(outPam.tuple_type, "GRAYSCALE_ALPHA");
+    } else if (inPamP->depth == 3) {
+        alphaPlane = 3;
+        strcpy(outPam.tuple_type, "RGB_ALPHA");
     }
+    outPam.depth = alphaPlane + 1;
 
-    for (i=0; i < cmapsize; i++)
-        perm[permi[i]] = i;
-}
+    pnm_writepaminit(&outPam);
 
-
-
-static void
-normalize_to_255(colorhist_vector const chv, struct cmap * const cmapP) {
-/*----------------------------------------------------------------------------
-   With a PPM color histogram vector 'chv' as input, produce a colormap
-   of integers 0-255 as output in *cmapP.
------------------------------------------------------------------------------*/
-    int i;
-    pixval const maxval = cmapP->maxval;
-
-    if ( maxval != 255 )
-        pm_message(
-            "maxval is not 255 - automatically rescaling colors" );
-
-    for ( i = 0; i < cmapP->cmapsize; ++i ) {
-        if ( maxval == 255 ) {
-            cmapP->red[i] = (int) PPM_GETR( chv[i].color );
-            cmapP->green[i] = (int) PPM_GETG( chv[i].color );
-            cmapP->blue[i] = (int) PPM_GETB( chv[i].color );
-        } else {
-            cmapP->red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval;
-            cmapP->green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval;
-            cmapP->blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval;
-        }
-    }
-}
-
-
-
-static void add_to_colormap(struct cmap * const cmapP, 
-                            const char *  const colorspec, 
-                            int *         const new_indexP) {
-/*----------------------------------------------------------------------------
-  Add a new entry to the colormap.  Make the color that specified by
-  'colorspec', and return the index of the new entry as *new_indexP.
-
-  'colorspec' is a color specification given by the user, e.g.
-  "red" or "rgb:ff/03.0d".  The maxval for this color specification is
-  that for the colormap *cmapP.
------------------------------------------------------------------------------*/
-    pixel const transcolor = ppm_parsecolor((char*)colorspec, cmapP->maxval);
-    
-    *new_indexP = cmapP->cmapsize++; 
-
-    cmapP->red[*new_indexP] = PPM_GETR(transcolor);
-    cmapP->green[*new_indexP] = PPM_GETG(transcolor); 
-    cmapP->blue[*new_indexP] = PPM_GETB(transcolor); 
+    copyRasterWithAlpha(inPamP, alphaPamP, &outPam, alphaPlane);
 }
 
 
 
 static void
-colormap_from_file(const char filespec[], unsigned int const maxcolors,
-                   colorhist_vector * const chvP, pixval * const maxvalP,
-                   int * const colorsP) {
-/*----------------------------------------------------------------------------
-   Read a colormap from the PPM file filespec[].  Return the color histogram
-   vector (which is practically a colormap) of the input image as *cvhP
-   and the maxval for that histogram as *maxvalP.
------------------------------------------------------------------------------*/
-    FILE *mapfile;
-    int cols, rows;
-    pixel ** colormap_ppm;
-
-    mapfile = pm_openr(filespec);
-    colormap_ppm = ppm_readppm(mapfile, &cols, &rows, maxvalP);
-    pm_close(mapfile);
+feedPamtogif(struct pam * const inPamP,
+             const char * const alphaFilespec,
+             FILE *       const pipeToPamtogif) {
     
-    /* Figure out the colormap from the <mapfile>. */
-    pm_message("computing other colormap...");
-    *chvP = 
-        ppm_computecolorhist(colormap_ppm, cols, rows, maxcolors, colorsP);
-    
-    ppm_freearray(colormap_ppm, rows); 
-}
-
-
-
-static void
-get_alpha(const char * const alpha_filespec, int const cols, int const rows,
-          gray *** const alphaP, gray * const maxvalP) {
-
-    if (alpha_filespec) {
-        int alpha_cols, alpha_rows;
-        *alphaP = pgm_readpgm(pm_openr(alpha_filespec),
-                              &alpha_cols, &alpha_rows, maxvalP);
-        if (alpha_cols != cols || alpha_rows != rows)
-            pm_error("alpha mask is not the same dimensions as the "
-                     "input file (alpha is %dW x %dH; image is %dW x %dH)",
-                     alpha_cols, alpha_rows, cols, rows);
-    } else 
-        *alphaP = NULL;
-}
-
-
-
-static void
-compute_ppm_colormap(pixel ** const pixels, int const cols, int const rows,
-                     int const input_maxval, bool const have_alpha, 
-                     const char * const mapfile, colorhist_vector * const chvP,
-                     colorhash_table * const chtP,
-                     pixval * const colormap_maxvalP, 
-                     int * const colorsP) {
-/*----------------------------------------------------------------------------
-   Compute a colormap, PPM style, for the image 'pixels', which is
-   'cols' by 'rows' with maxval 'input_maxval'.  If 'mapfile' is
-   non-null, Use the colors in that (PPM) file for the color map
-   instead of the colors in 'pixels'.
-
-   Return the colormap as *chvP and *chtP.  Return the maxval for that
-   colormap as *colormap_maxvalP.
-
-   While we're at it, count the colors and validate that there aren't
-   too many.  Return the count as *colorsP.  In determining if there are
-   too many, allow one slot for a fake transparency color if 'have_alpha'
-   is true.  If there are too many, issue an error message and abort the
-   program.
------------------------------------------------------------------------------*/
-    unsigned int maxcolors;
-        /* The most colors we can tolerate in the image.  If we have
-           our own made-up entry in the colormap for transparency, it
-           isn't included in this count.
-        */
-
-    if (have_alpha)
-        maxcolors = MAXCMAPSIZE - 1;
-    else
-        maxcolors = MAXCMAPSIZE;
-
-    if (mapfile) {
-        /* Read the colormap from a separate colormap file. */
-        colormap_from_file(mapfile, maxcolors, chvP, colormap_maxvalP, 
-                           colorsP);
-    } else {
-        /* Figure out the color map from the input file */
-        pm_message("computing colormap...");
-        *chvP = ppm_computecolorhist(pixels, cols, rows, maxcolors, colorsP); 
-        *colormap_maxvalP = input_maxval;
-    }
-
-    if (*chvP == NULL)
-        pm_error("too many colors - try doing a 'pnmquant %d'", maxcolors);
-    pm_message("%d colors found", *colorsP);
-
-    /* And make a hash table for fast lookup. */
-    *chtP = ppm_colorhisttocolorhash(*chvP, *colorsP);
+    if (alphaFilespec) {
+        FILE * afP;
+        struct pam alphaPam;
+        afP = pm_openr(alphaFilespec);
+        pnm_readpaminit(afP, &alphaPam, PAM_STRUCT_SIZE(tuple_type));
+        feedPamtogifWithAlpha(inPamP, &alphaPam, pipeToPamtogif);
+        pm_close(afP);
+    } else
+        feedPamtogifNoAlpha(inPamP, pipeToPamtogif);
 }
 
 
 
 int
-main(int argc, char *argv[]) {
+main(int    argc,
+     char * argv[]) {
+
     struct cmdlineInfo cmdline;
     FILE * ifP;
-    int rows, cols;
-    int BitsPerPixel;
-    pixel ** pixels;   /* The input image, in PPM format */
-    pixval input_maxval;  /* Maxval for 'pixels' */
-    gray ** alpha;     /* The supplied alpha mask; NULL if none */
-    gray alpha_maxval; /* Maxval for 'alpha' */
-
-    struct cmap cmap;
-        /* The colormap, with all its accessories */
-    colorhist_vector chv;
-    int fake_transparent;
-        /* colormap index of the fake transparency color we're using to
-           implement the alpha mask.  Undefined if we're not doing an alpha
-           mask.
-        */
+    struct pam inPam;
+    const char * command;
+    FILE * pipeToPamtogif;
+    int rc;
 
-    ppm_init( &argc, argv );
+    pnm_init(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
-    verbose = cmdline.verbose;
-
-    ifP = pm_openr(cmdline.input_filespec);
-
-    pixels = ppm_readppm(ifP, &cols, &rows, &input_maxval);
-
-    pm_close(ifP);
+    if (cmdline.mapfile)
+        openPnmremapStream(cmdline.inputFileName, cmdline.mapfile,
+                           cmdline.verbose, &ifP);
+    else
+        ifP = pm_openr(cmdline.inputFileName);
+        
+    command = pamtogifCommand(argv[0], cmdline);
 
-    get_alpha(cmdline.alpha_filespec, cols, rows, &alpha, &alpha_maxval);
+    if (cmdline.verbose)
+        pm_message("Executing shell command '%s'", command);
+    
+    pipeToPamtogif = popen(command, "w");
 
-    compute_ppm_colormap(pixels, cols, rows, input_maxval, (alpha != NULL), 
-                         cmdline.mapfile, 
-                         &chv, &cmap.cht, &cmap.maxval, &cmap.cmapsize);
+    if (pipeToPamtogif == NULL)
+        pm_error("Shell command '%s', via popen(), failed.", command);
 
-    /* Now turn the ppm colormap into the appropriate GIF colormap. */
+    pnm_readpaminit(ifP, &inPam, PAM_STRUCT_SIZE(allocation_depth));
 
-    normalize_to_255(chv, &cmap);
+    feedPamtogif(&inPam, cmdline.alpha_filespec, pipeToPamtogif);
 
-    ppm_freecolorhist(chv);
+    rc = pclose(pipeToPamtogif);
 
-    if (alpha) {
-        /* Add a fake entry to the end of the colormap for transparency.  
-           Make its color black. 
-        */
-        add_to_colormap(&cmap, cmdline.alphacolor, &fake_transparent);
-    }
-    sort_colormap(cmdline.sort, &cmap);
-
-    BitsPerPixel = pm_maxvaltobits(cmap.cmapsize-1);
-
-    if (alpha) {
-        cmap.transparent = cmap.perm[fake_transparent];
-    } else {
-        if (cmdline.transparent)
-            cmap.transparent = 
-                compute_transparent(cmdline.transparent, &cmap);
-        else 
-            cmap.transparent = -1;
-    }
-    /* All set, let's do it. */
-    gifEncode(stdout, pixels, input_maxval, cols, rows, 
-              alpha, alpha_maxval, 
-              cmdline.interlace, 0, BitsPerPixel, &cmap, cmdline.comment,
-              cmdline.nolzw);
+    if (rc != 0)
+        pm_error("Pamtogif process failed.  pclose() failed.");
 
-    ppm_freearray(pixels, rows);
-    if (alpha)
-        pgm_freearray(alpha, rows);
+    strfree(command);
 
-    fclose(stdout);
+    pm_close(ifP);
+    pm_close(stdout);
 
     return 0;
 }
diff --git a/converter/ppm/ppmtoilbm.c b/converter/ppm/ppmtoilbm.c
index fcc6053f..d296f498 100644
--- a/converter/ppm/ppmtoilbm.c
+++ b/converter/ppm/ppmtoilbm.c
@@ -439,14 +439,14 @@ compute_ham_cmap(cols, rows, maxval, maxcolors, colorsP, hbits)
                     tmp = hmap[i].b - b; dist += tmp * tmp;
 
                     if( dist <= maxdist ) {
-                        int sum = hmap[i].count + hmap[col].count;
-
-                        hmap[i].r = (hmap[i].r * hmap[i].count + 
-                                     r * hmap[col].count + sum/2)/sum;
-                        hmap[i].g = (hmap[i].g * hmap[i].count + 
-                                     g * hmap[col].count + sum/2)/sum;
-                        hmap[i].b = (hmap[i].b * hmap[i].count + 
-                                     b * hmap[col].count + sum/2)/sum;
+                        unsigned int sum = hmap[i].count + hmap[col].count;
+
+                        hmap[i].r = ROUNDDIV(hmap[i].r * hmap[i].count + 
+                                             r * hmap[col].count, sum);
+                        hmap[i].g = ROUNDDIV(hmap[i].g * hmap[i].count + 
+                                             g * hmap[col].count, sum);
+                        hmap[i].b = ROUNDDIV(hmap[i].b * hmap[i].count + 
+                                             b * hmap[col].count, sum);
                         hmap[i].count = sum;
 
                         hmap[col] = hmap[i];    /* temp store */
@@ -641,20 +641,9 @@ ppm_to_ham(fp, cols, rows, maxval, colormap, colors, cmapmaxval, hamplanes)
 
 
 static long
-#ifdef __STDC__
 do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows,
             pixval maxval, pixval hammaxval, int nPlanes,
             pixel *colormap, int colors)
-#else
-do_ham_body(ifP, ofp, cols, rows, maxval, hammaxval, nPlanes, colormap, colors)
-    FILE *ifP, *ofp;
-    int cols, rows;
-    pixval maxval;      /* maxval of image color components */
-    pixval hammaxval;   /* maxval of HAM color changes */
-    int nPlanes;
-    pixel *colormap;
-    int colors;
-#endif
 {
     register int col, row, i;
     rawtype *raw_rowbuf;
@@ -882,16 +871,8 @@ ppm_to_deep(fp, cols, rows, maxval, bitspercolor)
 
 
 static long
-#if __STDC__
 do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, 
              int bitspercolor)
-#else
-do_deep_body(ifP, ofp, cols, rows, maxval, bitspercolor)
-    FILE *ifP, *ofp;
-    int cols, rows;
-    pixval maxval;
-    int bitspercolor;
-#endif
 {
     register int row, col;
     pixel *pP;
@@ -1020,16 +1001,8 @@ ppm_to_dcol(fp, cols, rows, maxval, dcol)
 
 
 static long
-#if __STDC__
 do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, 
              DirectColor *dcol)
-#else
-do_dcol_body(ifP, ofp, cols, rows, maxval, dcol)
-    FILE *ifP, *ofp;
-    int cols, rows;
-    pixval maxval;
-    DirectColor *dcol;
-#endif
 {
     register int row, col;
     pixel *pP;
@@ -1167,18 +1140,8 @@ ppm_to_std(fp, cols, rows, maxval, colormap, colors, cmapmaxval,
 
 
 static long
-#if __STDC__
 do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
             pixel *colormap, int colors, int nPlanes)
-#else
-do_std_body(ifP, ofp, cols, rows, maxval, colormap, colors, nPlanes)
-    FILE *ifP, *ofp;
-    int cols, rows;
-    pixval maxval;
-    pixel *colormap;
-    int colors;
-    int nPlanes;
-#endif
 {
     register int row, col, i;
     pixel *pP;
@@ -1789,12 +1752,7 @@ runbyte1(size)
 /************ other utility functions ************/
 
 static void
-#if __STDC__
 put_big_short(short s)
-#else
-put_big_short(s)
-    short s;
-#endif
 {
     if ( pm_writebigshort( stdout, s ) == -1 )
         pm_error( "write error" );
@@ -1824,12 +1782,12 @@ static int *
 make_val_table(oldmaxval, newmaxval)
     int oldmaxval, newmaxval;
 {
-    int i;
-    int *table;
+    unsigned int i;
+    int * table;
 
     MALLOCARRAY_NOFAIL(table, oldmaxval + 1);
-    for(i = 0; i <= oldmaxval; i++ )
-        table[i] = (i * newmaxval + oldmaxval/2) / oldmaxval;
+    for (i = 0; i <= oldmaxval; ++i)
+        table[i] = ROUNDDIV(i * newmaxval, oldmaxval);
 
     return table;
 }
diff --git a/converter/ppm/ppmtoleaf.c b/converter/ppm/ppmtoleaf.c
index fa5fdaf5..dcff0985 100644
--- a/converter/ppm/ppmtoleaf.c
+++ b/converter/ppm/ppmtoleaf.c
@@ -1,4 +1,4 @@
-/* ppmtoleaf.c - read a portable pixmap and produce a ileaf img file
+/* ppmtoleaf.c - read a PPM and produce a ileaf img file
  *
  * Copyright (C) 1994 by Bill O'Donnell.
  *
@@ -15,57 +15,60 @@
  */
 
 #include <stdio.h>
+
 #include "ppm.h"
 
 #define MAXCOLORS 256
 
-pixel **pixels;
+pixel ** pixels;
 colorhash_table cht;
 
-int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
+static int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
 
 
 
 static int
-colorstobpp( colors )
-int colors;
-{
+colorstobpp(unsigned int const colors) {
+
     int bpp;
     
-    if ( colors <= 2 )
-	bpp = 1;
-    else if ( colors <= 256 )
-	bpp = 8;
+    if (colors <= 2)
+        bpp = 1;
+    else if (colors <= 256)
+        bpp = 8;
     else
-	bpp = 24;
+        bpp = 24;
+
     return bpp;
 }
 
 
 
 static int
-GetPixel( x, y )
-int x, y;
-{
+GetPixel(int const x,
+         int const y) {
+
     int color;
     
-    color = ppm_lookupcolor( cht, &pixels[y][x] );
+    color = ppm_lookupcolor(cht, &pixels[y][x]);
+    
     return color;
 }
 
 
 
-/* OK, this routine is not wicked efficient, but it is simple to follow
-   and it works. */
+
 static void
-leaf_writeimg(width, height, depth, ncolors, maxval)
-int width;
-int height;
-int depth;
-int ncolors;
-{
-    int i,row,col;
-    
+leaf_writeimg(unsigned int const width,
+              unsigned int const height,
+              unsigned int const depth,
+              unsigned int const ncolors,
+              pixval       const maxval) {
+
+    /* OK, this routine is not wicked efficient, but it is simple to follow
+       and it works.
+    */
+
     /* NOTE: byte order in ileaf img file fmt is big-endian, always! */
     
     /* magic */
@@ -115,136 +118,142 @@ int ncolors;
     
     /* format, mono/gray = 0x20000000, RGB=0x29000000 */
     if (depth == 1)
-	fputc(0x20, stdout);
+        fputc(0x20, stdout);
     else
-	fputc(0x29, stdout);
+        fputc(0x29, stdout);
+
     fputc(0x00, stdout);
     fputc(0x00, stdout);
     fputc(0x00, stdout);
     
     /* colormap size */
-    if (depth == 8)
-    {
-	fputc((unsigned char)((ncolors >> 8) & 0x00ff), stdout);
-	fputc((unsigned char)(ncolors  & 0x00ff), stdout);
-	for (i=0; i<256; i++)
-	    fputc((unsigned char) Red[i]*255/maxval, stdout);
-	for (i=0; i<256; i++)
-	    fputc((unsigned char) Green[i]*255/maxval, stdout);
-	for (i=0; i<256; i++)
-	    fputc((unsigned char) Blue[i]*255/maxval, stdout);
-	
-	for (row=0; row<height; row++) 
-	{
-	    for (col=0; col<width; col++) 
-		fputc(GetPixel(col, row), stdout);
-	    if (width % 2)
-		fputc(0x00, stdout); /* pad to 2-bytes */
-	}
+    if (depth == 8) {
+        unsigned int i;
+        unsigned int row;
+
+        fputc((unsigned char)((ncolors >> 8) & 0x00ff), stdout);
+        fputc((unsigned char)(ncolors  & 0x00ff), stdout);
+        for (i = 0; i < 256; ++i)
+            fputc((unsigned char) Red[i]*255/maxval, stdout);
+        for (i=0; i < 256; ++i)
+            fputc((unsigned char) Green[i]*255/maxval, stdout);
+        for (i = 0; i < 256; ++i)
+            fputc((unsigned char) Blue[i]*255/maxval, stdout);
+    
+        for (row=0; row < height; ++row) {
+            unsigned int col;
+            for (col = 0; col < width; ++col) 
+                fputc(GetPixel(col, row), stdout);
+            if ((width % 2) != 0)
+                fputc(0x00, stdout); /* pad to 2-bytes */
+        }
     } else if (depth == 1) {
-	/* mono image */
-	/* no colormap */
-	fputc(0x00, stdout);
-	fputc(0x00, stdout);
-
-	for (row=0; row<height; row++) 
-	{
-	    unsigned char bits = 0;
-	    for (col=0; col<width; col++) {
-		if (GetPixel(col,row))
-		    bits |= (unsigned char) (0x0080 >> (col % 8));
-		if (((col + 1) % 8) == 0)  {
-		    fputc(bits, stdout);
-		    bits = 0;
-		}
-	    }
-	    if ((width % 8) != 0)
-		fputc(bits, stdout);
-	    if ((width % 16) && (width % 16) <= 8)
-		fputc(0x00, stdout);  /* 16 bit pad */
-	}
+        /* mono image */
+        /* no colormap */
+
+        unsigned int row;
+
+        fputc(0x00, stdout);
+        fputc(0x00, stdout);
+
+        for (row = 0; row < height; ++row) {
+            unsigned char bits;
+            unsigned int col;
+            bits = 0;
+            for (col = 0; col < width; ++col) {
+                if (GetPixel(col,row))
+                    bits |= (unsigned char) (0x0080 >> (col % 8));
+                if (((col + 1) % 8) == 0)  {
+                    fputc(bits, stdout);
+                    bits = 0;
+                }
+            }
+            if ((width % 8) != 0)
+                fputc(bits, stdout);
+            if ((width % 16) && (width % 16) <= 8)
+                fputc(0x00, stdout);  /* 16 bit pad */
+        }
     } else {
-	/* no colormap, direct or true color (24 bit) image */
-	fputc(0x00, stdout);
-	fputc(0x00, stdout);
-	
-	for (row=0; row<height; row++) 
-	{
-	    for (col=0; col<width; col++) 
-		fputc(pixels[row][col].r * 255 / maxval, stdout);
-	    if (width % 2)
-		fputc(0x00, stdout); /* pad to 2-bytes */
-	    for (col=0; col<width; col++) 
-		fputc(pixels[row][col].g * 255 / maxval, stdout);
-	    if (width % 2)
-		fputc(0x00, stdout); /* pad to 2-bytes */
-	    for (col=0; col<width; col++) 
-		fputc(pixels[row][col].b * 255 / maxval, stdout);
-	    if (width % 2)
-		fputc(0x00, stdout); /* pad to 2-bytes */
-	}
+        /* no colormap, direct or true color (24 bit) image */
+
+        unsigned int row;
+
+        fputc(0x00, stdout);
+        fputc(0x00, stdout);
+        
+        for (row = 0; row < height; ++row) {
+            unsigned int col;
+            for (col = 0; col < width; ++col) 
+                fputc(pixels[row][col].r * 255 / maxval, stdout);
+            if (width % 2 != 0)
+                fputc(0x00, stdout); /* pad to 2-bytes */
+            for (col = 0; col < width; ++col) 
+                fputc(pixels[row][col].g * 255 / maxval, stdout);
+            if (width % 2 != 0)
+                fputc(0x00, stdout); /* pad to 2-bytes */
+            for (col = 0; col < width; ++col) 
+                fputc(pixels[row][col].b * 255 / maxval, stdout);
+            if (width % 2 != 0)
+                fputc(0x00, stdout); /* pad to 2-bytes */
+        }
     }
 }
 
 
 
 int
-main( argc, argv )
-int argc;
-char *argv[];
-{
-    FILE *ifd;
-    int argn, rows, cols, colors, i, BitsPerPixel;
+main(int argc, const char * argv[]) {
+
+    FILE * ifP;
+    int argn;
+    int rows, cols;
+    unsigned int BitsPerPixel;
+    int colors;
     pixval maxval;
     colorhist_vector chv;
     const char * const usage = "[ppmfile]";
     
-    ppm_init(&argc, argv);
+    pm_proginit(&argc, argv);
     
     argn = 1;
     
-    if ( argn < argc )
-    {
-	ifd = pm_openr( argv[argn] );
-	argn++;
+    if (argn < argc) {
+        ifP = pm_openr(argv[argn]);
+        argn++;
     } else
-	ifd = stdin;
+        ifP = stdin;
     
-    if ( argn != argc )
-	pm_usage( usage );
+    if (argn != argc)
+        pm_usage(usage);
     
-    pixels = ppm_readppm( ifd, &cols, &rows, &maxval );
+    pixels = ppm_readppm(ifP, &cols, &rows, &maxval);
     
-    pm_close( ifd );
+    pm_close(ifP);
     
     /* Figure out the colormap. */
-    fprintf( stderr, "(Computing colormap..." );
-    fflush( stderr );
-    chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
-    if ( chv != (colorhist_vector) 0 )
-    {
-	fprintf( stderr, "  Done.  %d colors found.)\n", colors );
-	
-	for ( i = 0; i < colors; i++ )
-	{
-	    Red[i] = (int) PPM_GETR( chv[i].color );
-	    Green[i] = (int) PPM_GETG( chv[i].color );
-	    Blue[i] = (int) PPM_GETB( chv[i].color );
-	}
-	BitsPerPixel = colorstobpp( colors );
-	
-	/* And make a hash table for fast lookup. */
-	cht = ppm_colorhisttocolorhash( chv, colors );
-	ppm_freecolorhist( chv );
+    pm_message("Computing colormap...");
+    chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
+    if (chv) {
+        unsigned int i;
+
+        pm_message("... Done.  %u colors found.", colors);
+    
+        for (i = 0; i < colors; ++i) {
+            Red[i]   = (int) PPM_GETR( chv[i].color);
+            Green[i] = (int) PPM_GETG( chv[i].color);
+            Blue[i]  = (int) PPM_GETB( chv[i].color);
+        }
+        BitsPerPixel = colorstobpp(colors);
+    
+        /* And make a hash table for fast lookup. */
+        cht = ppm_colorhisttocolorhash(chv, colors);
+        ppm_freecolorhist(chv);
     } else {
-	BitsPerPixel = 24;
-	fprintf( stderr, "  Done.  24-bit true color %d color image.)\n", colors );
+        BitsPerPixel = 24;
+        pm_message("  ... Done.  24-bit true color %u color image.", colors);
     }
     
     leaf_writeimg(cols, rows, BitsPerPixel, colors, maxval);
     
-    return( 0 );
+    return 0;
 }
-
-
-
diff --git a/converter/ppm/ppmtomitsu.c b/converter/ppm/ppmtomitsu.c
index 3934ae45..e59f09b3 100644
--- a/converter/ppm/ppmtomitsu.c
+++ b/converter/ppm/ppmtomitsu.c
@@ -1,10 +1,10 @@
-/* ppmtomitsu.c - read a portable pixmap and produce output for the
+/* ppmtomitsu.c - read a PPM image and produce output for the
 **                Mitsubishi S340-10 Thermo-Sublimation Printer
 **                (or the S3410-30 parallel interface)
 **
 ** Copyright (C) 1992,93 by S.Petra Zeidler
 ** Minor modifications by Ingo Wilken:
-x**  - mymalloc() and check_and_rotate() functions for often used
+**  - mymalloc() and check_and_rotate() functions for often used
 **    code fragments.  Reduces code size by a few KB.
 **  - use pm_error() instead of fprintf(stderr)
 **  - localized allocation of colorhastable
@@ -20,362 +20,70 @@ x**  - mymalloc() and check_and_rotate() functions for often used
 ** implied warranty.
 */
 
+#include <assert.h>
 #include <string.h>
+#include <stdio.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
 #include "nstring.h"
 #include "mallocvar.h"
+#include "ppm.h"
 
 #include "mitsu.h"
 
 
-#include <stdio.h>
-
 #define HASHSIZE 2048
 #define myhash(x) ((PPM_GETR(x)*3 + PPM_GETG(x)*5 + PPM_GETB(x)*7) % HASHSIZE)
 
 typedef struct hashinfo {
         pixel     color;
         long      flag;
-        struct hashinfo *next;
+        struct hashinfo * next;
 } hashinfo;
 
-#ifdef __STDC__
-static void lineputinit(int cols, int rows, int sharpness, int enlarge, int
-                        copy, struct mediasize medias);
-static void frametransferinit(int cols, int rows, int sharpness, int enlarge,
-                              int copy, struct mediasize medias);
-static void lookuptableinit(int sharpness, int enlarge, int copy,
-                            struct mediasize medias);
-static void lookuptabledata(int cols, int rows, int enlarge,
-                            struct mediasize medias);
-static void check_and_rotate(int cols, int rows, int enlarge,
-                             struct mediasize medias);
-#define CONST const
-#else /*__STDC__*/
-static int lineputinit();
-static int lookuptableinit();
-static int lookuptabledata();
-static int frametransferinit();
-static int check_and_rotate();
-#define CONST
-#endif
-
 #define cmd(arg)           fputc((arg), stdout)
 #define datum(arg)         fputc((char)(arg), stdout)
 #define data(arg,num)      fwrite((arg), sizeof(char), (num), stdout)
 
 
-#ifdef __STDC__
-int main(int argc, char *argv[] )
-#else
-int main( argc, argv )
-    int argc;
-    char* argv[];
-#endif
-    {
-    FILE             *ifp;
-    /*hashinfo         colorhashtable[HASHSIZE];*/
-    struct hashinfo  *hashrun;
-    pixel            *xP;
-    int              argn;
-    bool             dpi300;
-    int              cols, rows, format, col, row;
-    int              sharpness, enlarge, copy, tiny;
-    pixval           maxval;
-    struct mediasize medias;
-    char             media[16];
-    const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media <a,a4,as,a4s>] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]";
-
-    ppm_init(&argc, argv);
-
-    dpi300 = FALSE;
-    argn = 1;
-    sharpness = 32;
-    enlarge   = 1;
-    copy      = 1;
-    memset(media, '\0', 16);
-    tiny      = FALSE;
-
-    /* check for flags */
-    while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
-    if (pm_keymatch(argv[argn], "-sharpness", 2)) {
-        ++argn;
-        if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1)
-            pm_usage(usage);
-        else if (sharpness < 1 || sharpness > 4)
-            pm_usage(usage);
-        }
-    else if (pm_keymatch(argv[argn], "-enlarge", 2)) {
-        ++argn;
-        if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1)
-            pm_usage(usage);
-        else if (enlarge < 1 || enlarge > 3)
-            pm_usage(usage);
-        }
-    else if (pm_keymatch(argv[argn], "-media", 2)) {
-        ++argn;
-        if (argn == argc || sscanf(argv[argn], "%15s", media) < 1)
-            pm_usage(usage);
-        else if (TOUPPER(media[0]) != 'A')
-            pm_usage(usage);
-    }
-    else if (pm_keymatch(argv[argn], "-copy", 2)) {
-        ++argn;
-        if (argn == argc || sscanf(argv[argn], "%d", &copy) != 1)
-            pm_usage(usage);
-        else if (copy < 1 || copy > 9)
-            pm_usage(usage);
-        }
-    else if (pm_keymatch(argv[argn], "-dpi300", 2))
-        dpi300 = TRUE;
-    else if (pm_keymatch(argv[argn], "-tiny", 2))
-        tiny = TRUE;
-    else
-        pm_usage(usage);
-        ++argn;
-    }
-
-    if (argn < argc) {
-        ifp = pm_openr(argv[argn]);
-        ++argn;
-    }
-    else
-        ifp = stdin;
-
-    if (argn != argc)
-        pm_usage(usage);
 
-    if (TOUPPER(media[0]) == 'A')
-        switch (TOUPPER(media[1])) {
-        case 'S':
-            medias = MSize_AS;
-            break;
-        case '4':
-            if(TOUPPER(media[2]) == 'S')
-                medias = MSize_A4S;
-            else {
-                medias = MSize_A4;
-            }
-            break;
-        default:
-            medias = MSize_A;
-        }
-    else
-        medias = MSize_User;
-
-        if (dpi300) {
-                medias.maxcols *= 2;
-                medias.maxrows *= 2;
-        }
+static void
+check_and_rotate(int              const cols,
+                 int              const rows,
+                 int              const enlarge,
+                 struct mediasize const medias) {
 
-    if (tiny) {
-        pixel            *pixelrow;
-        char             *redrow, *greenrow, *bluerow;
-
-        ppm_readppminit(ifp, &cols, &rows, &maxval, &format);
-        pixelrow = (pixel *) ppm_allocrow(cols);
-        MALLOCARRAY_NOFAIL(redrow, cols);
-        MALLOCARRAY_NOFAIL(greenrow, cols);
-        MALLOCARRAY_NOFAIL(bluerow, cols);
-        lineputinit(cols, rows, sharpness, enlarge, copy, medias);
-
-        for ( row = 0; row < rows; ++row ) {
-            ppm_readppmrow(ifp, pixelrow, cols, maxval, format);
-            switch(PPM_FORMAT_TYPE(format)) {
-            /* color */
-            case PPM_TYPE:
-                for (col = 0, xP = pixelrow; col < cols; col++, xP++) {
-                    /* First red. */
-                    redrow[col] = PPM_GETR(*xP);
-                    /* Then green. */
-                    greenrow[col] = PPM_GETG(*xP);
-                    /* And blue. */
-                    bluerow[col] = PPM_GETB(*xP);
-                }
-                data(redrow,   cols);
-                data(greenrow, cols);
-                data(bluerow,  cols);
-                break;
-            /* grayscale */
-            default:
-                for (col = 0, xP = pixelrow; col < cols; col++, xP++)
-                    bluerow[col] = PPM_GETB(*xP);
-                data(bluerow, cols);
-                data(bluerow, cols);
-                data(bluerow, cols);
-                break;
-            }
-        }
-        pm_close(ifp);
+    if (cols > rows) {
+        ROTATEIMG(DOROTATE);                        /* rotate image */
+        if (enlarge * rows > medias.maxcols || enlarge * cols > medias.maxrows)
+            pm_error("Image too large, MaxPixels = %u x %u",
+                     medias.maxrows, medias.maxcols);
+        HPIXELS(cols);
+        VPIXELS(rows);
+        HPIXELSOFF((medias.maxcols/enlarge - rows)/2);
+        VPIXELSOFF((medias.maxrows/enlarge - cols)/2);
+        pm_message("rotating image for output");
+    } else {
+        ROTATEIMG(DONTROTATE);
+        if (enlarge * rows > medias.maxrows || enlarge * cols > medias.maxcols)
+            pm_error("Image too large, MaxPixels = %u x %u",
+                     medias.maxrows, medias.maxcols);
+        HPIXELS(cols);
+        VPIXELS(rows);
+        HPIXELSOFF((medias.maxcols/enlarge - cols)/2);
+        VPIXELSOFF((medias.maxrows/enlarge - rows)/2);
     }
-    else {
-        pixel            **pixelpic;
-        int              colanz, colval;
-        int                 i;
-        colorhist_vector table;
-
-        ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
-        pixelpic = ppm_allocarray( cols, rows );
-        for (row = 0; row < rows; row++)
-            ppm_readppmrow( ifp, pixelpic[row], cols, maxval, format );
-        pm_close(ifp);
-
-        /* first check wether we can use the lut transfer */
+}
 
-        table = ppm_computecolorhist(pixelpic, cols, rows, MAXLUTCOL+1, 
-                                     &colanz);
-        if (table != NULL) {
-            hashinfo *colorhashtable;
 
-            MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE);
-            for (i=0; i<HASHSIZE; i++) {
-                colorhashtable[i].flag = -1;
-                colorhashtable[i].next = NULL;
-            }
 
-            /* we can use the lookuptable */
-            pm_message("found %d colors - using the lookuptable-method",
-                       colanz);
-            lookuptableinit(sharpness, enlarge, copy, medias);
-            switch(PPM_FORMAT_TYPE(format)) {
-            /* color */
-            case PPM_TYPE:
-                for (colval=0; colval<colanz; colval++) {
-                    cmd('$');
-                    datum(colval);
-                    datum(PPM_GETR((table[colval]).color));
-                    datum(PPM_GETG((table[colval]).color));
-                    datum(PPM_GETB((table[colval]).color));
-
-                    hashrun = &colorhashtable[myhash((table[colval]).color)];
-                    if (hashrun->flag == -1) {
-                        hashrun->color = (table[colval]).color;
-                        hashrun->flag  = colval;
-                    }
-                    else {
-                        while (hashrun->next != NULL)
-                            hashrun = hashrun->next;
-                        MALLOCVAR_NOFAIL(hashrun->next);
-                        hashrun = hashrun->next;
-                        hashrun->color = (table[colval]).color;
-                        hashrun->flag  = colval;
-                        hashrun->next  = NULL;
-                    }
-                }
-                break;
-            /* other */
-            default:
-                for (colval=0; colval<colanz; colval++) {
-                    cmd('$');
-                    datum(colval);
-                    datum(PPM_GETB((table[colval]).color));
-                    datum(PPM_GETB((table[colval]).color));
-                    datum(PPM_GETB((table[colval]).color));
-
-                    hashrun = &colorhashtable[myhash((table[colval]).color)];
-                    if (hashrun->flag == -1) {
-                        hashrun->color = (table[colval]).color;
-                        hashrun->flag  = colval;
-                    }
-                    else {
-                        while (hashrun->next != NULL)
-                            hashrun = hashrun->next;
-                        MALLOCVAR_NOFAIL(hashrun->next);
-                        hashrun = hashrun->next;
-                        hashrun->color = (table[colval]).color;
-                        hashrun->flag  = colval;
-                        hashrun->next  = NULL;
-                    }
-                }
-            }
-            lookuptabledata(cols, rows, enlarge, medias);
-            for (row=0; row<rows; row++) {
-                xP = pixelpic[row];
-                for (col=0; col<cols; col++, xP++) {
-                    hashrun = &colorhashtable[myhash(*xP)];
-                    while (!PPM_EQUAL((hashrun->color), *xP))
-                        if (hashrun->next != NULL)
-                            hashrun = hashrun->next;
-                        else {
-                            pm_error("you just found a lethal bug.");
-                        }
-                    datum(hashrun->flag);
-                }
-            }
-            free(colorhashtable);
-        }
-        else {
-        /* $#%@^!& no lut possible, so send the pic as 24bit */
-            pm_message("found too many colors for fast lookuptable mode");
-            frametransferinit(cols, rows, sharpness, enlarge, copy, medias);
-            switch(PPM_FORMAT_TYPE(format)) {
-            /* color */
-            case PPM_TYPE:
-                COLORDES(RED);
-                DATASTART;                    /* red coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETR(*xP));
-                }
-                COLORDES(GREEN);
-                DATASTART;                    /* green coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETG(*xP));
-                }
-                COLORDES(BLUE);
-                DATASTART;                    /* blue coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETB(*xP));
-                }
-                break;
-            /* grayscale */
-            default:
-                COLORDES(RED);
-                DATASTART;                    /* red coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETB(*xP));
-                }
-                COLORDES(GREEN);
-                DATASTART;                    /* green coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETB(*xP));
-                }
-                COLORDES(BLUE);
-                DATASTART;                    /* blue coming */
-                for (row=0; row<rows; row++) {
-                    xP = pixelpic[row];
-                    for (col=0; col<cols; col++, xP++)
-                        datum(PPM_GETB(*xP));
-                }
-            }
-        }
-    }
-    PRINTIT;
-    exit(0);
-}
-
-#ifdef __STDC__
-static void lineputinit(int cols, int rows,
-                        int sharpness, int enlarge, int copy,
-                        struct mediasize medias)
-#else /*__STDC__*/
-static int lineputinit(cols, rows, sharpness, enlarge, copy, medias)
-    int cols, rows;
-    int sharpness, enlarge, copy;
-    struct mediasize medias;
-#endif /*__STDC__*/
-{
+static void
+lineputinit(int              const cols,
+            int              const rows,
+            int              const sharpness,
+            int              const enlarge,
+            int              const copy,
+            struct mediasize const medias) {
     ONLINE;
     CLRMEM;
     MEDIASIZE(medias);
@@ -426,18 +134,16 @@ static int lineputinit(cols, rows, sharpness, enlarge, copy, medias)
     }
     check_and_rotate(cols, rows, enlarge, medias);
     DATASTART;
-    return;
 }
 
-#ifdef __STDC__
-static void lookuptableinit(int sharpness, int enlarge, int copy,
-                            struct mediasize medias)
-#else /*__STDC__*/
-static int lookuptableinit(sharpness, enlarge, copy, medias)
-    int sharpness, enlarge, copy;
-    struct mediasize medias;
-#endif /*__STDC__*/
-{
+
+
+static void
+lookuptableinit(int              const sharpness,
+                int              const enlarge,
+                int              const copy,
+                struct mediasize const medias) {
+
     ONLINE;
     CLRMEM;
     MEDIASIZE(medias);
@@ -486,36 +192,31 @@ static int lookuptableinit(sharpness, enlarge, copy, medias)
     }
 
     LOADLOOKUPTABLE;
-    return;
 }
 
-#ifdef __STDC__
-static void lookuptabledata(int cols, int rows, int enlarge,
-                                                        struct mediasize medias)
-#else /*__STDC__*/
-static int lookuptabledata(cols, rows, enlarge, medias)
-    int   rows, cols;
-    int   enlarge;
-    struct mediasize medias;
-#endif /*__STDC__*/
-{
+
+
+static void
+lookuptabledata(int              const cols,
+                int              const rows,
+                int              const enlarge,
+                struct mediasize const medias) {
+
     DONELOOKUPTABLE;
     check_and_rotate(cols, rows, enlarge, medias);
     DATASTART;
-    return;
 }
 
-#ifdef __STDC__
-static void frametransferinit(int cols, int rows, int sharpness,
-                              int enlarge, int copy, struct mediasize medias)
-#else
-static int frametransferinit(cols, rows, sharpness, enlarge, copy, medias)
 
-    int     rows, cols;
-    int     sharpness, enlarge, copy;
-    struct mediasize medias;
-#endif
-{
+
+static void
+frametransferinit(int              const cols,
+                  int              const rows,
+                  int              const sharpness,
+                  int              const enlarge,
+                  int              const copy,
+                  struct mediasize const medias) {
+
     ONLINE;
     CLRMEM;
     MEDIASIZE(medias);
@@ -565,40 +266,458 @@ static int frametransferinit(cols, rows, sharpness, enlarge, copy, medias)
         SHARPNESS(SP_USER);
     }
     check_and_rotate(cols, rows, enlarge, medias);
-    return;
 }
 
 
-#ifdef __STDC__
+
 static void
-check_and_rotate(int cols, int rows, int enlarge, struct mediasize medias)
-#else
-static int
-check_and_rotate(cols, rows, enlarge, medias)
-    int cols, rows, enlarge;
-    struct mediasize medias;
-#endif
-{
-    if (cols > rows) {
-        ROTATEIMG(DOROTATE);                        /* rotate image */
-        if (enlarge*rows > medias.maxcols || enlarge*cols > medias.maxrows) {
-            pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols);
+doLookupTableColors(colorhist_vector const table,
+                    unsigned int     const nColor,
+                    hashinfo *       const colorhashtable) {
+                
+    unsigned int colval;
+    for (colval = 0; colval < nColor; ++colval) {
+        struct hashinfo * const hashchain =
+            &colorhashtable[myhash((table[colval]).color)];
+
+        struct hashinfo * hashrun;
+
+        cmd('$');
+        datum(colval);
+        datum(PPM_GETR((table[colval]).color));
+        datum(PPM_GETG((table[colval]).color));
+        datum(PPM_GETB((table[colval]).color));
+        
+        hashrun = hashchain;  /* start at beginning of chain */
+
+        if (hashrun->flag == -1) {
+            hashrun->color = (table[colval]).color;
+            hashrun->flag  = colval;
+        } else {
+            while (hashrun->next != NULL)
+                hashrun = hashrun->next;
+            MALLOCVAR_NOFAIL(hashrun->next);
+            hashrun = hashrun->next;
+            hashrun->color = (table[colval]).color;
+            hashrun->flag  = colval;
+            hashrun->next  = NULL;
         }
-        HPIXELS(cols);
-        VPIXELS(rows);
-        HPIXELSOFF((medias.maxcols/enlarge - rows)/2);
-        VPIXELSOFF((medias.maxrows/enlarge - cols)/2);
-        pm_message("rotating image for output");
     }
-    else {
-        ROTATEIMG(DONTROTATE);
-        if (enlarge*rows > medias.maxrows || enlarge*cols > medias.maxcols) {
-            pm_error("Image too large, MaxPixels = %d x %d", medias.maxrows, medias.maxcols);
+}
+
+
+
+static void
+doLookupTableGrays(colorhist_vector const table,
+                   unsigned int     const nColor,
+                   hashinfo *       const colorhashtable) {
+
+    unsigned int colval;
+    for (colval = 0; colval < nColor; ++colval) {
+        struct hashinfo * const hashchain =
+            &colorhashtable[myhash((table[colval]).color)];
+        struct hashinfo * hashrun;
+
+        cmd('$');
+        datum(colval);
+        datum(PPM_GETB((table[colval]).color));
+        datum(PPM_GETB((table[colval]).color));
+        datum(PPM_GETB((table[colval]).color));
+        
+        hashrun = hashchain;  /* start at beginning of chain */
+
+        if (hashrun->flag == -1) {
+            hashrun->color = (table[colval]).color;
+            hashrun->flag  = colval;
+        } else {
+            while (hashrun->next != NULL)
+                hashrun = hashrun->next;
+            MALLOCVAR_NOFAIL(hashrun->next);
+            hashrun = hashrun->next;
+            hashrun->color = (table[colval]).color;
+            hashrun->flag  = colval;
+            hashrun->next  = NULL;
         }
-        HPIXELS(cols);
-        VPIXELS(rows);
-        HPIXELSOFF((medias.maxcols/enlarge - cols)/2);
-        VPIXELSOFF((medias.maxrows/enlarge - rows)/2);
     }
 }
 
+
+
+static void
+generateLookupTable(colorhist_vector const table,
+                    unsigned int     const nColor,
+                    unsigned int     const cols,
+                    unsigned int     const rows,
+                    int              const format,
+                    int              const sharpness,
+                    int              const enlarge,
+                    int              const copy,
+                    struct mediasize const medias,
+                    hashinfo **      const colorhashtableP) {
+/*----------------------------------------------------------------------------
+   Write to the output file the palette (color lookup table) indicated by
+   'table' and generate a hash table to use with it: *colorhashtableP.
+
+   Also write the various properties 'sharpness', 'enlarge', 'copy', and
+   'medias' to the output file.
+-----------------------------------------------------------------------------*/
+    hashinfo * colorhashtable;
+
+    lookuptableinit(sharpness, enlarge, copy, medias);
+
+    /* Initialize the hash table to empty */
+
+    MALLOCARRAY_NOFAIL(colorhashtable, HASHSIZE);
+    {
+        unsigned int i;
+        for (i = 0; i < HASHSIZE; ++i) {
+            colorhashtable[i].flag = -1;
+                    colorhashtable[i].next = NULL;
+        }
+    }
+
+    switch(PPM_FORMAT_TYPE(format)) {
+    case PPM_TYPE:
+        doLookupTableColors(table, nColor, colorhashtable);
+        break;
+    default:
+        doLookupTableGrays(table, nColor, colorhashtable);
+    }
+    lookuptabledata(cols, rows, enlarge, medias);
+
+    *colorhashtableP = colorhashtable;
+}
+
+
+
+static void
+writeColormapRaster(pixel **         const pixels,
+                    unsigned int     const cols,
+                    unsigned int     const rows,
+                    hashinfo *       const colorhashtable) {
+/*----------------------------------------------------------------------------
+   Write a colormapped raster: write the pixels pixels[][] (dimensions cols x
+   rows) as indices into the colormap (palette; lookup table) indicated by
+   'colorhashtable'.
+-----------------------------------------------------------------------------*/
+    unsigned int row;
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+
+        for (col = 0; col < cols; ++col) {
+            pixel * const pixrow = pixels[row];
+            struct hashinfo * const hashchain =
+                &colorhashtable[myhash(pixrow[col])];
+            struct hashinfo * p;
+                
+            p = hashchain;
+            while (!PPM_EQUAL((p->color), pixrow[col])) {
+                assert(p->next);
+                p = p->next;
+            }
+            datum(p->flag);
+        }
+    }
+}
+
+
+
+static void
+useLookupTable(pixel **         const pixels,
+               colorhist_vector const table,
+               int              const sharpness,
+               int              const enlarge,
+               int              const copy,
+               struct mediasize const medias,
+               unsigned int     const cols,
+               unsigned int     const rows,
+               int              const format,
+               unsigned int     const nColor) {
+
+    hashinfo * colorhashtable;
+
+    pm_message("found %u colors - using the lookuptable-method", nColor);
+
+    generateLookupTable(table, nColor, cols, rows, format,
+                        sharpness, enlarge, copy, medias,
+                        &colorhashtable);
+
+    writeColormapRaster(pixels, cols, rows, colorhashtable);
+
+    free(colorhashtable);
+}
+
+
+
+static void
+noLookupColor(pixel **     const pixels,
+              unsigned int const cols,
+              unsigned int const rows) {
+
+    unsigned int row;
+    COLORDES(RED);
+    DATASTART;                    /* red coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETR(pixrow[col]));
+    }
+    COLORDES(GREEN);
+    DATASTART;                    /* green coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETG(pixrow[col]));
+    }
+    COLORDES(BLUE);
+    DATASTART;                    /* blue coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETB(pixrow[col]));
+    }
+}
+
+
+
+static void
+noLookupGray(pixel **     const pixels,
+             unsigned int const cols,
+             unsigned int const rows) {
+
+    unsigned int row;
+    COLORDES(RED);
+    DATASTART;                    /* red coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETB(pixrow[col]));
+    }
+    COLORDES(GREEN);
+    DATASTART;                    /* green coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETB(pixrow[col]));
+    }
+    COLORDES(BLUE);
+    DATASTART;                    /* blue coming */
+    for (row = 0; row < rows; ++row) {
+        pixel * const pixrow = pixels[row];
+        unsigned int col;
+        for (col = 0; col < cols; ++col)
+            datum(PPM_GETB(pixrow[col]));
+    }
+}
+
+
+
+static void
+useNoLookupTable(pixel **         const pixels,
+                 int              const sharpness,
+                 int              const enlarge,
+                 int              const copy,
+                 struct mediasize const medias,
+                 unsigned int     const cols,
+                 unsigned int     const rows,
+                 int              const format) {
+
+    /* $#%@^!& no lut possible, so send the pic as 24bit */
+
+    pm_message("found too many colors for fast lookuptable mode");
+
+    frametransferinit(cols, rows, sharpness, enlarge, copy, medias);
+    switch(PPM_FORMAT_TYPE(format)) {
+    case PPM_TYPE:
+        noLookupColor(pixels, cols, rows);
+        break;
+    default:
+        noLookupGray(pixels, cols, rows);
+    }
+}
+
+
+
+static void
+doTiny(FILE *           const ifP,
+       unsigned int     const cols,
+       unsigned int     const rows,
+       pixval           const maxval,
+       int              const format,
+       int              const sharpness,
+       int              const enlarge,
+       int              const copy,
+       struct mediasize const medias) {
+       
+    pixel * pixelrow;
+    unsigned char * redrow;
+    unsigned char * grnrow;
+    unsigned char * blurow;
+    unsigned int row;
+
+    pixelrow = ppm_allocrow(cols);
+    MALLOCARRAY_NOFAIL(redrow, cols);
+    MALLOCARRAY_NOFAIL(grnrow, cols);
+    MALLOCARRAY_NOFAIL(blurow, cols);
+    lineputinit(cols, rows, sharpness, enlarge, copy, medias);
+
+    for (row = 0; row < rows; ++row) {
+        ppm_readppmrow(ifP, pixelrow, cols, maxval, format);
+        switch(PPM_FORMAT_TYPE(format)) {
+        case PPM_TYPE: {            /* color */
+            unsigned int col;
+            for (col = 0; col < cols; ++col) {
+                redrow[col] = PPM_GETR(pixelrow[col]);
+                grnrow[col] = PPM_GETG(pixelrow[col]);
+                blurow[col] = PPM_GETB(pixelrow[col]);
+            }
+            data(redrow, cols);
+            data(grnrow, cols);
+            data(blurow, cols);
+        } break;
+        default: {           /* grayscale */
+            unsigned int col;
+            for (col = 0; col < cols; ++col)
+                blurow[col] = PPM_GETB(pixelrow[col]);
+            data(blurow, cols);
+            data(blurow, cols);
+            data(blurow, cols);
+        }
+        }
+    }
+}
+
+
+
+int
+main(int argc, char * argv[]) {
+    FILE * ifP;
+    int              argn;
+    bool             dpi300;
+    int              cols, rows, format;
+    pixval           maxval;
+    int              sharpness, enlarge, copy, tiny;
+    struct mediasize medias;
+    char             media[16];
+    const char * const usage = "[-sharpness <1-4>] [-enlarge <1-3>] [-media <a,a4,as,a4s>] [-copy <1-9>] [-tiny] [-dpi300] [ppmfile]";
+
+    ppm_init(&argc, argv);
+
+    dpi300 = FALSE;
+    argn = 1;
+    sharpness = 32;
+    enlarge   = 1;
+    copy      = 1;
+    memset(media, '\0', 16);
+    tiny      = FALSE;
+
+    /* check for flags */
+    while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
+    if (pm_keymatch(argv[argn], "-sharpness", 2)) {
+        ++argn;
+        if (argn == argc || sscanf(argv[argn], "%d", &sharpness) != 1)
+            pm_usage(usage);
+        else if (sharpness < 1 || sharpness > 4)
+            pm_usage(usage);
+        }
+    else if (pm_keymatch(argv[argn], "-enlarge", 2)) {
+        ++argn;
+        if (argn == argc || sscanf(argv[argn], "%d", &enlarge) != 1)
+            pm_usage(usage);
+        else if (enlarge < 1 || enlarge > 3)
+            pm_usage(usage);
+        }
+    else if (pm_keymatch(argv[argn], "-media", 2)) {
+        ++argn;
+        if (argn == argc || sscanf(argv[argn], "%15s", media) < 1)
+            pm_usage(usage);
+        else if (TOUPPER(media[0]) != 'A')
+            pm_usage(usage);
+    }
+    else if (pm_keymatch(argv[argn], "-copy", 2)) {
+        ++argn;
+        if (argn == argc || sscanf(argv[argn], "%d", &copy) != 1)
+            pm_usage(usage);
+        else if (copy < 1 || copy > 9)
+            pm_usage(usage);
+        }
+    else if (pm_keymatch(argv[argn], "-dpi300", 2))
+        dpi300 = TRUE;
+    else if (pm_keymatch(argv[argn], "-tiny", 2))
+        tiny = TRUE;
+    else
+        pm_usage(usage);
+        ++argn;
+    }
+
+    if (argn < argc) {
+        ifP = pm_openr(argv[argn]);
+        ++argn;
+    }
+    else
+        ifP = stdin;
+
+    if (argn != argc)
+        pm_usage(usage);
+
+    if (TOUPPER(media[0]) == 'A')
+        switch (TOUPPER(media[1])) {
+        case 'S':
+            medias = MSize_AS;
+            break;
+        case '4':
+            if(TOUPPER(media[2]) == 'S')
+                medias = MSize_A4S;
+            else {
+                medias = MSize_A4;
+            }
+            break;
+        default:
+            medias = MSize_A;
+        }
+    else
+        medias = MSize_User;
+
+    if (dpi300) {
+        medias.maxcols *= 2;
+        medias.maxrows *= 2;
+    }
+
+    ppm_readppminit(ifP, &cols, &rows, &maxval, &format);
+    
+    if (tiny) {
+        doTiny(ifP, cols, rows, maxval, format,
+               sharpness, enlarge, copy, medias);
+
+    } else {
+        pixel ** pixels;
+        int nColor;
+        colorhist_vector table;
+        unsigned int row;
+
+        pixels = ppm_allocarray(cols, rows);
+        for (row = 0; row < rows; ++row)
+            ppm_readppmrow(ifP, pixels[row], cols, maxval, format);
+
+        /* first check wether we can use the lut transfer */
+
+        table = ppm_computecolorhist(pixels, cols, rows, MAXLUTCOL+1, 
+                                     &nColor);
+        if (table)
+            useLookupTable(pixels, table, sharpness, enlarge, copy, medias,
+                           cols, rows, format, nColor);
+        else
+            useNoLookupTable(pixels, sharpness, enlarge, copy, medias,
+                             cols, rows, format);
+        ppm_freearray(pixels, rows);
+    }
+    PRINTIT;
+    pm_close(ifP);
+    return 0;
+}
diff --git a/converter/ppm/ppmtomitsu.test b/converter/ppm/ppmtomitsu.test
new file mode 100644
index 00000000..f574d927
--- /dev/null
+++ b/converter/ppm/ppmtomitsu.test
@@ -0,0 +1,12 @@
+echo Test 1.  Should print 3110813682 101562
+./ppmtomitsu ../../testimg.ppm | cksum 
+echo Test 2.  Should print 239186803 34399
+pnmquant 100 ../../testimg.ppm | ./ppmtomitsu | cksum 
+echo Test 3.  Should print 3201293405 310
+./ppmtomitsu ../../testgrid.pbm | cksum 
+echo Test 4.  Should print 3354679572 752
+./ppmtomitsu -tiny ../../testgrid.pbm | cksum 
+echo Test 5.  Should print 3999654426 101549
+./ppmtomitsu -tiny ../../testimg.ppm | cksum 
+echo Test 2.  Should print 3078685526 101549
+pnmquant 100 ../../testimg.ppm | ./ppmtomitsu -tiny | cksum 
diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile
index 4e0ad8d6..a1004fdd 100644
--- a/converter/ppm/ppmtompeg/Makefile
+++ b/converter/ppm/ppmtompeg/Makefile
@@ -5,7 +5,7 @@ endif
 SUBDIR = converter/ppm/ppmtompeg
 VPATH=.:$(SRCDIR)/$(SUBDIR)
 
-include $(BUILDDIR)/Makefile.config
+include $(BUILDDIR)/config.mk
 
 ifeq ($(JPEGLIB),NONE)
   # 'nojpeg' is a module that implements all the jpeg access routines as
@@ -18,11 +18,12 @@ else
   JPEGLIBX = $(JPEGLIB)
 endif
 
-INCLUDES = -I$(SRCDIR)/$(SUBDIR)/headers 
+COMP_INCLUDES = -I$(SRCDIR)/$(SUBDIR)/headers 
 
+EXTERN_INCLUDES =
 ifneq ($(JPEGHDR_DIR),NONE)
   ifneq ($(JPEGHDR_DIR)x,x)
-    INCLUDES += -I$(JPEGHDR_DIR)
+    EXTERN_INCLUDES += -I$(JPEGHDR_DIR)
   endif
 endif
 
@@ -38,17 +39,31 @@ endif
 #
 
 MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o
-MP_ENCODE_OBJS = iframe.o pframe.o bframe.o psearch.o bsearch.o block.o 
+MP_ENCODE_OBJS = \
+  frames.o \
+  iframe.o \
+  pframe.o \
+  bframe.o \
+  psearch.o \
+  bsearch.o \
+  block.o 
+
 MP_OTHER_OBJS = mpeg.o subsample.o param.o rgbtoycc.o \
 	readframe.o combine.o jrevdct.o frame.o fsize.o frametype.o \
-	specifics.o rate.o opts.o input.o gethostname.o
+	specifics.o rate.o opts.o input.o
 ifeq ($(OMIT_NETWORK),y)
-  MP_PARALLEL_OBJS = noparallel.o
+  MP_OTHER_OBJS += noparallel.o
+else
+  MP_OTHER_OBJS += parallel.o psocket.o
+endif
+ifeq ($(MSVCRT),Y)
+  MP_OTHER_OBJS += gethostname_win32.o
 else
-  MP_PARALLEL_OBJS = parallel.o psocket.o
+  MP_OTHER_OBJS += gethostname.o
 endif
+
 NONMAIN_OBJS = $(MP_BASE_OBJS) $(MP_OTHER_OBJS) $(MP_ENCODE_OBJS) \
-	      $(MP_PARALLEL_OBJS) $(JPEG_MODULE).o
+	      	$(JPEG_MODULE).o
 OBJECTS = ppmtompeg.o $(NONMAIN_OBJS)
 MERGE_OBJECTS = ppmtompeg.o2 $(NONMAIN_OBJS)
 MP_INCLUDE = mproto.h mtypes.h huff.h bitio.h
@@ -61,7 +76,7 @@ SCRIPTS =
 .PHONY: all
 all: ppmtompeg
 
-include $(SRCDIR)/Makefile.common
+include $(SRCDIR)/common.mk
 
 ifeq ($(NEED_RUNTIME_PATH),Y)
   LIBOPTR = -runtime
diff --git a/converter/ppm/ppmtompeg/bframe.c b/converter/ppm/ppmtompeg/bframe.c
index 5dfb76d3..1dbc1846 100644
--- a/converter/ppm/ppmtompeg/bframe.c
+++ b/converter/ppm/ppmtompeg/bframe.c
@@ -84,7 +84,6 @@ static struct bframeStats {
  *====================*/
 
 extern Block **dct, **dctr, **dctb;
-extern dct_data_type **dct_data;
 #define NO_MOTION 0
 #define MOTION 1
 #define SKIP 2  /* used in useMotion in dct_data */
diff --git a/converter/ppm/ppmtompeg/bsearch.c b/converter/ppm/ppmtompeg/bsearch.c
index 142987f5..70edfef6 100644
--- a/converter/ppm/ppmtompeg/bsearch.c
+++ b/converter/ppm/ppmtompeg/bsearch.c
@@ -77,6 +77,7 @@
 #include "frames.h"
 #include "motion_search.h"
 #include "fsize.h"
+#include "block.h"
 
 
 /*==================*
diff --git a/converter/ppm/ppmtompeg/combine.c b/converter/ppm/ppmtompeg/combine.c
index 52cc646d..8e0d3281 100644
--- a/converter/ppm/ppmtompeg/combine.c
+++ b/converter/ppm/ppmtompeg/combine.c
@@ -35,8 +35,8 @@
 #include <errno.h>
 #include <unistd.h>
 
-#include "ppm.h"
 #include "nstring.h"
+#include "nsleep.h"
 
 #include "mtypes.h"
 #include "frames.h"
@@ -111,11 +111,9 @@ appendSpecifiedGopFiles(struct inputSource * const inputSourceP,
              ++nAttempts) {
 
             ifP = fopen(fileName, "rb");
-            if (ifP == NULL) {
+            if (ifP == NULL)
                 pm_message("ERROR:  Couldn't read file '%s'.  retry %u", 
                            fileName, nAttempts);
-                sleep(1);
-            }
         }
         if (ifP) {
             if (!realQuiet)
diff --git a/converter/ppm/ppmtompeg/file.c b/converter/ppm/ppmtompeg/file.c
index ae741962..223170a4 100644
--- a/converter/ppm/ppmtompeg/file.c
+++ b/converter/ppm/ppmtompeg/file.c
@@ -19,17 +19,6 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
 
-/*  
- *  $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/file.c,v 1.2 1993/06/30 20:06:09 keving Exp $
- *  $Log: file.c,v $
- * Revision 1.2  1993/06/30  20:06:09  keving
- * nothing
- *
- * Revision 1.1  1993/06/03  21:08:08  keving
- * nothing
- *
- */
-
 #include "tk.h"
 
 #include "all.h"
@@ -40,11 +29,10 @@
 #include <time.h>
 #include <string.h>
 #include <dirent.h>
-#include <strings.h>
 
 #define MAX_FILES   1000
-#define MAX_NAME_LEN	256
-#define MAX_STRING_LEN	MAX_NAME_LEN
+#define MAX_NAME_LEN    256
+#define MAX_STRING_LEN  MAX_NAME_LEN
 
 typedef int boolean;
 #define TRUE 1
@@ -52,77 +40,76 @@ typedef int boolean;
 
 extern char currentPath[MAXPATHLEN];
 
-char	globString[1024];
+char globString[1024];
 
-static DIR *dfd;
+static DIR * dfd;
 
-void	ResetPath(void);
+void ResetPath(void);
 int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
-		  char **argv);
+                  char **argv);
 int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
-		  char **argv);
-void	SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN],
-		  boolean *dirList, int permute[]);
+                    char **argv);
+void SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN],
+               boolean *dirList, int permute[]);
+
+static void UpdatePath(Tcl_Interp *interp, char *directory);
+static boolean MatchesGlob(char *string, char *glob);
 
-static void	UpdatePath(Tcl_Interp *interp, char *directory);
-static boolean	MatchesGlob(char *string, char *glob);
 
 
+void
+ResetPath() {
 
-void	ResetPath()
-{
-    if ( getwd(currentPath) == 0 )
-    {
-	fprintf(stderr, "Error getting pathname!!!\n");
-	exit(1);
+    if (getwd(currentPath) == 0) {
+        fprintf(stderr, "Error getting pathname!!!\n");
+        exit(1);
     }
 
     strcpy(&currentPath[strlen(currentPath)], "/");
 
     dfd = opendir(currentPath);
-    if ( dfd == NULL )
-    {
-	fprintf(stderr, "can't open '%s'\n", currentPath);
-	exit(1);
+    if (dfd == NULL) {
+        fprintf(stderr, "can't open '%s'\n", currentPath);
+        exit(1);
     }
 }
 
 
-static void	UpdatePath(Tcl_Interp *interp, char *directory)
-{
+
+static void
+UpdatePath(Tcl_Interp *interp, char *directory) {
+
     int length;
     char *charPtr;
 
     length = strlen(currentPath);
 
-    if ( strcmp(directory, "./") == 0 )
-	return /* nothing */ ;
-    else if ( strcmp(directory, "../") == 0 )
-    {
-	/* delete backwards up to '/' */
-
-	if ( length < 2 )
-	{
-	    fprintf(stderr, "Error:  backing up from root directory!!!\n");
-	    exit(1);
-	}
-
-	charPtr = &currentPath[length-2];
-	while ( (charPtr != currentPath) && (*charPtr != '/') )
-	    charPtr--;
-	charPtr++;	/* leave the '/' */
-	*charPtr = '\0';
-    }
-    else
-    {
-	strcpy(&currentPath[length], directory);
+    if (streq(directory, "./"))
+        return /* nothing */ ;
+    else if (streq(directory, "../")) {
+        /* delete backwards up to '/' */
+
+        if (length < 2) {
+            fprintf(stderr, "Error:  backing up from root directory!!!\n");
+            exit(1);
+        }
+
+        charPtr = &currentPath[length-2];
+        while ((charPtr != currentPath) && (*charPtr != '/'))
+            --charPtr;
+        ++charPtr;  /* leave the '/' */
+        *charPtr = '\0';
+    } else {
+        strcpy(&currentPath[length], directory);
     }
 }
 
 
-int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
-		  char **argv)
-{
+
+int
+ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
+                char **argv) {
+
     char *directory = argv[1];
 
     UpdatePath(interp, directory);
@@ -130,82 +117,74 @@ int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
     fprintf(stdout, "Opening directory: '%s'\n", currentPath);
 
     dfd = opendir(currentPath);
-    if ( dfd == NULL )
-    {
-	fprintf(stderr, "can't open '%s'\n", currentPath);
-	return TCL_OK;	/* shouldn't, really */
+    if (dfd == NULL) {
+        fprintf(stderr, "can't open '%s'\n", currentPath);
+        return TCL_OK;  /* shouldn't, really */
     }
-
+    
     return TCL_OK;
 }
 
 
-int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
-		  char **argv)
-{
-    struct dirent *dp;
+
+int
+ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
+              char **argv) {
+
+    struct dirent * dp;
     struct stat stbuf;
     char command[256];
     char fileName[MAX_FILES][MAX_NAME_LEN];
     boolean dirList[MAX_FILES];
     int permute[MAX_FILES];
-    int	fileCount = 0;
-    register int index;
+    int fileCount = 0;
+    int index;
     char fullName[MAXPATHLEN];
-    char    *restPtr;
+    char * restPtr;
 
     sprintf(command, "ShowCurrentDirectory %s", currentPath);
     Tcl_Eval(interp, command, 0, (char **) NULL);
 
-    if ( dfd == NULL )
-    {
-	fprintf(stderr, "TRIED TO LIST NULL DIRECTORY\n");
+    if (dfd == NULL) {
+        fprintf(stderr, "TRIED TO LIST NULL DIRECTORY\n");
 
-	return TCL_OK;
+        return TCL_OK;
     }
 
-/* check if root directory */
-    if ( strlen(currentPath) != 1 )
-    {
-	sprintf(fileName[fileCount], "../");
-	dirList[fileCount] = TRUE;
-	fileCount++;
+    /* check if root directory */
+    if (strlen(currentPath) != 1) {
+        sprintf(fileName[fileCount], "../");
+        dirList[fileCount] = TRUE;
+        ++fileCount;
     }
 
     strcpy(fullName, currentPath);
     restPtr = &fullName[strlen(fullName)];
 
-    while ( (dp = readdir(dfd)) != NULL )
-    {
-	strcpy(restPtr, dp->d_name);
-	stat(fullName, &stbuf);
-
-	if ( dp->d_name[0] != '.' )
-	{
-	    if ( S_ISDIR(stbuf.st_mode) )
-	    {
-		sprintf(fileName[fileCount], "%s/", dp->d_name);
-		dirList[fileCount] = TRUE;
-		fileCount++;
-	    }
-	    else
-	    {
-		if ( MatchesGlob(dp->d_name, globString) )
-		{
-		    strcpy(fileName[fileCount], dp->d_name);
-		    dirList[fileCount] = FALSE;
-		    fileCount++;
-		}
-	    }
-	}
+    while ((dp = readdir(dfd)) != NULL) {
+        strcpy(restPtr, dp->d_name);
+        stat(fullName, &stbuf);
+        
+        if (dp->d_name[0] != '.') {
+            if (S_ISDIR(stbuf.st_mode)) {
+                sprintf(fileName[fileCount], "%s/", dp->d_name);
+                dirList[fileCount] = TRUE;
+                ++fileCount;
+            } else {
+                if (MatchesGlob(dp->d_name, globString)) {
+                    strcpy(fileName[fileCount], dp->d_name);
+                    dirList[fileCount] = FALSE;
+                    ++fileCount;
+                }
+            }
+        }
     }
 
     SortFiles(fileCount, fileName, dirList, permute);
 
-    for ( index = 0; index < fileCount; index++ )
-    {
-	sprintf(command, "AddBrowseFile %s", fileName[permute[index]]);
-	Tcl_Eval(interp, command, 0, (char **) NULL);
+    for (index = 0; index < fileCount; ++index) {
+        sprintf(command, "AddBrowseFile %s", fileName[permute[index]]);
+        Tcl_Eval(interp, command, 0, (char **) NULL);
     }
 
     closedir(dfd);
@@ -214,108 +193,110 @@ int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc,
 }
 
 
-void	SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN],
-		  boolean *dirList, int permute[])
-{
-    register int i, j;
-    int temp;
-    int	numDirs;
-    int	ptr;
 
-    for ( i = 0; i < numStrings; i++ )
-	permute[i] = i;
+void
+SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN],
+          boolean *dirList, int permute[]) {
+
+    int i;
+    int numDirs;
+    int ptr;
+
+    for (i = 0; i < numStrings; ++i)
+        permute[i] = i;
 
     /* put all directories at front */
     numDirs = 0;
     ptr = numStrings-1;
-    while ( numDirs != ptr )
-    {
-	/* go past dirs */
-	while ( (numDirs < ptr) && (dirList[permute[numDirs]]) )
-	    numDirs++;
-
-	/* go past non-dirs */
-	while ( (numDirs < ptr) && (! dirList[permute[ptr]]) )
-	    ptr--;
-
-	if ( numDirs != ptr )
-	{
-	    temp = permute[numDirs];
-	    permute[numDirs] = ptr;
-	    permute[ptr] = temp;
-	}
+    while (numDirs != ptr) {
+        /* go past dirs */
+        while ((numDirs < ptr) && (dirList[permute[numDirs]]))
+            ++numDirs;
+
+        /* go past non-dirs */
+        while ((numDirs < ptr) && (! dirList[permute[ptr]]))
+            --ptr;
+
+        if (numDirs != ptr) {
+            int const temp = permute[numDirs];
+            permute[numDirs] = ptr;
+            permute[ptr] = temp;
+        }
     }
 
-    if ( dirList[permute[numDirs]] )
-	numDirs++;
-
-    for ( i = 0; i < numDirs; i++ )
-	for ( j = i+1; j < numDirs; j++ )
-	{
-	    if ( strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0 )
-	    {
-		temp = permute[j];
-		permute[j] = permute[i];
-		permute[i] = temp;
-	    }
-	}
-
-    for ( i = numDirs; i < numStrings; i++ )
-	for ( j = i+1; j < numStrings; j++ )
-	{
-	    if ( strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0 )
-	    {
-		temp = permute[j];
-		permute[j] = permute[i];
-		permute[i] = temp;
-	    }
-	}
+    if (dirList[permute[numDirs]])
+        ++numDirs;
+
+    for (i = 0; i < numDirs; ++i) {
+        int j;
+        for (j = i + 1; j < numDirs; ++j) {
+            if (strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0) {
+                int const temp = permute[j];
+                permute[j] = permute[i];
+                permute[i] = temp;
+            }
+        }
+    }
+    for (i = numDirs; i < numStrings; ++i) {
+        int j;
+        for (j = i + 1; j < numStrings; ++j) {
+            if (strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0) {
+                int const temp = permute[j];
+                permute[j] = permute[i];
+                permute[i] = temp;
+            }
+        }
+    }
 }
 
 
-int SetBrowseGlob (ClientData nulldata, Tcl_Interp *interp,
-		   int argc, char **argv)
-{
-    if (argc == 2 )
-    {
-	strcpy(globString, argv[1]);
 
-	fprintf(stdout, "GLOB:  %s\n", globString);
+int
+SetBrowseGlob(ClientData nulldata, Tcl_Interp *interp,
+              int argc, char **argv) {
+
+    if (argc == 2) {
+        strcpy(globString, argv[1]);
+
+        fprintf(stdout, "GLOB:  %s\n", globString);
 
-	return TCL_OK;
+        return TCL_OK;
     }
 
-	Tcl_AppendResult (interp, 
-            "wrong args: should be \"", argv[0]," string\"", (char *) NULL);
-	return TCL_ERROR;
+    Tcl_AppendResult(interp, 
+                     "wrong args: should be \"", argv[0]," string\"",
+                     NULL);
+    return TCL_ERROR;
 }
 
 
-static boolean	MatchesGlob(char *string, char *glob)
-{
-    char    *stringRight, *globRight;
 
-    while ( (*glob != '\0') && (*glob != '*') )	    /* match left side */
-    {
-	if ( (*string == '\0') || (*string != *glob) )
-	    return FALSE;
-	string++;
-	glob++;
+static boolean
+MatchesGlob(char *string, char *glob) {
+
+    char * stringRight;
+    char * globRight;
+
+    while ((*glob != '\0') && (*glob != '*')) {
+        /* match left side */
+        if ((*string == '\0') || (*string != *glob))
+            return FALSE;
+        ++string;
+        ++glob;
     }
 
-    if ( *glob == '\0' )	/* no star */
-	return TRUE;
+    if (*glob == '\0')    /* no star */
+        return TRUE;
 
     /* now match right side */
     stringRight = &string[strlen(string)-1];
     globRight = &glob[strlen(glob)-1];
 
-    while ( *globRight != '*' )
-    {
-	if ( (stringRight < string) || (*stringRight != *globRight) )
-	    return FALSE;
-	globRight--;
-	stringRight--;
+    while (*globRight != '*') {
+        if ((stringRight < string) || (*stringRight != *globRight))
+            return FALSE;
+        --globRight;
+        --stringRight;
     }
 
     return TRUE;
diff --git a/converter/ppm/ppmtompeg/frames.c b/converter/ppm/ppmtompeg/frames.c
new file mode 100644
index 00000000..a0764890
--- /dev/null
+++ b/converter/ppm/ppmtompeg/frames.c
@@ -0,0 +1,58 @@
+#include "mallocvar.h"
+#include "fsize.h"
+
+#include "frames.h"
+
+
+Block **dct=NULL, **dctr=NULL, **dctb=NULL;
+dct_data_type   **dct_data; /* used in p/bframe.c */
+
+
+/*===========================================================================*
+ *
+ * AllocDctBlocks
+ *
+ *  allocate memory for dct blocks
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    creates dct, dctr, dctb
+ *
+ *===========================================================================*/
+void
+AllocDctBlocks(void) {
+
+    int dctx, dcty;
+    int i;
+
+    dctx = Fsize_x / DCTSIZE;
+    dcty = Fsize_y / DCTSIZE;
+
+    MALLOCARRAY(dct, dcty);
+    ERRCHK(dct, "malloc");
+    for (i = 0; i < dcty; ++i) {
+        dct[i] = (Block *) malloc(sizeof(Block) * dctx);
+        ERRCHK(dct[i], "malloc");
+    }
+
+    MALLOCARRAY(dct_data, dcty);
+    ERRCHK(dct_data, "malloc");
+    for (i = 0; i < dcty; ++i) {
+        MALLOCARRAY(dct_data[i], dctx);
+        ERRCHK(dct[i], "malloc");
+    }
+
+    MALLOCARRAY(dctr, dcty/2);
+    ERRCHK(dctr, "malloc");
+    MALLOCARRAY(dctb, dcty/2);
+    ERRCHK(dctb, "malloc");
+    for (i = 0; i < dcty/2; ++i) {
+        MALLOCARRAY(dctr[i], dctx/2);
+        ERRCHK(dctr[i], "malloc");
+        MALLOCARRAY(dctb[i], dctx/2);
+        ERRCHK(dctb[i], "malloc");
+    }
+}
+
+
+
diff --git a/converter/ppm/ppmtompeg/gethostname_win32.c b/converter/ppm/ppmtompeg/gethostname_win32.c
new file mode 100644
index 00000000..383f4e55
--- /dev/null
+++ b/converter/ppm/ppmtompeg/gethostname_win32.c
@@ -0,0 +1,404 @@
+/* define this macro for activating debugging version */
+/* #define GETHOSTNAME_LOCAL_DEBUG     1*/
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdarg.h>
+
+#ifndef GETHOSTNAME_LOCAL_DEBUG
+#include "pm.h"
+#include "gethostname.h"
+#endif
+
+#define BUFSIZE 80
+
+typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
+typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
+
+typedef struct {
+    char  str[256];
+    int   level;
+} push_string_t;
+
+static void
+pushString(push_string_t *p, const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    p->level += _vsnprintf(p->str + p->level, sizeof(p->str)-p->level, fmt, args);
+    va_end(args);
+}
+
+#if _WIN32_WINNT < 0x0600
+/*
+ * Reference available here:
+ *
+ * GetProductInfo() Function
+ * http://msdn2.microsoft.com/en-us/library/ms724358.aspx
+ */
+#define PRODUCT_BUSINESS                        0x00000006  /* Business Edition */
+#define PRODUCT_BUSINESS_N                      0x00000010  /* Business Edition */
+#define PRODUCT_CLUSTER_SERVER                  0x00000012  /* Cluster Server Edition */
+#define PRODUCT_DATACENTER_SERVER               0x00000008  /* Server Datacenter Edition (full installation) */
+#define PRODUCT_DATACENTER_SERVER_CORE          0x0000000C  /* Server Datacenter Edition (core installation) */
+#define PRODUCT_ENTERPRISE                      0x00000004  /* Enterprise Edition */
+#define PRODUCT_ENTERPRISE_N                    0x0000001B  /* Enterprise Edition */
+#define PRODUCT_ENTERPRISE_SERVER               0x0000000A  /* Server Enterprise Edition (full installation) */
+#define PRODUCT_ENTERPRISE_SERVER_CORE          0x0000000E  /* Server Enterprise Edition (core installation) */
+#define PRODUCT_ENTERPRISE_SERVER_IA64          0x0000000F  /* Server Enterprise Edition for Itanium-based Systems */
+#define PRODUCT_HOME_BASIC                      0x00000002  /* Home Basic Edition */
+#define PRODUCT_HOME_BASIC_N                    0x00000005  /* Home Basic Edition */
+#define PRODUCT_HOME_PREMIUM                    0x00000003  /* Home Premium Edition */
+#define PRODUCT_HOME_PREMIUM_N                  0x0000001A  /* Home Premium Edition */
+#define PRODUCT_HOME_SERVER                     0x00000013  /* Home Server Edition */
+#define PRODUCT_SERVER_FOR_SMALLBUSINESS        0x00000018  /* Server for Small Business Edition */
+#define PRODUCT_SMALLBUSINESS_SERVER            0x00000009  /* Small Business Server */
+#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM    0x00000019  /* Small Business Server Premium Edition */
+#define PRODUCT_STANDARD_SERVER                 0x00000007  /* Server Standard Edition (full installation) */
+#define PRODUCT_STANDARD_SERVER_CORE            0x0000000D  /* Server Standard Edition (core installation) */
+#define PRODUCT_STARTER                         0x0000000B  /* Starter Edition */
+#define PRODUCT_STORAGE_ENTERPRISE_SERVER       0x00000017  /* Storage Server Enterprise Edition */
+#define PRODUCT_STORAGE_EXPRESS_SERVER          0x00000014  /* Storage Server Express Edition */
+#define PRODUCT_STORAGE_STANDARD_SERVER         0x00000015  /* Storage Server Standard Edition */
+#define PRODUCT_STORAGE_WORKGROUP_SERVER        0x00000016  /* Storage Server Workgroup Edition */
+#define PRODUCT_UNDEFINED                       0x00000000  /* An unknown product */
+#define PRODUCT_ULTIMATE                        0x00000001  /* Ultimate Edition */
+#define PRODUCT_ULTIMATE_N                      0x0000001C  /* Ultimate Edition */
+#define PRODUCT_WEB_SERVER                      0x00000011  /* Web Server Edition (full installation) */
+#define PRODUCT_WEB_SERVER_CORE                 0x0000001D  /* Web Server Edition (core installation) */
+#endif
+
+static BOOL
+get_string_version(push_string_t *str)
+{
+    OSVERSIONINFOEX osvi;
+    SYSTEM_INFO si;
+    PGPI pGPI;
+    PGNSI pGNSI;
+    BOOL bOsVersionInfoEx;
+    DWORD dwType;
+
+    ZeroMemory(&si, sizeof(SYSTEM_INFO));
+    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+
+    /*
+     * Try calling GetVersionEx using the OSVERSIONINFOEX structure.
+     * If that fails, try using the OSVERSIONINFO structure.
+     */
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+    if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
+    {
+        osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+        if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) 
+            return FALSE;
+    }
+
+    /* Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. */
+    pGNSI = (PGNSI)
+            GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), 
+            "GetNativeSystemInfo");
+    if (NULL != pGNSI)
+        pGNSI(&si);
+    else
+        GetSystemInfo(&si);
+
+    switch (osvi.dwPlatformId)
+    {
+    /* Test for the Windows NT product family. */
+    case VER_PLATFORM_WIN32_NT:
+        /* Test for the specific product. */
+        if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
+        {
+            if (osvi.wProductType == VER_NT_WORKSTATION)
+                pushString(str, "Windows Vista ");
+            else
+                pushString(str, "Windows Server 2008 ");
+
+            pGPI = (PGPI) GetProcAddress(
+                GetModuleHandle(TEXT("kernel32.dll")),
+                "GetProductInfo");
+
+            pGPI( 6, 0, 0, 0, &dwType);
+            switch (dwType)
+            {
+            case PRODUCT_ULTIMATE:
+                pushString(str, "Ultimate Edition");
+                break;
+            case PRODUCT_HOME_PREMIUM:
+                pushString(str, "Home Premium Edition");
+                break;
+            case PRODUCT_HOME_BASIC:
+                pushString(str, "Home Basic Edition");
+                break;
+            case PRODUCT_ENTERPRISE:
+                pushString(str, "Enterprise Edition");
+                break;
+            case PRODUCT_BUSINESS:
+                pushString(str, "Business Edition");
+                break;
+            case PRODUCT_STARTER:
+                pushString(str, "Starter Edition");
+                break;
+            case PRODUCT_CLUSTER_SERVER:
+                pushString(str, "Cluster Server Edition");
+                break;
+            case PRODUCT_DATACENTER_SERVER:
+                pushString(str, "Datacenter Edition");
+                break;
+            case PRODUCT_DATACENTER_SERVER_CORE:
+                pushString(str, "Datacenter Edition (core installation)");
+                break;
+            case PRODUCT_ENTERPRISE_SERVER:
+                pushString(str, "Enterprise Edition");
+                break;
+            case PRODUCT_ENTERPRISE_SERVER_CORE:
+                pushString(str, "Enterprise Edition (core installation)");
+                break;
+            case PRODUCT_ENTERPRISE_SERVER_IA64:
+                pushString(str, "Enterprise Edition for Itanium-based Systems");
+                break;
+            case PRODUCT_SMALLBUSINESS_SERVER:
+                pushString(str, "Small Business Server");
+                break;
+            case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+                pushString(str, "Small Business Server Premium Edition");
+                break;
+            case PRODUCT_STANDARD_SERVER:
+                pushString(str, "Standard Edition");
+                break;
+            case PRODUCT_STANDARD_SERVER_CORE:
+                pushString(str, "Standard Edition (core installation)");
+                break;
+            case PRODUCT_WEB_SERVER:
+                pushString(str, "Web Server Edition");
+                break;
+            }
+            if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
+                pushString(str,  ", 64-bit");
+            else
+            if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL)
+                pushString(str, ", 32-bit");
+            else
+                /* space for optional build number */
+                pushString(str, " ");
+        }
+        else
+        if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
+        {
+            if( GetSystemMetrics(SM_SERVERR2) )
+                pushString(str, "Microsoft Windows Server 2003 \"R2\" ");
+            else
+            if ( osvi.wSuiteMask==VER_SUITE_STORAGE_SERVER )
+                pushString(str, "Windows Storage Server 2003 ");
+            else
+            if( osvi.wProductType == VER_NT_WORKSTATION &&
+                si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
+                pushString(str, "Microsoft Windows XP Professional x64 Edition ");
+            else
+                pushString(str, "Microsoft Windows Server 2003, ");
+
+            /* Test for the server type. */
+            if ( osvi.wProductType != VER_NT_WORKSTATION )
+            {
+                switch (si.wProcessorArchitecture)
+                {
+                case PROCESSOR_ARCHITECTURE_IA64:
+                    if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+                       pushString(str, "Datacenter Edition for Itanium-based Systems ");
+                    else
+                    if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                       pushString(str, "Enterprise Edition for Itanium-based Systems ");
+                    break;
+
+                case PROCESSOR_ARCHITECTURE_AMD64:
+                    if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+                        pushString(str, "Datacenter x64 Edition ");
+                    else
+                    if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                        pushString(str, "Enterprise x64 Edition ");
+                    else
+                        pushString(str, "Standard x64 Edition ");
+                    break;
+
+                default:
+                    if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
+                        pushString(str, "Compute Cluster Edition ");
+                    else
+                    if ( osvi.wSuiteMask & VER_SUITE_DATACENTER)
+                        pushString(str, "Datacenter Edition ");
+                    else
+                    if ( osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                        pushString(str, "Enterprise Edition ");
+                    else
+                    if ( osvi.wSuiteMask & VER_SUITE_BLADE)
+                        pushString(str, "Web Edition ");
+                    else
+                        pushString(str, "Standard Edition ");
+                    break;
+                }
+            }
+        }
+        else
+        if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
+        {
+            pushString(str, "Microsoft Windows XP ");
+            if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
+                pushString(str, "Home Edition ");
+            else
+                pushString(str, "Professional ");
+        }
+        else
+        if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
+        {
+            pushString(str, "Microsoft Windows 2000 ");
+            if (osvi.wProductType == VER_NT_WORKSTATION)
+                pushString(str, "Professional ");
+            else 
+            if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+                pushString(str, "Datacenter Server ");
+            else
+            if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                pushString(str, "Advanced Server ");
+            else
+                pushString(str, "Server ");
+        } else
+        if ( osvi.dwMajorVersion <= 4 )
+            pushString(str, "Microsoft Windows NT ");
+
+        /* Test for specific product on Windows NT 4.0 SP6 and later. */
+        if (bOsVersionInfoEx)
+        {
+            /* Test for the workstation type. */
+            switch (osvi.wProductType)
+            {
+            case VER_NT_WORKSTATION:
+                if (si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64 &&
+                    osvi.dwMajorVersion == 4)
+                    pushString(str, "Workstation 4.0 ");
+                break;
+
+            case VER_NT_SERVER:
+            case VER_NT_DOMAIN_CONTROLLER:
+                if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                    pushString(str, "Server 4.0, Enterprise Edition ");
+                else
+                    pushString(str, "Server 4.0 ");
+                break;
+            }
+        }
+        /* Test for specific product on Windows NT 4.0 SP5 and earlier */
+        else  
+        {
+            HKEY hKey;
+            TCHAR szProductType[BUFSIZE];
+            DWORD dwBufLen=BUFSIZE*sizeof(TCHAR);
+            LONG lRet;
+
+            lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
+                0, KEY_QUERY_VALUE, &hKey);
+            if (lRet != ERROR_SUCCESS)
+                return FALSE;
+
+            lRet = RegQueryValueEx(hKey, TEXT("ProductType"), NULL, NULL,
+                (LPBYTE) szProductType, &dwBufLen);
+            RegCloseKey( hKey );
+
+            if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE*sizeof(TCHAR)))
+                return FALSE;
+
+            if (lstrcmpi(TEXT("WINNT"), szProductType) == 0)
+                pushString(str, "Workstation ");
+            else
+            if (lstrcmpi(TEXT("LANMANNT"), szProductType) == 0)
+                pushString(str, "Server ");
+            else
+            if (lstrcmpi( TEXT("SERVERNT"), szProductType) == 0)
+                pushString(str, "Advanced Server ");
+            else
+                pushString(str, "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion);
+        }
+
+        /* Display service pack (if any) and build number. */
+        if (osvi.dwMajorVersion == 4 && 
+            lstrcmpi(osvi.szCSDVersion, TEXT("Service Pack 6")) == 0)
+        { 
+            HKEY hKey;
+            LONG lRet;
+
+            /* Test for SP6 versus SP6a. */
+            lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+                TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"),
+                0, KEY_QUERY_VALUE, &hKey );
+            if( lRet == ERROR_SUCCESS )
+                pushString(str, "Service Pack 6a (Build %d)\n", osvi.dwBuildNumber & 0xFFFF );         
+            else
+                /* Windows NT 4.0 prior to SP6a */
+                pushString(str, "%s (Build %d)\n", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
+
+             RegCloseKey( hKey );
+        }
+        else /* not Windows NT 4.0 */
+            pushString(str, "%s (Build %d)\n", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
+
+        break;
+
+    /* Test for the Windows Me/98/95. */
+    case VER_PLATFORM_WIN32_WINDOWS:
+        if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
+        {
+            pushString(str, "Microsoft Windows 95");
+            if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
+                pushString(str, " OSR2");
+        }
+        else
+        if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
+        {
+            pushString(str, "Microsoft Windows 98");
+            if (osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
+                pushString(str, " SE");
+        } 
+        else
+        if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
+            pushString(str, "Microsoft Windows Millennium Edition\n");
+        break;
+
+    case VER_PLATFORM_WIN32s:
+        pushString(str, "Microsoft Win32s\n");
+        break;
+    }
+    return TRUE; 
+}
+
+const char *
+GetHostName(void)
+{
+/*----------------------------------------------------------------------------
+   Return the host name of this system.
+-----------------------------------------------------------------------------*/
+    push_string_t str;
+
+    ZeroMemory(&str, sizeof(str));
+    if (!get_string_version(&str)) {
+#ifndef GETHOSTNAME_LOCAL_DEBUG
+        pm_error("Unable to find out host name.");
+#endif
+        pushString(&str, "unknown");
+    }
+    return (const char *)_strdup(str.str);
+}
+
+#ifdef GETHOSTNAME_LOCAL_DEBUG
+int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
+                   LPSTR lpsCmdLine, int nCmdShow)
+{
+    char *hostName = (char *)GetHostName();
+
+    /* compile as ascii only (not UNICODE) */
+    MessageBox(NULL, hostName, TEXT("GetHostName"), MB_OK);
+    free(hostName);
+
+    return 0;
+}
+#endif
diff --git a/converter/ppm/ppmtompeg/headers/bitio.h b/converter/ppm/ppmtompeg/headers/bitio.h
index 89e61fbb..a24c21cd 100644
--- a/converter/ppm/ppmtompeg/headers/bitio.h
+++ b/converter/ppm/ppmtompeg/headers/bitio.h
@@ -60,9 +60,7 @@
 #define BIT_IO_INCLUDED
 
 
-/*==============*
- * HEADER FILES *
- *==============*/
+#include <stdio.h>
 
 #include "general.h"
 #include "ansi.h"
diff --git a/converter/ppm/ppmtompeg/headers/block.h b/converter/ppm/ppmtompeg/headers/block.h
index 46050492..22d306a1 100644
--- a/converter/ppm/ppmtompeg/headers/block.h
+++ b/converter/ppm/ppmtompeg/headers/block.h
@@ -1,3 +1,46 @@
+#ifndef BLOCK_H_INCLUDED
+
+#include "frame.h"
+#include "mtypes.h"
+
+/* DIFFERENCE FUNCTIONS */
+
+int32
+LumBlockMAD(const LumBlock * const currentBlockP,
+            const LumBlock * const motionBlockP,
+            int32            const bestSoFar);
+
+int32
+LumBlockMSE(const LumBlock * const currentBlockP,
+            const LumBlock * const motionBlockP,
+            int32            const bestSoFar);
+
+int32
+LumMotionError(const LumBlock * const currentBlockP,
+               MpegFrame *      const prev,
+               int              const by,
+               int              const bx,
+               vector           const m,
+               int32            const bestSoFar);
+
+int32
+LumAddMotionError(const LumBlock * const currentBlockP,
+                  const LumBlock * const blockSoFarP,
+                  MpegFrame *      const prev,
+                  int              const by,
+                  int              const bx,
+                  vector           const m,
+                  int32            const bestSoFar);
+
+int32
+LumMotionErrorSubSampled(const LumBlock * const currentBlockP,
+                         MpegFrame *      const prevFrame,
+                         int              const by,
+                         int              const bx,
+                         vector           const m,
+                         int              const startY,
+                         int              const startX);
+
 void
 ComputeDiffDCTs(MpegFrame * const current,
                 MpegFrame * const prev,
@@ -51,3 +94,4 @@ AddBMotionBlock(Block          block,
 void
 BlockifyFrame(MpegFrame * const frameP);
 
+#endif
diff --git a/converter/ppm/ppmtompeg/headers/byteorder.h b/converter/ppm/ppmtompeg/headers/byteorder.h
index 0070252a..e2d8030c 100644
--- a/converter/ppm/ppmtompeg/headers/byteorder.h
+++ b/converter/ppm/ppmtompeg/headers/byteorder.h
@@ -72,6 +72,8 @@
 #else
     /* let in.h handle it, if possible */		   
 #include <sys/types.h>
+#if !defined(WIN32) || defined(__CYGWIN__)
 #include <netinet/in.h>
+#endif
 #endif /* FORCE_LITTLE_ENDIAN */
 #endif /* FORCE_BIG_ENDIAN */
diff --git a/converter/ppm/ppmtompeg/headers/frame.h b/converter/ppm/ppmtompeg/headers/frame.h
index 6df3d19f..acd74419 100644
--- a/converter/ppm/ppmtompeg/headers/frame.h
+++ b/converter/ppm/ppmtompeg/headers/frame.h
@@ -130,18 +130,4 @@ Frame_Resize(MpegFrame * const omf,
              int         const outsize_x,
              int         const outsize_y);
 
-
-extern void	  Frame_Free _ANSI_ARGS_((MpegFrame * const frame));
-extern void	  Frame_Exit _ANSI_ARGS_((void));
-extern void	  Frame_AllocPPM _ANSI_ARGS_((MpegFrame * frame));
-extern void	  Frame_AllocYCC _ANSI_ARGS_((MpegFrame * const mf));
-extern void	  Frame_AllocDecoded _ANSI_ARGS_((MpegFrame * const frame,
-						  boolean const makeReference));
-extern void	  Frame_AllocHalf _ANSI_ARGS_((MpegFrame * const frame));
-extern void	  Frame_AllocBlocks _ANSI_ARGS_((MpegFrame * const mf));
-extern void	  Frame_Resize _ANSI_ARGS_((MpegFrame * const omf, MpegFrame * const mf,
-					    int const insize_x, int const insize_y,
-					    int const outsize_x, int const outsize_y));
-
-
-#endif /* FRAME_INCLUDED */
+#endif
diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h
index 14304c48..f2bcf6ae 100644
--- a/converter/ppm/ppmtompeg/headers/frames.h
+++ b/converter/ppm/ppmtompeg/headers/frames.h
@@ -16,6 +16,7 @@
 #include "ansi.h"
 #include "mtypes.h"
 #include "mheaders.h"
+#include "iframe.h"
 #include "frame.h"
 
 
@@ -86,11 +87,13 @@ typedef struct dct_data_tye_struct {
   int fmotionX, fmotionY, bmotionX, bmotionY;
 } dct_data_type;
 
-void    EncodeYDC _ANSI_ARGS_((int32 const dc_term, int32 * const pred_term, BitBucket * const bb));
-void
-EncodeCDC(int32       const dc_term,
-          int32     * const pred_term,
-          BitBucket * const bb);
+
+/*==================*
+ * GLOBAL VARIABLES *
+ *==================*/
+
+extern Block    **dct, **dctr, **dctb;
+extern dct_data_type **dct_data;
 
 
 /*========*
@@ -101,63 +104,6 @@ EncodeCDC(int32       const dc_term,
 #define int_ceil_div(a,b,c)     ((b*(c = a/b) < a) ? (c+1) : c)
 #define int_floor_div(a,b,c)    ((b*(c = a/b) > a) ? (c-1) : c)
 
-/* assumes many things:
- * block indices are (y,x)
- * variables y_dc_pred, cr_dc_pred, and cb_dc_pred
- * flat block fb exists
- */
-#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) {                   \
-    boolean overflow, overflowChange=FALSE;                             \
-        int overflowValue = 0;                                              \
-        do {                                                                \
-      overflow =  Mpost_QuantZigBlock(dct[y][x], fb[0],                 \
-             qscale, TRUE)==MPOST_OVERFLOW;                     \
-          overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1],               \
-                 qscale, TRUE)==MPOST_OVERFLOW;                     \
-      overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2],               \
-                         qscale, TRUE)==MPOST_OVERFLOW;                     \
-      overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3],             \
-                         qscale, TRUE)==MPOST_OVERFLOW;                     \
-      overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1],             \
-                         fb[4], qscale, TRUE)==MPOST_OVERFLOW;              \
-      overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1],             \
-             fb[5], qscale, TRUE)==MPOST_OVERFLOW;              \
-          if ((overflow) && (qscale!=31)) {                                 \
-           overflowChange = TRUE; overflowValue++;                          \
-       qscale++;                                                        \
-       } else overflow = FALSE;                                         \
-    } while (overflow);                                                 \
-        Mhead_GenMBHeader(bb,                           \
-            frameType /* pict_code_type */, mbAI /* addr_incr */,   \
-            qscale /* q_scale */,                               \
-            0 /* forw_f_code */, 0 /* back_f_code */,           \
-            0 /* horiz_forw_r */, 0 /* vert_forw_r */,          \
-            0 /* horiz_back_r */, 0 /* vert_back_r */,          \
-            0 /* motion_forw */, 0 /* m_horiz_forw */,          \
-            0 /* m_vert_forw */, 0 /* motion_back */,           \
-            0 /* m_horiz_back */, 0 /* m_vert_back */,          \
-            0 /* mb_pattern */, TRUE /* mb_intra */);           \
-                                        \
-    /* Y blocks */                              \
-        EncodeYDC(fb[0][0], &y_dc_pred, bb);                            \
-    Mpost_RLEHuffIBlock(fb[0], bb);                         \
-    EncodeYDC(fb[1][0], &y_dc_pred, bb);                        \
-        Mpost_RLEHuffIBlock(fb[1], bb);                             \
-    EncodeYDC(fb[2][0], &y_dc_pred, bb);                        \
-    Mpost_RLEHuffIBlock(fb[2], bb);                         \
-    EncodeYDC(fb[3][0], &y_dc_pred, bb);                        \
-    Mpost_RLEHuffIBlock(fb[3], bb);                         \
-                                        \
-    /* CB block */                              \
-    EncodeCDC(fb[4][0], &cb_dc_pred, bb);                   \
-    Mpost_RLEHuffIBlock(fb[4], bb);                     \
-                                        \
-    /* CR block */                              \
-    EncodeCDC(fb[5][0], &cr_dc_pred, bb);                   \
-    Mpost_RLEHuffIBlock(fb[5], bb);                     \
-    if (overflowChange) qscale -= overflowValue;                        \
-    }
-
 #define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) {    \
     x1 = (bx1)*DCTSIZE;             \
     x2 = (bx2)*DCTSIZE;             \
@@ -254,6 +200,9 @@ encodeMotionVector(int      const x,
  *===============================*/
 
 void
+AllocDctBlocks(void);
+
+void
 ComputeBMotionLumBlock(MpegFrame * const prev,
                        MpegFrame * const next,
                        int         const by,
@@ -271,8 +220,6 @@ BMotionSearch(const LumBlock * const currentBlockP,
               motion *         const motionP,
               int              const oldMode);
 
-void GenIFrame (BitBucket * const bb,
-                MpegFrame * const mf);
 void GenPFrame (BitBucket * const bb,
                 MpegFrame * const current,
                 MpegFrame * const prev);
@@ -280,11 +227,6 @@ void GenBFrame (BitBucket * const bb,
                 MpegFrame * const curr,
                 MpegFrame * const prev,
                 MpegFrame * const next);
-void    AllocDctBlocks _ANSI_ARGS_((void ));
-
-
-float
-IFrameTotalTime(void);
 
 float
 PFrameTotalTime(void);
@@ -293,11 +235,6 @@ float
 BFrameTotalTime(void);
 
 void
-ShowIFrameSummary(unsigned int const inputFrameBits, 
-                  unsigned int const totalBits, 
-                  FILE *       const fpointer);
-
-void
 ShowPFrameSummary(unsigned int const inputFrameBits, 
                   unsigned int const totalBits, 
                   FILE *       const fpointer);
@@ -307,87 +244,6 @@ ShowBFrameSummary(unsigned int const inputFrameBits,
                   unsigned int const totalBits, 
                   FILE *       const fpointer);
 
-/* DIFFERENCE FUNCTIONS */
-
-int32
-LumBlockMAD(const LumBlock * const currentBlockP,
-            const LumBlock * const motionBlockP,
-            int32            const bestSoFar);
-
-int32
-LumBlockMSE(const LumBlock * const currentBlockP,
-            const LumBlock * const motionBlockP,
-            int32            const bestSoFar);
-
-int32
-LumMotionError(const LumBlock * const currentBlockP,
-               MpegFrame *      const prev,
-               int              const by,
-               int              const bx,
-               vector           const m,
-               int32            const bestSoFar);
-
-int32
-LumAddMotionError(const LumBlock * const currentBlockP,
-                  const LumBlock * const blockSoFarP,
-                  MpegFrame *      const prev,
-                  int              const by,
-                  int              const bx,
-                  vector           const m,
-                  int32            const bestSoFar);
-
-int32
-LumMotionErrorA(const LumBlock * const currentBlockP,
-                MpegFrame *      const prevFrame,
-                int              const by,
-                int              const bx,
-                vector           const m,
-                int32            const bestSoFar);
-
-int32
-LumMotionErrorB(const LumBlock * const currentP,
-                MpegFrame *      const prevFrame,
-                int              const by,
-                int              const bx,
-                vector           const m,
-                int32            const bestSoFar);
-
-int32
-LumMotionErrorC(const LumBlock * const currentP,
-                MpegFrame *      const prevFrame,
-                int              const by,
-                int              const bx,
-                vector           const m,
-                int32            const bestSoFar);
-
-int32
-LumMotionErrorD(const LumBlock * const currentP,
-                MpegFrame *      const prevFrame,
-                int              const by,
-                int              const bx,
-                vector           const m,
-                int32            const bestSoFar);
-
-int32
-LumMotionErrorSubSampled(const LumBlock * const currentBlockP,
-                         MpegFrame *      const prevFrame,
-                         int              const by,
-                         int              const bx,
-                         vector           const m,
-                         int              const startY,
-                         int              const startX);
-
-void
-BlockComputeSNR(MpegFrame * const current,
-                float *     const snr,
-                float *     const psnr);
-
-int32
-time_elapsed(void);
-
-void
-AllocDctBlocks(void);
-
 /*==================*
  * GLOBAL VARIABLES *
  *==================*/
@@ -399,7 +255,7 @@ extern int gopSize;
 extern int slicesPerFrame;
 extern int blocksPerSlice;
 extern int referenceFrame;
-extern int specificsOn;
+extern boolean specificsOn;
 extern int quietTime;       /* shut up for at least quietTime seconds;
                  * negative means shut up forever
                  */
@@ -413,7 +269,7 @@ extern int  fCodeI,fCodeP,fCodeB;
 extern boolean    forceEncodeLast;
 extern int TIME_RATE;
 
-#endif /* FRAMES_INCLUDED */
+#endif
 
 
 /*
diff --git a/converter/ppm/ppmtompeg/headers/iframe.h b/converter/ppm/ppmtompeg/headers/iframe.h
new file mode 100644
index 00000000..c4f77c74
--- /dev/null
+++ b/converter/ppm/ppmtompeg/headers/iframe.h
@@ -0,0 +1,118 @@
+#ifndef IFRAME_H_INCLUDED
+#define IFRAME_H_INCLUDED
+
+#include "frame.h"
+
+void
+SetFCode(void);
+
+void
+SetSlicesPerFrame(int const number);
+
+void
+SetBlocksPerSlice(void);
+
+void
+SetIQScale(int const qI);
+
+int
+GetIQScale(void);
+
+void
+GenIFrame(BitBucket * const bb, 
+          MpegFrame * const current);
+
+void
+ResetIFrameStats(void);
+
+float
+IFrameTotalTime(void);
+
+
+void
+ShowIFrameSummary(unsigned int const inputFrameBits, 
+                  unsigned int const totalBits, 
+                  FILE *       const fpointer);
+
+void
+EncodeYDC(int32       const dc_term,
+          int32 *     const pred_term,
+          BitBucket * const bb);
+
+void
+EncodeCDC(int32       const dc_term,
+          int32     * const pred_term,
+          BitBucket * const bb);
+
+void
+BlockComputeSNR(MpegFrame * const current,
+                float *     const snr,
+                float *     const psnr);
+
+void
+WriteDecodedFrame(MpegFrame * const frame);
+
+void
+PrintItoIBitRate(int const numBits,
+                 int const frameNum);
+
+int32 time_elapsed(void);
+
+/* assumes many things:
+ * block indices are (y,x)
+ * variables y_dc_pred, cr_dc_pred, and cb_dc_pred
+ * flat block fb exists
+ */
+#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) {                   \
+    boolean overflow, overflowChange=FALSE;                             \
+        int overflowValue = 0;                                              \
+        do {                                                                \
+      overflow =  Mpost_QuantZigBlock(dct[y][x], fb[0],                 \
+             qscale, TRUE)==MPOST_OVERFLOW;                     \
+          overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1],               \
+                 qscale, TRUE)==MPOST_OVERFLOW;                     \
+      overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2],               \
+                         qscale, TRUE)==MPOST_OVERFLOW;                     \
+      overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3],             \
+                         qscale, TRUE)==MPOST_OVERFLOW;                     \
+      overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1],             \
+                         fb[4], qscale, TRUE)==MPOST_OVERFLOW;              \
+      overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1],             \
+             fb[5], qscale, TRUE)==MPOST_OVERFLOW;              \
+          if ((overflow) && (qscale!=31)) {                                 \
+           overflowChange = TRUE; overflowValue++;                          \
+       qscale++;                                                        \
+       } else overflow = FALSE;                                         \
+    } while (overflow);                                                 \
+        Mhead_GenMBHeader(bb,                           \
+            frameType /* pict_code_type */, mbAI /* addr_incr */,   \
+            qscale /* q_scale */,                               \
+            0 /* forw_f_code */, 0 /* back_f_code */,           \
+            0 /* horiz_forw_r */, 0 /* vert_forw_r */,          \
+            0 /* horiz_back_r */, 0 /* vert_back_r */,          \
+            0 /* motion_forw */, 0 /* m_horiz_forw */,          \
+            0 /* m_vert_forw */, 0 /* motion_back */,           \
+            0 /* m_horiz_back */, 0 /* m_vert_back */,          \
+            0 /* mb_pattern */, TRUE /* mb_intra */);           \
+                                        \
+    /* Y blocks */                              \
+        EncodeYDC(fb[0][0], &y_dc_pred, bb);                            \
+    Mpost_RLEHuffIBlock(fb[0], bb);                         \
+    EncodeYDC(fb[1][0], &y_dc_pred, bb);                        \
+        Mpost_RLEHuffIBlock(fb[1], bb);                             \
+    EncodeYDC(fb[2][0], &y_dc_pred, bb);                        \
+    Mpost_RLEHuffIBlock(fb[2], bb);                         \
+    EncodeYDC(fb[3][0], &y_dc_pred, bb);                        \
+    Mpost_RLEHuffIBlock(fb[3], bb);                         \
+                                        \
+    /* CB block */                              \
+    EncodeCDC(fb[4][0], &cb_dc_pred, bb);                   \
+    Mpost_RLEHuffIBlock(fb[4], bb);                     \
+                                        \
+    /* CR block */                              \
+    EncodeCDC(fb[5][0], &cr_dc_pred, bb);                   \
+    Mpost_RLEHuffIBlock(fb[5], bb);                     \
+    if (overflowChange) qscale -= overflowValue;                        \
+    }
+
+#endif
diff --git a/converter/ppm/ppmtompeg/headers/motion_search.h b/converter/ppm/ppmtompeg/headers/motion_search.h
index ab83cbca..62f3abab 100644
--- a/converter/ppm/ppmtompeg/headers/motion_search.h
+++ b/converter/ppm/ppmtompeg/headers/motion_search.h
@@ -100,6 +100,9 @@ PMotionSearch(const LumBlock * const currentBlockP,
               int              const bx, 
               vector *         const motionP);
 
+void
+MotionSearchPreComputation(MpegFrame * const frameP);
+
 /*==================*
  * GLOBAL VARIABLES *
  *==================*/
diff --git a/converter/ppm/ppmtompeg/headers/mpeg.h b/converter/ppm/ppmtompeg/headers/mpeg.h
index 23875c2c..56862c42 100644
--- a/converter/ppm/ppmtompeg/headers/mpeg.h
+++ b/converter/ppm/ppmtompeg/headers/mpeg.h
@@ -90,8 +90,9 @@ void
 ReadDecodedRefFrame(MpegFrame *  const frameP, 
                     unsigned int const frameNumber);
 
-extern void	WriteDecodedFrame _ANSI_ARGS_((MpegFrame * const frame));
-extern void	SetBitRateFileName _ANSI_ARGS_((char *fileName));
+void
+SetBitRateFileName(const char * const fileName);
+
 extern void	SetFrameRate _ANSI_ARGS_((void));
 
 
diff --git a/converter/ppm/ppmtompeg/headers/mproto.h b/converter/ppm/ppmtompeg/headers/mproto.h
index c3b0f4b3..d8fefd84 100644
--- a/converter/ppm/ppmtompeg/headers/mproto.h
+++ b/converter/ppm/ppmtompeg/headers/mproto.h
@@ -74,7 +74,6 @@
 #include "bitio.h"
 
 
-#define DCTSIZE2    DCTSIZE*DCTSIZE
 typedef short DCTELEM;
 typedef DCTELEM DCTBLOCK[DCTSIZE2];
 
@@ -111,9 +110,6 @@ void	ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width,
 boolean	ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer));
 void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf));
 
-void	MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame));
-boolean	PMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev,
-				   int by, int bx, int *motionY, int *motionX));
 void	ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame));
 void mp_validate_size _ANSI_ARGS_((int *x, int *y));
 void AllocYCC _ANSI_ARGS_((MpegFrame * mf));
@@ -126,7 +122,3 @@ void j_rev_dct _ANSI_ARGS_((DCTBLOCK data ));
 void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos ));
 void j_rev_dct _ANSI_ARGS_((DCTBLOCK data ));
 
-/* block.c */
-void	BlockToData _ANSI_ARGS_((uint8 **data, Block block, int by, int bx));
-void	AddMotionBlock _ANSI_ARGS_((Block block, uint8 **prev, int by, int bx,
-		       int my, int mx));
diff --git a/converter/ppm/ppmtompeg/headers/param.h b/converter/ppm/ppmtompeg/headers/param.h
index 31be61ee..c7f57b44 100644
--- a/converter/ppm/ppmtompeg/headers/param.h
+++ b/converter/ppm/ppmtompeg/headers/param.h
@@ -1,30 +1,4 @@
-/*===========================================================================*
- * param.h								     *
- *									     *
- *	reading the parameter file					     *
- *									     *
- *===========================================================================*/
-
-/*
- * Copyright (c) 1995 The Regents of the University of California.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement is
- * hereby granted, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
+/* COPYRIGHT information is at end of file */
 
 #include "pm_c_util.h"
 #include "ansi.h"
@@ -35,14 +9,21 @@
  * CONSTANTS *
  *===========*/
 
-#define MAX_MACHINES	    256
+#define MAX_MACHINES        256
 #ifndef MAXPATHLEN
 #define MAXPATHLEN  1024
 #endif
 
-#define	ENCODE_FRAMES	0
-#define COMBINE_GOPS	1
-#define COMBINE_FRAMES	2
+typedef enum {
+    ENCODE_FRAMES,
+        /* The regular, default function: Input is individual single unencoded
+           frames.
+        */
+    COMBINE_GOPS,
+        /* Input is pre-encoded GOPs */
+    COMBINE_FRAMES
+        /* Input is pre-encoded individual frames */
+} majorProgramFunction;
 
 
 struct params {
@@ -53,9 +34,9 @@ struct params {
 
 
 void
-ReadParamFile(const char *    const fileName, 
-              int             const function,
-              struct params * const paramP);
+ReadParamFile(const char *         const fileName, 
+              majorProgramFunction const function,
+              struct params *      const paramP);
 
 /*==================*
  * GLOBAL VARIABLES *
@@ -63,25 +44,47 @@ ReadParamFile(const char *    const fileName,
 
 /* All this stuff ought to be in a struct param instead */
 
-extern char	outputFileName[256];
-extern int	whichGOP;
+extern char outputFileName[256];
+extern int whichGOP;
 extern int numMachines;
-extern char	machineName[MAX_MACHINES][256];
-extern char	userName[MAX_MACHINES][256];
-extern char	executable[MAX_MACHINES][1024];
-extern char	remoteParamFile[MAX_MACHINES][1024];
-extern boolean	remote[MAX_MACHINES];
-extern char	currentPath[MAXPATHLEN];
-extern char	currentFramePath[MAXPATHLEN];
-extern char	currentGOPPath[MAXPATHLEN];
+extern char machineName[MAX_MACHINES][256];
+extern char userName[MAX_MACHINES][256];
+extern char executable[MAX_MACHINES][1024];
+extern char remoteParamFile[MAX_MACHINES][1024];
+extern boolean remote[MAX_MACHINES];
+extern char currentPath[MAXPATHLEN];
+extern char currentFramePath[MAXPATHLEN];
+extern char currentGOPPath[MAXPATHLEN];
 extern char inputConversion[1024];
 extern char yuvConversion[256];
-extern int  yuvWidth, yuvHeight;
-extern int  realWidth, realHeight;
+extern int yuvWidth, yuvHeight;
+extern int realWidth, realHeight;
 extern char ioConversion[1024];
 extern char slaveConversion[1024];
-extern FILE *bitRateFile;
+extern FILE * bitRateFile;
 extern boolean showBitRatePerFrame;
 extern boolean computeMVHist;
 extern const double VidRateNum[9];
 extern boolean keepTempFiles;
+
+
+/*
+ * Copyright (c) 1995 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
diff --git a/converter/ppm/ppmtompeg/headers/prototypes.h b/converter/ppm/ppmtompeg/headers/prototypes.h
index a284888f..b421af35 100644
--- a/converter/ppm/ppmtompeg/headers/prototypes.h
+++ b/converter/ppm/ppmtompeg/headers/prototypes.h
@@ -44,33 +44,26 @@ void    ResetBFrameStats _ANSI_ARGS_((void));
 void    ResetPFrameStats _ANSI_ARGS_((void));
 void SetSearchRange (int const pixelsP,
                      int const pixelsB);
-void    ResetIFrameStats _ANSI_ARGS_((void));
 void
 SetPixelSearch(const char * const searchType);
-void    SetIQScale _ANSI_ARGS_((int const qI));
 void    SetPQScale _ANSI_ARGS_((int qP));
 void    SetBQScale _ANSI_ARGS_((int qB));
-float   EstimateSecondsPerIFrame _ANSI_ARGS_((void));
 float   EstimateSecondsPerPFrame _ANSI_ARGS_((void));
 float   EstimateSecondsPerBFrame _ANSI_ARGS_((void));
 void    SetGOPSize _ANSI_ARGS_((int size));
 void
 SetStatFileName(const char * const fileName);
-void    SetSlicesPerFrame _ANSI_ARGS_((int const number));
-void    SetBlocksPerSlice _ANSI_ARGS_((void));
 
 
 void DCTFrame _ANSI_ARGS_((MpegFrame * mf));
 
 void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf));
 
-void    MotionSearchPreComputation _ANSI_ARGS_((MpegFrame * const frame));
+void    MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame));
 
 void    ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame));
 void mp_validate_size _ANSI_ARGS_((int *x, int *y));
 
-extern void SetFCode _ANSI_ARGS_((void));
-
 
 /* psearch.c */
 void    ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer));
diff --git a/converter/ppm/ppmtompeg/headers/subsample.h b/converter/ppm/ppmtompeg/headers/subsample.h
new file mode 100644
index 00000000..deedf251
--- /dev/null
+++ b/converter/ppm/ppmtompeg/headers/subsample.h
@@ -0,0 +1,39 @@
+#ifndef SUBSAMPLE_H_INCLUDED
+#define SUBSAMPLE_H_INCLUDED
+
+#include "frame.h"
+#include "mtypes.h"
+
+int32
+LumMotionErrorA(const LumBlock * const currentBlockP,
+                MpegFrame *      const prevFrame,
+                int              const by,
+                int              const bx,
+                vector           const m,
+                int32            const bestSoFar);
+
+int32
+LumMotionErrorB(const LumBlock * const currentP,
+                MpegFrame *      const prevFrame,
+                int              const by,
+                int              const bx,
+                vector           const m,
+                int32            const bestSoFar);
+
+int32
+LumMotionErrorC(const LumBlock * const currentP,
+                MpegFrame *      const prevFrame,
+                int              const by,
+                int              const bx,
+                vector           const m,
+                int32            const bestSoFar);
+
+int32
+LumMotionErrorD(const LumBlock * const currentP,
+                MpegFrame *      const prevFrame,
+                int              const by,
+                int              const bx,
+                vector           const m,
+                int32            const bestSoFar);
+
+#endif
diff --git a/converter/ppm/ppmtompeg/huff.h b/converter/ppm/ppmtompeg/huff.h
deleted file mode 100644
index 4d0b8840..00000000
--- a/converter/ppm/ppmtompeg/huff.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 1995 The Regents of the University of California.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement is
- * hereby granted, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-/*  
- *  $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/huff.h,v 1.2 1995/01/19 23:08:28 eyhung Exp $
- */
-
-/*  
- *  THIS FILE IS MACHINE GENERATED!  DO NOT EDIT!
- */
-#define HUFF_MAXRUN	32
-#define HUFF_MAXLEVEL	41
-
-extern int huff_maxlevel[];
-extern uint32 *huff_table[];
-extern int *huff_bits[];
diff --git a/converter/ppm/ppmtompeg/iframe.c b/converter/ppm/ppmtompeg/iframe.c
index f4d7665a..7552f413 100644
--- a/converter/ppm/ppmtompeg/iframe.c
+++ b/converter/ppm/ppmtompeg/iframe.c
@@ -11,10 +11,9 @@
  *  GetIQScale                               *
  *  ResetIFrameStats                             *
  *  ShowIFrameSummary                            *
- *  EstimateSecondsPerIFrame                         *
  *  EncodeYDC                                *
  *  EncodeCDC                                *
- *      time_elapsed                                                         *
+ *  time_elapsed                                                         *
  *                                       *
  *===========================================================================*/
 
@@ -43,11 +42,11 @@
  * HEADER FILES *
  *==============*/
 
+#include <time.h>  /* Defines CLOCKS_PER_SEC, if this system has clock() */
 
-#ifdef CLOCKS_PER_SEC
-#include <times.h>
-#else
-#include <sys/times.h>
+#ifndef CLOCKS_PER_SEC
+  /* System doesn't have clock(); we assume it has times() instead */
+  #include <sys/times.h>
 #endif
 
 #include <sys/types.h>
@@ -67,12 +66,14 @@
 #include "specifics.h"
 #include "opts.h"
 
+#include "iframe.h"
+
 /*==================*
  * STATIC VARIABLES *
  *==================*/
 
-static  int lastNumBits = 0;
-static  int lastIFrame = 0;
+static int lastNumBits = 0;
+static int lastIFrame = 0;
 static int numBlocks = 0;
 static int numBits;
 static int numFrames = 0;
@@ -128,24 +129,11 @@ int fCodeI, fCodeP, fCodeB;
 boolean printSNR = FALSE;
 boolean printMSE = FALSE;
 boolean decodeRefFrames = FALSE;
-Block **dct=NULL, **dctr=NULL, **dctb=NULL;
-dct_data_type   **dct_data; /* used in p/bframe.c */
 int  TIME_RATE;
 
 
-/*=====================*
- * EXPORTED PROCEDURES *
- *=====================*/
-extern void PrintItoIBitRate _ANSI_ARGS_((int const numBits, int const frameNum));
 
-/*===============================*
- * INTERNAL PROCEDURE prototypes *
- *===============================*/
-void AllocDctBlocks(void );
-int SetFCodeHelper (int const sr);
-void CalcDistortion (MpegFrame * const current, int const y, int const x);
-
-int
+static int
 SetFCodeHelper(int const SR) {
 
     int     range,fCode;
@@ -296,6 +284,68 @@ GetIQScale(void) {
 
 
 
+static void
+CalcDistortion(MpegFrame * const current,
+               int         const y,
+               int         const x) {
+
+    int qscale, distort=0;
+    Block decblk;
+    FlatBlock fblk;
+    int datarate = 0;
+  
+    for (qscale = 1; qscale < 32; qscale ++) {
+        distort = 0;
+        datarate = 0;
+        Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->y_blocks[y][x], decblk);
+
+        Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->y_blocks[y][x+1], decblk);
+
+        Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->y_blocks[y+1][x], decblk);
+
+        Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->y_blocks[y+1][x+1], decblk);
+
+        Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->cb_blocks[y>>1][x>>1], decblk);
+
+        Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE);
+        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
+        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
+        mpeg_jrevdct((int16 *)decblk);
+        distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk);
+
+        if (!collect_distortion_detailed) {
+            fprintf(distortion_fp, "\t%d\n", distort);
+        } else if (collect_distortion_detailed == 1) {
+            fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate);
+        } else {
+            fprintf(fp_table_rate[qscale-1], "%d\n", datarate);
+            fprintf(fp_table_dist[qscale-1], "%d\n", distort);
+        }
+    }
+}
+
+
+
 /*===========================================================================*
  *
  * GenIFrame
@@ -618,24 +668,6 @@ ShowIFrameSummary(unsigned int const inputFrameBits,
 
 /*===========================================================================*
  *
- * EstimateSecondsPerIFrame
- *
- *  estimates the number of seconds required per I-frame
- *
- * RETURNS: seconds (floating point value)
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-float
-EstimateSecondsPerIFrame()
-{
-    return (float)totalTime/((float)TIME_RATE*(float)numFrames);
-}
-
-
-/*===========================================================================*
- *
  * EncodeYDC
  *
  *  Encode the DC portion of a DCT of a luminance block
@@ -926,53 +958,6 @@ PrintItoIBitRate(int const numBits,
 
 
 
-/*===========================================================================*
- *
- * AllocDctBlocks
- *
- *  allocate memory for dct blocks
- *
- * RETURNS: nothing
- *
- * SIDE EFFECTS:    creates dct, dctr, dctb
- *
- *===========================================================================*/
-void
-AllocDctBlocks(void) {
-    int dctx, dcty;
-    int i;
-
-    dctx = Fsize_x / DCTSIZE;
-    dcty = Fsize_y / DCTSIZE;
-
-    dct = (Block **) malloc(sizeof(Block *) * dcty);
-    ERRCHK(dct, "malloc");
-    for (i = 0; i < dcty; i++) {
-        dct[i] = (Block *) malloc(sizeof(Block) * dctx);
-        ERRCHK(dct[i], "malloc");
-    }
-
-    dct_data = (dct_data_type **) malloc(sizeof(dct_data_type *) * dcty);
-    ERRCHK(dct_data, "malloc");
-    for (i = 0; i < dcty; i++) {
-        dct_data[i] = (dct_data_type *) malloc(sizeof(dct_data_type) * dctx);
-        ERRCHK(dct[i], "malloc");
-    }
-
-    dctr = (Block **) malloc(sizeof(Block *) * (dcty >> 1));
-    dctb = (Block **) malloc(sizeof(Block *) * (dcty >> 1));
-    ERRCHK(dctr, "malloc");
-    ERRCHK(dctb, "malloc");
-    for (i = 0; i < (dcty >> 1); i++) {
-        dctr[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1));
-        dctb[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1));
-        ERRCHK(dctr[i], "malloc");
-        ERRCHK(dctb[i], "malloc");
-    }
-}
-
-
-
 /*======================================================================*
  *
  * time_elapsed
@@ -994,69 +979,3 @@ int32 time_elapsed(void) {
     return timeBuffer.tms_utime + timeBuffer.tms_stime;
 #endif
 }
-
-
-
-void
-CalcDistortion(MpegFrame * const current,
-               int         const y,
-               int         const x) {
-
-    int qscale, distort=0;
-    Block decblk;
-    FlatBlock fblk;
-    int datarate = 0;
-  
-    for (qscale = 1; qscale < 32; qscale ++) {
-        distort = 0;
-        datarate = 0;
-        Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->y_blocks[y][x], decblk);
-
-        Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->y_blocks[y][x+1], decblk);
-
-        Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->y_blocks[y+1][x], decblk);
-
-        Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->y_blocks[y+1][x+1], decblk);
-
-        Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->cb_blocks[y>>1][x>>1], decblk);
-
-        Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE);
-        Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE);
-        if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk);
-        mpeg_jrevdct((int16 *)decblk);
-        distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk);
-
-        if (!collect_distortion_detailed) {
-            fprintf(distortion_fp, "\t%d\n", distort);
-        } else if (collect_distortion_detailed == 1) {
-            fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate);
-        } else {
-            fprintf(fp_table_rate[qscale-1], "%d\n", datarate);
-            fprintf(fp_table_dist[qscale-1], "%d\n", distort);
-        }
-    }
-}
-
-
-
-
diff --git a/converter/ppm/ppmtompeg/jpeg.c b/converter/ppm/ppmtompeg/jpeg.c
index b51cf083..a703cf39 100644
--- a/converter/ppm/ppmtompeg/jpeg.c
+++ b/converter/ppm/ppmtompeg/jpeg.c
@@ -15,6 +15,7 @@
  * HEADER FILES *
  *==============*/
 #define _XOPEN_SOURCE    /* Make sure stdio.h contains fileno() */
+#include <unistd.h>
 #include <stdio.h>
 #include "all.h"
 /* With the lossless jpeg patch applied to the Jpeg library
@@ -52,6 +53,17 @@ extern void jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
 #define HEADER_SIZE 607   /*JFIF header size used on output images*/
 
 
+static int
+minDctVScaledSize(struct jpeg_decompress_struct const cinfo) {
+
+#if JPEG_LIB_VERSION >= 70
+    return cinfo.min_DCT_v_scaled_size;
+#else
+    return cinfo.min_DCT_scaled_size;
+#endif
+}
+
+
 
 /*=======================================================================*
  *                                                                       *
@@ -416,11 +428,7 @@ ReadJPEG(MpegFrame * const mf,
      */
   
     /* set parameters for decompression */
-#ifdef JPEG4
-    cinfo.want_raw_output = TRUE;
-#else
     cinfo.raw_data_out = TRUE;
-#endif
     cinfo.out_color_space = JCS_YCbCr;
   
     /* calculate image output dimensions */
@@ -466,13 +474,7 @@ ReadJPEG(MpegFrame * const mf,
     /* Make an 8-row-high sample array that will go away when done
        with image
     */
-#ifdef JPEG4
-    buffer_height = 8;  /* could be 2, 4,8 rows high */
-#elif JPEG_LIB_VERSION >= 70
-    buffer_height = cinfo.max_v_samp_factor * cinfo.min_DCT_v_scaled_size;
-#else
-    buffer_height = cinfo.max_v_samp_factor * cinfo.min_DCT_scaled_size;
-#endif
+    buffer_height = cinfo.max_v_samp_factor * minDctVScaledSize(cinfo);
   
     for(cp=0,compptr = cinfo.comp_info;cp<cinfo.num_components;
         cp++,compptr++) {
@@ -496,11 +498,7 @@ ReadJPEG(MpegFrame * const mf,
 
     while (cinfo.output_scanline < cinfo.output_height) {
 
-#ifdef JPEG4
-        (void) jpeg_read_raw_scanlines(&cinfo, scanarray, buffer_height);
-#else
         (void) jpeg_read_raw_data(&cinfo, scanarray, buffer_height);
-#endif
 
         /* alter subsample ratio's if neccessary */
         if ((h_samp[0]==2) && (h_samp[1]==1) && (h_samp[2]==1) &&
diff --git a/converter/ppm/ppmtompeg/mheaders.c b/converter/ppm/ppmtompeg/mheaders.c
index 8a51c089..4cfe49ac 100644
--- a/converter/ppm/ppmtompeg/mheaders.c
+++ b/converter/ppm/ppmtompeg/mheaders.c
@@ -278,24 +278,350 @@ const double VidRateNum[9]={1.0, 23.976, 24.0, 25.0, 29.97, 30.0,
                              50.0 ,59.94, 60.0};
 
 
-/*===============================*
- * INTERNAL PROCEDURE prototypes *
- *===============================*/
-
-static void	GenMBAddrIncr _ANSI_ARGS_((BitBucket *bb, uint32 addr_incr));
-static void	GenPictHead _ANSI_ARGS_((BitBucket *bb, uint32 temp_ref,
-		    uint32 code_type, uint32 vbv_delay,
-		    int32 full_pel_forw_flag, uint32 forw_f_code,
-		    int32 full_pel_back_flag, uint32 back_f_code,
-		    uint8 *extra_info, uint32 extra_info_size,
-		    uint8 *ext_data, uint32 ext_data_size,
-		    uint8 *user_data, uint32 user_data_size));
-static void	GenMBType _ANSI_ARGS_((BitBucket *bb, uint32 pict_code_type,
-		  uint32 mb_quant, uint32 motion_forw, uint32 motion_back,
-		  uint32 mb_pattern, uint32 mb_intra));
-static void	GenMotionCode _ANSI_ARGS_((BitBucket * const bb, int32 const vector));
-static void	GenBlockPattern _ANSI_ARGS_((BitBucket *bb,
-					     uint32 mb_pattern));
+/*=====================*
+ * INTERNAL PROCEDURES *
+ *=====================*/
+
+/*===========================================================================*
+ *
+ * GenMBType
+ *
+ *	generate macroblock type with given attributes
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back,
+          mb_pattern, mb_intra)
+    BitBucket *bbPtr;
+    uint32 pict_code_type;
+    uint32 mb_quant;
+    uint32 motion_forw;
+    uint32 motion_back;
+    uint32 mb_pattern;
+    uint32 mb_intra;
+{
+    int code;
+
+    switch (pict_code_type) {
+    case 1:
+        if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) {
+            perror("Illegal parameters for macroblock type.");
+            exit(-1);
+        }
+        if (mb_quant) {
+            Bitio_Write(bbPtr, 0x1, 2);
+        } else {
+            Bitio_Write(bbPtr, 0x1, 1);
+        }
+        break;
+
+    case 2:
+        code = 0;
+        if (mb_quant) {
+            code += 16;
+        }
+        if (motion_forw) {
+            code += 8;
+        }
+        if (motion_back) {
+            code += 4;
+        }
+        if (mb_pattern) {
+            code += 2;
+        }
+        if (mb_intra) {
+            code += 1;
+        }
+
+        switch (code) {
+        case 1:
+            Bitio_Write(bbPtr, 0x3, 5);
+            break;
+        case 2:
+            Bitio_Write(bbPtr, 0x1, 2);
+            break;
+        case 8:
+            Bitio_Write(bbPtr, 0x1, 3);
+            break;
+        case 10:
+            Bitio_Write(bbPtr, 0x1, 1);
+            break;
+        case 17:
+            Bitio_Write(bbPtr, 0x1, 6);
+            break;
+        case 18:
+            Bitio_Write(bbPtr, 0x1, 5);
+            break;
+        case 26:
+            Bitio_Write(bbPtr, 0x2, 5);
+            break;
+        default:
+            perror("Illegal parameters for macroblock type.");
+            exit(-1);
+            break;
+        }
+        break;
+
+    case 3:
+        code = 0;
+        if (mb_quant) {
+            code += 16;
+        }
+        if (motion_forw) {
+            code += 8;
+        }
+        if (motion_back) {
+            code += 4;
+        }
+        if (mb_pattern) {
+            code += 2;
+        }
+        if (mb_intra) {
+            code += 1;
+        }
+
+        switch (code) {
+        case 12:
+            Bitio_Write(bbPtr, 0x2, 2);
+            break;
+        case 14:
+            Bitio_Write(bbPtr, 0x3, 2);
+            break;
+        case 4:
+            Bitio_Write(bbPtr, 0x2, 3);
+            break;
+        case 6:
+            Bitio_Write(bbPtr, 0x3, 3);
+            break;
+        case 8:
+            Bitio_Write(bbPtr, 0x2, 4);
+            break;
+        case 10:
+            Bitio_Write(bbPtr, 0x3, 4);
+            break;
+        case 1:
+            Bitio_Write(bbPtr, 0x3, 5);
+            break;
+        case 30:
+            Bitio_Write(bbPtr, 0x2, 5);
+            break;
+        case 26:
+            Bitio_Write(bbPtr, 0x3, 6);
+            break;
+        case 22:
+            Bitio_Write(bbPtr, 0x2, 6);
+            break;
+        case 17:
+            Bitio_Write(bbPtr, 0x1, 6);
+            break;
+        default:
+            perror("Illegal parameters for macroblock type.");
+            exit(-1);
+            break;
+        }
+        break;
+    }
+}
+
+
+/*===========================================================================*
+ *
+ * GenMotionCode
+ *
+ *	generate motion vector output with given value
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenMotionCode(BitBucket * const bbPtr,
+              int32       const vector) {
+
+    uint32 code, num;
+
+    if ((vector < -16) || (vector > 16)) {
+        perror("Motion vector out of range.");
+        fprintf(stderr, "Motion vector out of range:  vector = %d\n", vector);
+        exit(-1);
+    }
+    code = mbMotionVectorTable[vector + 16][0];
+    num = mbMotionVectorTable[vector + 16][1];
+
+    Bitio_Write(bbPtr, code, num);
+}
+
+
+/*===========================================================================*
+ *
+ * GenBlockPattern
+ *
+ *	generate macroblock pattern output
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenBlockPattern(bbPtr, mb_pattern)
+    BitBucket *bbPtr;
+    uint32 mb_pattern;
+{
+    uint32 code, num;
+
+    code = mbPatTable[mb_pattern][0];
+    num = mbPatTable[mb_pattern][1];
+
+    Bitio_Write(bbPtr, code, num);
+}
+
+
+/*===========================================================================*
+ *
+ * GenMBAddrIncr
+ *
+ *	generate macroblock address increment output
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenMBAddrIncr(bbPtr, addr_incr)
+    BitBucket *bbPtr;
+    uint32 addr_incr;
+{
+    uint32 code;
+    uint32 num;
+
+    code = mbAddrIncrTable[addr_incr][0];
+    num = mbAddrIncrTable[addr_incr][1];
+
+    Bitio_Write(bbPtr, code, num);
+}
+
+
+/*===========================================================================*
+ *
+ * GenPictHead
+ *
+ *	generate picture header with given attributes
+ *	append result to the specified bitstream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag,
+            forw_f_code, full_pel_back_flag, back_f_code, extra_info,
+            extra_info_size, ext_data, ext_data_size, user_data,
+            user_data_size)
+    BitBucket *bbPtr;
+    uint32 temp_ref;
+    uint32 code_type;
+    uint32 vbv_delay;
+    int32 full_pel_forw_flag;
+    uint32 forw_f_code;
+    int32 full_pel_back_flag;
+    uint32 back_f_code;
+    uint8 *extra_info;
+    uint32 extra_info_size;
+    uint8 *ext_data;
+    uint32 ext_data_size;
+    uint8 *user_data;
+    uint32 user_data_size;
+{
+    /* Write picture start code. */
+    Bitio_Write(bbPtr, PICT_START_CODE, 32);
+
+    /* Temp reference. */
+    Bitio_Write(bbPtr, temp_ref, 10);
+
+    /* Code_type. */
+    if (code_type == 0)
+        code_type = 1;
+
+    Bitio_Write(bbPtr, code_type, 3);
+
+    /* vbv_delay. */
+    vbv_delay = 0xffff;		    /* see page 36 (section 2.4.3.4) */
+    Bitio_Write(bbPtr, vbv_delay, 16);
+
+    if ((code_type == 2) || (code_type == 3)) {
+
+        /* Full pel forw flag. */
+
+        if (full_pel_forw_flag)
+            Bitio_Write(bbPtr, 0x01, 1);
+        else
+            Bitio_Write(bbPtr, 0x00, 1);
+
+        /* Forw f code. */
+
+        Bitio_Write(bbPtr, forw_f_code, 3);
+    }
+    if (code_type == 3) {
+
+        /* Full pel back flag. */
+
+        if (full_pel_back_flag)
+            Bitio_Write(bbPtr, 0x01, 1);
+        else
+            Bitio_Write(bbPtr, 0x00, 1);
+
+        /* Back f code. */
+
+        Bitio_Write(bbPtr, back_f_code, 3);
+    }
+    /* Extra bit picture info. */
+
+    if (extra_info != NULL) {
+        unsigned int i;
+        for (i = 0; i < extra_info_size; ++i) {
+            Bitio_Write(bbPtr, 0x01, 1);
+            Bitio_Write(bbPtr, extra_info[i], 8);
+        }
+    }
+    Bitio_Write(bbPtr, 0x00, 1);
+
+    /* next start code */
+    Bitio_BytePad(bbPtr);
+
+    /* Write ext data if present. */
+
+    if (ext_data != NULL) {
+        unsigned int i;
+
+        Bitio_Write(bbPtr, EXT_START_CODE, 32);
+
+        for (i = 0; i < ext_data_size; ++i)
+            Bitio_Write(bbPtr, ext_data[i], 8);
+        Bitio_BytePad(bbPtr);
+    }
+    /* Write user data if present. */
+    if (user_data != NULL) {
+        unsigned int i;
+        Bitio_Write(bbPtr, USER_START_CODE, 32);
+
+        for (i = 0; i < user_data_size; ++i)
+            Bitio_Write(bbPtr, user_data[i], 8);
+
+        Bitio_BytePad(bbPtr);
+    }
+}
 
 
 /*=====================*
@@ -767,7 +1093,8 @@ if ( addr_incr != 1 )
     }
 
     /* Generate mb type code. */
-    GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, mb_pattern, mb_intra);
+    GenMBType(bbPtr, pict_code_type, mb_quant,
+              motion_forw, motion_back, mb_pattern, mb_intra);
 
     /* MB quant. */
     if (mb_quant) {
@@ -831,353 +1158,6 @@ if ( addr_incr != 1 )
 }
 
 
-/*=====================*
- * INTERNAL PROCEDURES *
- *=====================*/
-
-/*===========================================================================*
- *
- * GenMBType
- *
- *	generate macroblock type with given attributes
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back,
-	  mb_pattern, mb_intra)
-    BitBucket *bbPtr;
-    uint32 pict_code_type;
-    uint32 mb_quant;
-    uint32 motion_forw;
-    uint32 motion_back;
-    uint32 mb_pattern;
-    uint32 mb_intra;
-{
-    int code;
-
-    switch (pict_code_type) {
-    case 1:
-	if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) {
-	    perror("Illegal parameters for macroblock type.");
-	    exit(-1);
-	}
-	if (mb_quant) {
-	    Bitio_Write(bbPtr, 0x1, 2);
-	} else {
-	    Bitio_Write(bbPtr, 0x1, 1);
-	}
-	break;
-
-    case 2:
-	code = 0;
-	if (mb_quant) {
-	    code += 16;
-	}
-	if (motion_forw) {
-	    code += 8;
-	}
-	if (motion_back) {
-	    code += 4;
-	}
-	if (mb_pattern) {
-	    code += 2;
-	}
-	if (mb_intra) {
-	    code += 1;
-	}
-
-	switch (code) {
-	case 1:
-	    Bitio_Write(bbPtr, 0x3, 5);
-	    break;
-	case 2:
-	    Bitio_Write(bbPtr, 0x1, 2);
-	    break;
-	case 8:
-	    Bitio_Write(bbPtr, 0x1, 3);
-	    break;
-	case 10:
-	    Bitio_Write(bbPtr, 0x1, 1);
-	    break;
-	case 17:
-	    Bitio_Write(bbPtr, 0x1, 6);
-	    break;
-	case 18:
-	    Bitio_Write(bbPtr, 0x1, 5);
-	    break;
-	case 26:
-	    Bitio_Write(bbPtr, 0x2, 5);
-	    break;
-	default:
-	    perror("Illegal parameters for macroblock type.");
-	    exit(-1);
-	    break;
-	}
-	break;
-
-    case 3:
-	code = 0;
-	if (mb_quant) {
-	    code += 16;
-	}
-	if (motion_forw) {
-	    code += 8;
-	}
-	if (motion_back) {
-	    code += 4;
-	}
-	if (mb_pattern) {
-	    code += 2;
-	}
-	if (mb_intra) {
-	    code += 1;
-	}
-
-	switch (code) {
-	case 12:
-	    Bitio_Write(bbPtr, 0x2, 2);
-	    break;
-	case 14:
-	    Bitio_Write(bbPtr, 0x3, 2);
-	    break;
-	case 4:
-	    Bitio_Write(bbPtr, 0x2, 3);
-	    break;
-	case 6:
-	    Bitio_Write(bbPtr, 0x3, 3);
-	    break;
-	case 8:
-	    Bitio_Write(bbPtr, 0x2, 4);
-	    break;
-	case 10:
-	    Bitio_Write(bbPtr, 0x3, 4);
-	    break;
-	case 1:
-	    Bitio_Write(bbPtr, 0x3, 5);
-	    break;
-	case 30:
-	    Bitio_Write(bbPtr, 0x2, 5);
-	    break;
-	case 26:
-	    Bitio_Write(bbPtr, 0x3, 6);
-	    break;
-	case 22:
-	    Bitio_Write(bbPtr, 0x2, 6);
-	    break;
-	case 17:
-	    Bitio_Write(bbPtr, 0x1, 6);
-	    break;
-	default:
-	    perror("Illegal parameters for macroblock type.");
-	    exit(-1);
-	    break;
-	}
-	break;
-    }
-}
-
-
-/*===========================================================================*
- *
- * GenMotionCode
- *
- *	generate motion vector output with given value
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenMotionCode(BitBucket * const bbPtr,
-              int32       const vector) {
-
-    uint32 code, num;
-
-    if ((vector < -16) || (vector > 16)) {
-	perror("Motion vector out of range.");
-	fprintf(stderr, "Motion vector out of range:  vector = %d\n", vector);
-	exit(-1);
-    }
-    code = mbMotionVectorTable[vector + 16][0];
-    num = mbMotionVectorTable[vector + 16][1];
-
-    Bitio_Write(bbPtr, code, num);
-}
-
-
-/*===========================================================================*
- *
- * GenBlockPattern
- *
- *	generate macroblock pattern output
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenBlockPattern(bbPtr, mb_pattern)
-    BitBucket *bbPtr;
-    uint32 mb_pattern;
-{
-    uint32 code, num;
-
-    code = mbPatTable[mb_pattern][0];
-    num = mbPatTable[mb_pattern][1];
-
-    Bitio_Write(bbPtr, code, num);
-}
-
-
-/*===========================================================================*
- *
- * GenMBAddrIncr
- *
- *	generate macroblock address increment output
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenMBAddrIncr(bbPtr, addr_incr)
-    BitBucket *bbPtr;
-    uint32 addr_incr;
-{
-    uint32 code;
-    uint32 num;
-
-    code = mbAddrIncrTable[addr_incr][0];
-    num = mbAddrIncrTable[addr_incr][1];
-
-    Bitio_Write(bbPtr, code, num);
-}
-
-
-/*===========================================================================*
- *
- * GenPictHead
- *
- *	generate picture header with given attributes
- *	append result to the specified bitstream
- *
- * RETURNS:	nothing
- *
- * SIDE EFFECTS:    none
- *
- *===========================================================================*/
-static void
-GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag,
-	    forw_f_code, full_pel_back_flag, back_f_code, extra_info,
-	    extra_info_size, ext_data, ext_data_size, user_data,
-	    user_data_size)
-    BitBucket *bbPtr;
-    uint32 temp_ref;
-    uint32 code_type;
-    uint32 vbv_delay;
-    int32 full_pel_forw_flag;
-    uint32 forw_f_code;
-    int32 full_pel_back_flag;
-    uint32 back_f_code;
-    uint8 *extra_info;
-    uint32 extra_info_size;
-    uint8 *ext_data;
-    uint32 ext_data_size;
-    uint8 *user_data;
-    uint32 user_data_size;
-{
-    int i;
-
-    /* Write picture start code. */
-    Bitio_Write(bbPtr, PICT_START_CODE, 32);
-
-    /* Temp reference. */
-    Bitio_Write(bbPtr, temp_ref, 10);
-
-    /* Code_type. */
-    if (code_type == 0) {
-	code_type = 1;
-    }
-    Bitio_Write(bbPtr, code_type, 3);
-
-    /* vbv_delay. */
-    vbv_delay = 0xffff;		    /* see page 36 (section 2.4.3.4) */
-    Bitio_Write(bbPtr, vbv_delay, 16);
-
-    if ((code_type == 2) || (code_type == 3)) {
-
-	/* Full pel forw flag. */
-
-	if (full_pel_forw_flag) {
-	    Bitio_Write(bbPtr, 0x01, 1);
-	} else {
-	    Bitio_Write(bbPtr, 0x00, 1);
-	}
-
-	/* Forw f code. */
-
-	Bitio_Write(bbPtr, forw_f_code, 3);
-    }
-    if (code_type == 3) {
-
-	/* Full pel back flag. */
-
-	if (full_pel_back_flag) {
-	    Bitio_Write(bbPtr, 0x01, 1);
-	} else {
-	    Bitio_Write(bbPtr, 0x00, 1);
-	}
-
-	/* Back f code. */
-
-	Bitio_Write(bbPtr, back_f_code, 3);
-    }
-    /* Extra bit picture info. */
-
-    if (extra_info != NULL) {
-	for (i = 0; i < extra_info_size; i++) {
-	    Bitio_Write(bbPtr, 0x01, 1);
-	    Bitio_Write(bbPtr, extra_info[i], 8);
-	}
-    }
-    Bitio_Write(bbPtr, 0x00, 1);
-
-    /* next start code */
-    Bitio_BytePad(bbPtr);
-
-    /* Write ext data if present. */
-
-    if (ext_data != NULL) {
-	Bitio_Write(bbPtr, EXT_START_CODE, 32);
-
-	for (i = 0; i < ext_data_size; i++) {
-	    Bitio_Write(bbPtr, ext_data[i], 8);
-	}
-	Bitio_BytePad(bbPtr);
-    }
-    /* Write user data if present. */
-    if (user_data != NULL) {
-	Bitio_Write(bbPtr, USER_START_CODE, 32);
-
-	for (i = 0; i < user_data_size; i++) {
-	    Bitio_Write(bbPtr, user_data[i], 8);
-	}
-	Bitio_BytePad(bbPtr);
-    }
-}
-
-
 #ifdef UNUSED_PROCEDURES
 
 /* GenMBEnd only used for `D` pictures. Shouldn't really ever be called. */
diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c
index fafbb97a..6557f377 100644
--- a/converter/ppm/ppmtompeg/mpeg.c
+++ b/converter/ppm/ppmtompeg/mpeg.c
@@ -43,8 +43,8 @@
 #endif
 #include <sys/stat.h>
 
-#include "ppm.h"
 #include "nstring.h"
+#include "nsleep.h"
 
 #include "mtypes.h"
 #include "frames.h"
@@ -276,9 +276,8 @@ SetReferenceFrameType(const char * const type) {
 
 
 void
-SetBitRateFileName(fileName)
-    char *fileName;
-{
+SetBitRateFileName(const char * const fileName) {
+
     strcpy(bitRateFileName, fileName);
 }
 
@@ -318,7 +317,7 @@ finishFrameOutput(MpegFrame * const frameP,
 
 static void
 outputIFrame(MpegFrame * const frameP,
-             BitBucket * const bb,
+             BitBucket * const bbP,
              int         const realStart,
              int         const realEnd,
              MpegFrame * const pastRefFrameP,
@@ -326,7 +325,7 @@ outputIFrame(MpegFrame * const frameP,
       
     /* only start a new GOP with I */
     /* don't start GOP if only doing frames */
-    if ((!separateFiles) && (currentGOP >= gopSize)) {
+    if (!separateFiles && currentGOP >= gopSize) {
         boolean const closed = 
             (totalFramesSent == frameP->id || pastRefFrameP == NULL);
 
@@ -344,7 +343,7 @@ outputIFrame(MpegFrame * const frameP,
             }
       
             Mhead_GenSequenceHeader(
-                bb, Fsize_x, Fsize_y,
+                bbP, Fsize_x, Fsize_y,
                 /* pratio */    aspectRatio,
                 /* pict_rate */ frameRate, /* bit_rate */ bit_rate,
                 /* buf_size */  buf_size,  /* c_param_flag */ 1,
@@ -359,7 +358,7 @@ outputIFrame(MpegFrame * const frameP,
                        closed ? "YES" : "NO", frameP->id);
     
         ++num_gop;
-        Mhead_GenGOPHeader(bb,  /* drop_frame_flag */ 0,
+        Mhead_GenGOPHeader(bbP,  /* drop_frame_flag */ 0,
                            tc_hrs, tc_min, tc_sec, tc_pict,
                            closed, /* broken_link */ 0,
                            /* ext_data */ NULL, /* ext_data_size */ 0,
@@ -368,16 +367,16 @@ outputIFrame(MpegFrame * const frameP,
         if (pastRefFrameP == NULL)
             SetGOPStartTime(0);
         else
-            SetGOPStartTime(pastRefFrameP->id+1);
+            SetGOPStartTime(pastRefFrameP->id + 1);
     }
       
-    if ((frameP->id >= realStart) && (frameP->id <= realEnd))
-        GenIFrame(bb, frameP);
+    if (frameP->id >= realStart && frameP->id <= realEnd)
+        GenIFrame(bbP, frameP);
       
-    numI--;
+    --numI;
     timeMask &= 0x6;
       
-    currentGOP++;
+    ++currentGOP;
     IncrementTCTime();
 }
 
@@ -393,10 +392,10 @@ outputPFrame(MpegFrame * const frameP,
     if ((frameP->id >= realStart) && (frameP->id <= realEnd))
         GenPFrame(bbP, frameP, pastRefFrameP);
 
-    numP--;
+    --numP;
     timeMask &= 0x5;
     
-    currentGOP++;
+    ++currentGOP;
     IncrementTCTime();
 }
 
@@ -498,6 +497,9 @@ processBFrames(MpegFrame *          const pastRefFrameP,
 
    But do only those B frames whose frame numbers are within the range
    'realStart' through 'realEnd'.
+
+   Output the frames to the output stream 'wholeStreamBbP'.  If NULL,
+   output each frame to its own individual file instead.
 -----------------------------------------------------------------------------*/
     boolean const separateFiles = (wholeStreamBbP == NULL);
     unsigned int const firstBFrameNum = pastRefFrameP->id + 1;
@@ -551,7 +553,7 @@ processBFrames(MpegFrame *          const pastRefFrameP,
 
 static void
 processRefFrame(MpegFrame *    const frameP, 
-                BitBucket *    const bb_arg,
+                BitBucket *    const wholeStreamBbP,
                 int            const realStart,
                 int            const realEnd,
                 MpegFrame *    const pastRefFrameP,
@@ -564,26 +566,28 @@ processRefFrame(MpegFrame *    const frameP,
 
    But only if its frame number is within the range 'realStart'
    through 'realEnd'.
+
+   Output the frame to the output stream 'wholeStreamBbP'.  If NULL,
+   output it to its own individual file instead.
 -----------------------------------------------------------------------------*/
     if (frameP->id >= realStart && frameP->id <= realEnd) {
-        boolean separateFiles;
-        BitBucket * bb;
+        bool const separateFiles = (wholeStreamBbP == NULL);
   
-        separateFiles = (bb_arg == NULL);
+        BitBucket * bbP;
   
-        if ( separateFiles )
-            bb = bitioNew(outputFileName, frameP->id, remoteIO);
+        if (separateFiles)
+            bbP = bitioNew(outputFileName, frameP->id, remoteIO);
         else
-            bb = bb_arg;
+            bbP = wholeStreamBbP;
   
         /* first, output this reference frame */
         switch (frameP->type) {
         case TYPE_IFRAME:
-            outputIFrame(frameP, bb, realStart, realEnd, pastRefFrameP, 
+            outputIFrame(frameP, bbP, realStart, realEnd, pastRefFrameP, 
                          separateFiles);
             break;
         case TYPE_PFRAME:
-            outputPFrame(frameP, bb, realStart, realEnd, pastRefFrameP);
+            outputPFrame(frameP, bbP, realStart, realEnd, pastRefFrameP);
             ShowRemainingTime(childProcess);
             break;
         default:
@@ -593,7 +597,7 @@ processRefFrame(MpegFrame *    const frameP,
         
         ++(*framesOutputP);
         
-        finishFrameOutput(frameP, bb, separateFiles, referenceFrame,
+        finishFrameOutput(frameP, bbP, separateFiles, referenceFrame,
                           childProcess, remoteIO);
     }
 }
@@ -702,7 +706,7 @@ readAndSaveFrame(struct inputSource * const inputSourceP,
 static void
 doFirstFrameStuff(enum frameContext const context,
                   const char *      const userDataFileName,
-                  BitBucket *       const bb,
+                  BitBucket *       const bbP,
                   int               const fsize_x,
                   int               const fsize_y,
                   int               const aspectRatio,
@@ -713,8 +717,12 @@ doFirstFrameStuff(enum frameContext const context,
 /*----------------------------------------------------------------------------
    Do stuff we have to do after reading the first frame in a sequence
    of frames requested of GenMPEGStream().
+
+   *bbP is the output stream to which to write any header stuff we have
+   to write.  If 'context' is such that there is no header stuff to write,
+   then 'bbP' is irrelevant.
 -----------------------------------------------------------------------------*/
-    *inputFrameBitsP = 24*Fsize_x*Fsize_y;
+    *inputFrameBitsP = 24 * Fsize_x * Fsize_y;
     SetBlocksPerSlice();
           
     if (context == CONTEXT_WHOLESTREAM) {
@@ -722,7 +730,7 @@ doFirstFrameStuff(enum frameContext const context,
         char * userData;
         unsigned int userDataSize;
 
-        assert(bb != NULL);
+        assert(bbP != NULL);
 
         DBG_PRINT(("Generating sequence header\n"));
         if (bitstreamMode == FIXED_RATE) {
@@ -770,7 +778,7 @@ doFirstFrameStuff(enum frameContext const context,
             userDataSize = strlen(userData);
             strfree(userDataString);
         }
-        Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y,
+        Mhead_GenSequenceHeader(bbP, Fsize_x, Fsize_y,
                                 /* pratio */ aspectRatio,
                                 /* pict_rate */ frameRate, 
                                 /* bit_rate */ bit_rate,
@@ -990,13 +998,21 @@ doAFrame(unsigned int         const frameNumber,
          unsigned int *       const framesReadP,
          unsigned int *       const framesOutputP,
          bool *               const firstFrameDoneP,
-         BitBucket *          const bbP,
+         BitBucket *          const wholeStreamBbP,
          unsigned int *       const inputFrameBitsP,
          bool *               const endOfStreamP) {
 /*----------------------------------------------------------------------------
    *endOfStreamP returned means we were unable to do a frame because
    the input stream has ended.  In that case, none of the other outputs
    are valid.
+
+   Process an input frame.  This can involve writing its description
+   to the output stream, saving it for later use, and/or writing
+   descriptions of previously saved frames to the output stream
+   because we now have enough information to do so.
+
+   Output the frames to the output stream 'wholeStreamBbP'.  If NULL,
+   output each frame to its own individual file instead.
 -----------------------------------------------------------------------------*/
     char const frameType = FType_Type(frameNumber);
     
@@ -1026,21 +1042,21 @@ doAFrame(unsigned int         const frameNumber,
             *endOfStreamP = FALSE;
 
             if (!*firstFrameDoneP) {
-                doFirstFrameStuff(context, userDataFileName,
-                                  bbP, Fsize_x, Fsize_y, aspectRatio,
+                doFirstFrameStuff(context, userDataFileName, wholeStreamBbP,
+                                  Fsize_x, Fsize_y, aspectRatio,
                                   frameRate, qtable, niqtable, 
                                   inputFrameBitsP);
             
                 *firstFrameDoneP = TRUE;
             }
-            processRefFrame(frameP, bbP, frameStart, frameEnd,
+            processRefFrame(frameP, wholeStreamBbP, frameStart, frameEnd,
                             pastRefFrameP, childProcess, outputFileName, 
                             framesReadP, framesOutputP);
                 
             if (pastRefFrameP) {
                 processBFrames(pastRefFrameP, frameP, realStart, realEnd,
                                inputSourceP, remoteIO, childProcess, 
-                               &IOtime, bbP, outputFileName,
+                               &IOtime, wholeStreamBbP, outputFileName,
                                framesReadP, framesOutputP, &currentGOP);
             }
             if (pastRefFrameP != NULL)
@@ -1086,17 +1102,20 @@ GenMPEGStream(struct inputSource * const inputSourceP,
    we stop where the stream ends if that is before 'frameEnd'.
 
 -----------------------------------------------------------------------------*/
-    BitBucket * bbP;
+    BitBucket * streamBbP;
+        /* The output stream to which we write all the frames.  NULL
+           means the frames are going to individual frame files.
+        */
     unsigned int frameNumber;
     bool endOfStream;
     bool firstFrameDone;
     int numBits;
     unsigned int firstFrame, lastFrame;
-    /* Frame numbers of the first and last frames we look at.  This
-       could be more than the the frames we actually encode because
-       we may need context (i.e. to encode a B frame, we need the subsequent
-       I or P frame).
-    */
+        /* Frame numbers of the first and last frames we look at.
+           This could be more than the the frames we actually encode
+           because we may need context (i.e. to encode a B frame, we
+           need the subsequent I or P frame).
+        */
     unsigned int framesRead;
         /* Number of frames we have read; for statistical purposes */
     MpegFrame * pastRefFrameP;
@@ -1150,10 +1169,10 @@ GenMPEGStream(struct inputSource * const inputSourceP,
     if (showBitRatePerFrame)
         OpenBitRateFile();  /* May modify showBitRatePerFrame */
 
-    if (context == CONTEXT_WHOLESTREAM || context == CONTEXT_GOP)
-        bbP = Bitio_New(ofP);
+    if (context == CONTEXT_JUSTFRAMES)
+        streamBbP = NULL;
     else
-        bbP = NULL;
+        streamBbP = Bitio_New(ofP);
 
     initTCTime(firstFrame);
 
@@ -1171,7 +1190,7 @@ GenMPEGStream(struct inputSource * const inputSourceP,
                  frameStart, frameEnd, realStart, realEnd,
                  childProcess, outputFileName,
                  pastRefFrameP, &pastRefFrameP,
-                 &framesRead, &framesOutput, &firstFrameDone, bbP,
+                 &framesRead, &framesOutput, &firstFrameDone, streamBbP,
                  inputFrameBitsP, &endOfStream);
     }
     
@@ -1180,10 +1199,10 @@ GenMPEGStream(struct inputSource * const inputSourceP,
     
     /* SEQUENCE END CODE */
     if (context == CONTEXT_WHOLESTREAM)
-        Mhead_GenSequenceEnder(bbP);
+        Mhead_GenSequenceEnder(streamBbP);
     
-    if (context == CONTEXT_WHOLESTREAM)
-        numBits = bbP->cumulativeBits;
+    if (streamBbP)
+        numBits = streamBbP->cumulativeBits;
     else {
         /* What should the correct value be?  Most likely 1.  "numBits" is
            used below, so we need to make sure it's properly initialized 
@@ -1192,9 +1211,8 @@ GenMPEGStream(struct inputSource * const inputSourceP,
         numBits = 1;
     }
 
-    if (context != CONTEXT_JUSTFRAMES) {
-        Bitio_Flush(bbP);
-        bbP = NULL;
+    if (streamBbP) {
+        Bitio_Flush(streamBbP);
         fclose(ofP);
     }
     handleBitRate(realEnd, numBits, childProcess, showBitRatePerFrame);
@@ -1662,7 +1680,7 @@ ReadDecodedRefFrame(MpegFrame *  const frameP,
     }
 
     if ((fpointer = fopen(fileName, "rb")) == NULL) {
-        sleep(1);
+        sleepN(1000);
         if ((fpointer = fopen(fileName, "rb")) == NULL) {
             fprintf(stderr, "Cannot open %s\n", fileName);
             exit(1);
diff --git a/converter/ppm/ppmtompeg/noparallel.c b/converter/ppm/ppmtompeg/noparallel.c
index b27934fb..6e6449a4 100644
--- a/converter/ppm/ppmtompeg/noparallel.c
+++ b/converter/ppm/ppmtompeg/noparallel.c
@@ -164,7 +164,7 @@ void
 CombineServer(int          const numFrames, 
               const char * const masterHostName, 
               int          const masterPortNum,
-              const char * const outputFileName) {
+              const char*  const outputFileName) {
 
     pm_error("This version of Ppmtompeg cannot run combine server because "
              "it does not have socket capability.");
diff --git a/converter/ppm/ppmtompeg/parallel.c b/converter/ppm/ppmtompeg/parallel.c
index 021e6d2b..e13bf221 100644
--- a/converter/ppm/ppmtompeg/parallel.c
+++ b/converter/ppm/ppmtompeg/parallel.c
@@ -41,6 +41,7 @@
 
 #include "mallocvar.h"
 #include "nstring.h"
+#include "nsleep.h"
 
 #include "pm.h"
 
@@ -128,7 +129,7 @@ boolean niceProcesses = FALSE;
 boolean forceIalign = FALSE;
 int     machineNumber = -1;
 boolean remoteIO = FALSE;
-bool separateConversion;
+boolean separateConversion;
     /* The I/O server will convert from the input format to the base format,
        and the slave will convert from the base format to the YUV internal
        format.  If false, the I/O server assumes the input format is the
@@ -630,7 +631,7 @@ static int safe_fork(command)       /* fork child process and remember its PID *
  *
  *===========================================================================*/
 void
-SetIOConvert(bool const separate) {
+SetIOConvert(boolean const separate) {
     separateConversion = separate;
 }
 
@@ -648,8 +649,7 @@ SetIOConvert(bool const separate) {
  *
  *===========================================================================*/
 void
-SetParallelPerfect(val)
-boolean val;
+SetParallelPerfect(boolean val)
 {
     parallelPerfect = val;
 }
@@ -1209,7 +1209,7 @@ openInputFile(const char * const fileName,
             pm_message("ERROR  Couldn't read frame file '%s' errno = %d (%s)"
                        "attempt %d", 
                        fileName, errno, strerror(errno), attempts);
-            sleep(1);
+            sleepN(1000);
         }
         ++attempts;
     }
diff --git a/converter/ppm/ppmtompeg/param.c b/converter/ppm/ppmtompeg/param.c
index 69e38a6c..a145d33c 100644
--- a/converter/ppm/ppmtompeg/param.c
+++ b/converter/ppm/ppmtompeg/param.c
@@ -665,66 +665,66 @@ processParamLine(char const input[],
 
     switch(input[0]) {
     case 'A':
-        if (STRNEQ(input, "ASPECT_RATIO", 12)) {
+        if (strneq(input, "ASPECT_RATIO", 12)) {
             aspectRatio = GetAspectRatio(SkipSpacesTabs(&input[12]));
             optionSeen[OPTION_ASPECT_RATIO] = TRUE;
         }
         break;
         
     case 'B':
-        if (STRNEQ(input, "BQSCALE", 7)) {
+        if (strneq(input, "BQSCALE", 7)) {
             SetBQScale(atoi(SkipSpacesTabs(&input[7])));
             optionSeen[OPTION_BQSCALE] = TRUE;
-        } else if (STRNEQ(input, "BASE_FILE_FORMAT", 16)) {
+        } else if (strneq(input, "BASE_FILE_FORMAT", 16)) {
             const char * arg = SkipSpacesTabs(&input[16]);
             SetFileFormat(arg);
-            if (STRNEQ(arg, "YUV", 3) || STREQ(arg, "Y"))
+            if (strneq(arg, "YUV", 3) || streq(arg, "Y"))
                 *yuvUsedP = TRUE;
             optionSeen[OPTION_BASE_FORMAT] = TRUE;
-        } else if (STRNEQ(input, "BSEARCH_ALG", 11)) {
+        } else if (strneq(input, "BSEARCH_ALG", 11)) {
             SetBSearchAlg(SkipSpacesTabs(&input[11]));
             optionSeen[OPTION_BSEARCH_ALG] = TRUE;
-        } else if (STRNEQ(input, "BIT_RATE", 8)) {
+        } else if (strneq(input, "BIT_RATE", 8)) {
             setBitRate(SkipSpacesTabs(&input[8]));
             optionSeen[OPTION_BIT_RATE] = TRUE;
-        } else if (STRNEQ(input, "BUFFER_SIZE", 11)) {
+        } else if (strneq(input, "BUFFER_SIZE", 11)) {
             setBufferSize(SkipSpacesTabs(&input[11]));
             optionSeen[OPTION_BUFFER_SIZE] = TRUE;                  
         }
         break;
 
     case 'C':
-        if (STRNEQ(input, "CDL_FILE", 8)) {
+        if (strneq(input, "CDL_FILE", 8)) {
             strcpy(specificsFile, SkipSpacesTabs(&input[8]));
             specificsOn = TRUE;
             optionSeen[OPTION_SPECIFICS] = TRUE;
-        } else if (STRNEQ(input, "CDL_DEFINES", 11)) {
+        } else if (strneq(input, "CDL_DEFINES", 11)) {
             strcpy(specificsDefines, SkipSpacesTabs(&input[11]));
             optionSeen[OPTION_DEFS_SPECIFICS] = TRUE;
         }
         break;
 
     case 'F':
-        if (STRNEQ(input, "FRAME_INPUT_DIR", 15)) {
+        if (strneq(input, "FRAME_INPUT_DIR", 15)) {
             const char * const arg = SkipSpacesTabs(&input[15]);
-            if (STRNCASEEQ(arg, "stdin", 5))
+            if (strncaseeq(arg, "stdin", 5))
                 SetStdinInput(frameInputSourceP);
 
             strcpy(currentFramePath, arg);
-        } else if (STRNEQ(input, "FRAME_INPUT", 11)) {
+        } else if (strneq(input, "FRAME_INPUT", 11)) {
             ReadInputFileNames(fpointer, "FRAME_END_INPUT", 
                                frameInputSourceP->stdinUsed ? 
                                NULL : frameInputSourceP);
             optionSeen[OPTION_FRAME_INPUT] = TRUE;
-        } else if (STRNEQ(input, "FORCE_I_ALIGN", 13)) {
+        } else if (strneq(input, "FORCE_I_ALIGN", 13)) {
             forceIalign = TRUE;
-        } else if (STRNEQ(input, "FORCE_ENCODE_LAST_FRAME", 23)) {
+        } else if (strneq(input, "FORCE_ENCODE_LAST_FRAME", 23)) {
             /* NO-OP.  We used to drop trailing B frames by default and you
                needed this option to change the last frame to I so you could
                encode all the frames.  Now we just do that all the time.  
                Why wouldn't we?
             */
-        } else if (STRNEQ(input, "FRAME_RATE", 10)) {
+        } else if (strneq(input, "FRAME_RATE", 10)) {
             frameRate = GetFrameRate(SkipSpacesTabs(&input[10]));
             frameRateRounded = (int) VidRateNum[frameRate];
             if ((frameRate % 3) == 1)
@@ -734,21 +734,21 @@ processParamLine(char const input[],
         break;
         
     case 'G':
-        if (STRNEQ(input, "GOP_SIZE", 8)) {
+        if (strneq(input, "GOP_SIZE", 8)) {
             SetGOPSize(atoi(SkipSpacesTabs(&input[8])));
             optionSeen[OPTION_GOP] = TRUE;
-        } else if (STRNEQ(input, "GOP_INPUT_DIR", 13)) {
+        } else if (strneq(input, "GOP_INPUT_DIR", 13)) {
             const char * const arg = SkipSpacesTabs(&input[13]);
-            if (STRNCASEEQ(arg, "stdin", 5))
+            if (strncaseeq(arg, "stdin", 5))
                 SetStdinInput(gopInputSourceP);
 
             strcpy(currentGOPPath, arg);
-        } else if (STRNEQ(input, "GOP_INPUT", 9)) {
+        } else if (strneq(input, "GOP_INPUT", 9)) {
             ReadInputFileNames(fpointer, "GOP_END_INPUT", 
                                gopInputSourceP->stdinUsed ? 
                                NULL : gopInputSourceP);
             optionSeen[OPTION_GOP_INPUT] = TRUE;
-        } else if (STRNEQ(input, "GAMMA", 5)) {
+        } else if (strneq(input, "GAMMA", 5)) {
             GammaCorrection = TRUE;
             sscanf(SkipSpacesTabs(&input[5]), "%f", &GammaValue);
             optionSeen[OPTION_GAMMA] = TRUE;
@@ -756,27 +756,27 @@ processParamLine(char const input[],
         break;
         
     case 'I':
-        if (STRNEQ(input, "IQSCALE", 7)) {
+        if (strneq(input, "IQSCALE", 7)) {
             SetIQScale(atoi(SkipSpacesTabs(&input[7])));
             optionSeen[OPTION_IQSCALE] = TRUE;
-        } else if (STRNEQ(input, "INPUT_DIR", 9)) {
+        } else if (strneq(input, "INPUT_DIR", 9)) {
             const char * const arg = SkipSpacesTabs(&input[9]);
-            if (STRNCASEEQ(arg, "stdin", 5))
+            if (strncaseeq(arg, "stdin", 5))
                 SetStdinInput(inputSourceP);
             strcpy(currentPath, arg);
             optionSeen[OPTION_INPUT_DIR] = TRUE;
-        } else if (STRNEQ(input, "INPUT_CONVERT", 13)) {
+        } else if (strneq(input, "INPUT_CONVERT", 13)) {
             strcpy(inputConversion, SkipSpacesTabs(&input[13]));
             optionSeen[OPTION_INPUT_CONVERT] = TRUE;
-        } else if (STREQ(input, "INPUT")) {
+        } else if (streq(input, "INPUT")) {
             ReadInputFileNames(fpointer, "END_INPUT", 
                                inputSourceP->stdinUsed ?
                                NULL : inputSourceP);
             optionSeen[OPTION_INPUT] = TRUE;
-        } else if (STRNEQ(input, "IO_SERVER_CONVERT", 17)) {
+        } else if (strneq(input, "IO_SERVER_CONVERT", 17)) {
             strcpy(ioConversion, SkipSpacesTabs(&input[17]));
             optionSeen[OPTION_IO_CONVERT] = TRUE;
-        } else if (STRNEQ(input, "IQTABLE", 7)) {
+        } else if (strneq(input, "IQTABLE", 7)) {
             processIqtable(fpointer);
 
             optionSeen[OPTION_IQTABLE] = TRUE;
@@ -784,12 +784,12 @@ processParamLine(char const input[],
         break;
 
     case 'K':
-        if (STRNEQ(input, "KEEP_TEMP_FILES", 15))
+        if (strneq(input, "KEEP_TEMP_FILES", 15))
             keepTempFiles = TRUE;
         break;
         
     case 'N':
-      if (STRNEQ(input, "NIQTABLE", 8)) {
+      if (strneq(input, "NIQTABLE", 8)) {
           readNiqTable(fpointer);
 
           optionSeen[OPTION_NIQTABLE] = TRUE;
@@ -797,7 +797,7 @@ processParamLine(char const input[],
       break;
 
     case 'O':
-        if (STRNEQ(input, "OUTPUT", 6)) {
+        if (strneq(input, "OUTPUT", 6)) {
             const char * const arg = SkipSpacesTabs(&input[6]);
             if ( whichGOP == -1 )
                 strcpy(outputFileName, arg);
@@ -809,45 +809,45 @@ processParamLine(char const input[],
         break;
         
     case 'P':
-        if (STRNEQ(input, "PATTERN", 7)) {
+        if (strneq(input, "PATTERN", 7)) {
             SetFramePattern(SkipSpacesTabs(&input[7]));
             optionSeen[OPTION_PATTERN] = TRUE;
-        } else if (STRNEQ(input, "PIXEL", 5)) {
+        } else if (strneq(input, "PIXEL", 5)) {
             SetPixelSearch(SkipSpacesTabs(&input[5]));
             optionSeen[OPTION_PIXEL] = TRUE;
-        } else if (STRNEQ(input, "PQSCALE", 7)) {
+        } else if (strneq(input, "PQSCALE", 7)) {
             SetPQScale(atoi(SkipSpacesTabs(&input[7])));
             optionSeen[OPTION_PQSCALE] = TRUE;
-        } else if (STRNEQ(input, "PSEARCH_ALG", 11)) {
+        } else if (strneq(input, "PSEARCH_ALG", 11)) {
             SetPSearchAlg(SkipSpacesTabs(&input[11]));
             optionSeen[OPTION_PSEARCH_ALG] = TRUE;
-        } else if (STRNEQ(input, "PARALLEL_TEST_FRAMES", 20)) {
+        } else if (strneq(input, "PARALLEL_TEST_FRAMES", 20)) {
             SetParallelPerfect(FALSE);
             parallelTestFrames = atoi(SkipSpacesTabs(&input[20]));
-        } else if (STRNEQ(input, "PARALLEL_TIME_CHUNKS", 20)) {
+        } else if (strneq(input, "PARALLEL_TIME_CHUNKS", 20)) {
             SetParallelPerfect(FALSE);
             parallelTimeChunks = atoi(SkipSpacesTabs(&input[20]));
-        } else if (STRNEQ(input, "PARALLEL_CHUNK_TAPER", 20)) {
+        } else if (strneq(input, "PARALLEL_CHUNK_TAPER", 20)) {
             SetParallelPerfect(FALSE);
             parallelTimeChunks = -1;
-        } else if (STRNEQ(input, "PARALLEL_PERFECT", 16)) {
+        } else if (strneq(input, "PARALLEL_PERFECT", 16)) {
             SetParallelPerfect(TRUE);
-        } else if (STRNEQ(input, "PARALLEL", 8)) {
+        } else if (strneq(input, "PARALLEL", 8)) {
             ReadMachineNames(fpointer);
             optionSeen[OPTION_PARALLEL] = TRUE;
         }
         break;
         
     case 'R':
-        if (STRNEQ(input, "RANGE", 5)) {
+        if (strneq(input, "RANGE", 5)) {
             processRanges(SkipSpacesTabs(&input[5]));
             optionSeen[OPTION_RANGE] = TRUE;
-        } else if (STRNEQ(input, "REFERENCE_FRAME", 15)) {
+        } else if (strneq(input, "REFERENCE_FRAME", 15)) {
             SetReferenceFrameType(SkipSpacesTabs(&input[15]));
             optionSeen[OPTION_REF_FRAME] = TRUE;
-        } else if (STRNEQ(input, "RSH", 3)) {
+        } else if (strneq(input, "RSH", 3)) {
             SetRemoteShell(SkipSpacesTabs(&input[3]));
-        } else if (STRNEQ(input, "RESIZE", 6)) {
+        } else if (strneq(input, "RESIZE", 6)) {
             const char * const arg = SkipSpacesTabs(&input[6]);
             sscanf(arg, "%dx%d", &outputWidth, &outputHeight);
             outputWidth &= ~(DCTSIZE * 2 - 1);
@@ -857,22 +857,22 @@ processParamLine(char const input[],
         break;
 
     case 'S':
-        if (STRNEQ(input, "SLICES_PER_FRAME", 16)) {
+        if (strneq(input, "SLICES_PER_FRAME", 16)) {
             SetSlicesPerFrame(atoi(SkipSpacesTabs(&input[16])));
             optionSeen[OPTION_SPF] = TRUE;
-        } else if (STRNEQ(input, "SLAVE_CONVERT", 13)) {
+        } else if (strneq(input, "SLAVE_CONVERT", 13)) {
             strcpy(slaveConversion, SkipSpacesTabs(&input[13]));
             optionSeen[OPTION_SLAVE_CONVERT] = TRUE;
-        } else if (STRNEQ(input, "SPECIFICS_FILE", 14)) {
+        } else if (strneq(input, "SPECIFICS_FILE", 14)) {
             strcpy(specificsFile, SkipSpacesTabs(&input[14]));
             specificsOn = TRUE;
             optionSeen[OPTION_SPECIFICS] = TRUE;
-        } else if (STRNEQ(input, "SPECIFICS_DEFINES", 16)) {
+        } else if (strneq(input, "SPECIFICS_DEFINES", 16)) {
             strcpy(specificsDefines, SkipSpacesTabs(&input[17]));
             optionSeen[OPTION_DEFS_SPECIFICS] = TRUE;
-        } else if (STRNEQ(input, "SEQUENCE_SIZE", 13)) {
+        } else if (strneq(input, "SEQUENCE_SIZE", 13)) {
             mult_seq_headers = atoi(SkipSpacesTabs(&input[13]));
-        } else if (STRNEQ(input, "SIZE", 4)) {
+        } else if (strneq(input, "SIZE", 4)) {
             const char * const arg = SkipSpacesTabs(&input[4]);
             sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight);
             realWidth = yuvWidth;
@@ -883,42 +883,42 @@ processParamLine(char const input[],
         break;
 
     case 'T':
-        if (STRNEQ(input, "TUNE", 4)) {
+        if (strneq(input, "TUNE", 4)) {
             tuneingOn = TRUE;
             ParseTuneParam(SkipSpacesTabs(&input[4]));
         }
         break;
 
     case 'U':
-        if (STRNEQ(input, "USER_DATA", 9)) {
+        if (strneq(input, "USER_DATA", 9)) {
             strcpy(userDataFileName, SkipSpacesTabs(&input[9]));
             optionSeen[OPTION_USER_DATA] = TRUE;
         }
         break;
         
     case 'W':
-        if (STRNEQ(input, "WARN_UNDERFLOW", 14))
+        if (strneq(input, "WARN_UNDERFLOW", 14))
             paramP->warnUnderflow = TRUE;
-        if (STRNEQ(input, "WARN_OVERFLOW", 13))
+        if (strneq(input, "WARN_OVERFLOW", 13))
             paramP->warnOverflow = TRUE;
         break;
         
     case 'Y':
-        if (STRNEQ(input, "YUV_SIZE", 8)) {
+        if (strneq(input, "YUV_SIZE", 8)) {
             const char * const arg = SkipSpacesTabs(&input[8]);
             sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight);
             realWidth = yuvWidth;
             realHeight = yuvHeight;
             Fsize_Validate(&yuvWidth, &yuvHeight);
             optionSeen[OPTION_YUV_SIZE] = TRUE;
-        } else if (STRNEQ(input, "Y_SIZE", 6)) {
+        } else if (strneq(input, "Y_SIZE", 6)) {
             const char * const arg = SkipSpacesTabs(&input[6]);
             sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight);
             realWidth = yuvWidth;
             realHeight = yuvHeight;
             Fsize_Validate(&yuvWidth, &yuvHeight);
             optionSeen[OPTION_YUV_SIZE] = TRUE;
-        } else if (STRNEQ(input, "YUV_FORMAT", 10)) {
+        } else if (strneq(input, "YUV_FORMAT", 10)) {
             strcpy(yuvConversion,  SkipSpacesTabs(&input[10]));
             optionSeen[OPTION_YUV_FORMAT] = TRUE;
         }
@@ -928,26 +928,21 @@ processParamLine(char const input[],
 
 
 
-/*===========================================================================*
- *
- * ReadParamFile
- *
- *	read the parameter file
- *	function is ENCODE_FRAMES, COMBINE_GOPS, or COMBINE_FRAMES, and
- *	    will slightly modify the procedure's behavior as to what it
- *	    is looking for in the parameter file
- *
- * SIDE EFFECTS:    sets parameters accordingly, as well as machine info for
- *		    parallel execution and input file names
- *
- *===========================================================================*/
 void
-ReadParamFile(const char *    const fileName, 
-              int             const function,
-              struct params * const paramP) {
+ReadParamFile(const char *         const fileName, 
+              majorProgramFunction const function,
+              struct params *      const paramP) {
+/*----------------------------------------------------------------------------
+   Read the parameter file 'fileName' as *paramP.
 
-  FILE *fpointer;
-  char    buffer[256];
+   'function' slightly modifies our behavior as to what it is looking for
+   in the parameter file.
+
+   As a side effect, set machine info for parallel execution and input
+   file names
+-----------------------------------------------------------------------------*/
+  FILE * fpointer;
+  char buffer[256];
   bool yuvUsed;
   struct inputSource * inputSourceP;
       /* Contents of INPUT section */
diff --git a/converter/ppm/ppmtompeg/pframe.c b/converter/ppm/ppmtompeg/pframe.c
index e72fe5d6..de91e32c 100644
--- a/converter/ppm/ppmtompeg/pframe.c
+++ b/converter/ppm/ppmtompeg/pframe.c
@@ -60,8 +60,6 @@ static int32    totalTime = 0;
 static int      qscaleP;
 static float    totalSNR = 0.0;
 static float    totalPSNR = 0.0;
-extern Block    **dct, **dctr, **dctb;
-extern dct_data_type   **dct_data;
 
 /*=====================*
  * INTERNAL PROCEDURES *
diff --git a/converter/ppm/ppmtompeg/ppmtompeg.c b/converter/ppm/ppmtompeg/ppmtompeg.c
index 2296e2cb..f53ffea9 100644
--- a/converter/ppm/ppmtompeg/ppmtompeg.c
+++ b/converter/ppm/ppmtompeg/ppmtompeg.c
@@ -33,7 +33,6 @@
 #define _BSD_SOURCE   /* Make sure strdup() is in string.h */
 
 #include <assert.h>
-#include <sys/utsname.h>
 
 #include "all.h"
 #include "mtypes.h"
@@ -98,7 +97,7 @@ void init_fdct _ANSI_ARGS_((void));
 
 struct cmdlineInfo {
     bool         childProcess;
-    int          function;
+    majorProgramFunction function;
     const char * masterHostname;
     int          masterPortNumber;
     unsigned int outputFrames;
@@ -130,36 +129,33 @@ parseArgs(int     const argc,
     
     /* parse the arguments */
     idx = 1;
-    while ( idx < argc-1 ) {
-        if ( argv[idx][0] != '-' )
+    while (idx < argc-1) {
+        if (argv[idx][0] != '-')
             pm_error("argument '%s', which must be an option because "
                      "it is not the last argument, "
                      "does not start with '-'", argv[idx]);
 
-        if ( strcmp(argv[idx], "-stat") == 0 ) {
-            if ( idx+1 < argc-1 ) {
+        if (streq(argv[idx], "-stat")) {
+            if (idx+1 < argc-1) {
                 SetStatFileName(argv[idx+1]);
                 idx += 2;
-            } else {
+            } else
                 pm_error("Invalid -stat option");
-            }
-        } else if ( strcmp(argv[idx], "-gop") == 0 ) {
-            if ((cmdlineP->function != ENCODE_FRAMES) || 
-                (cmdlineP->specificFrames))
+        } else if (streq(argv[idx], "-gop")) {
+            if (cmdlineP->function != ENCODE_FRAMES || 
+                cmdlineP->specificFrames)
                 pm_error("Invalid -gop option");
             
-            if ( idx+1 < argc-1 ) {
+            if (idx+1 < argc-1) {
                 whichGOP = atoi(argv[idx+1]);
                 idx += 2;
-            } else {
+            } else
                 pm_error("Invalid -gop option");
-            }
-        } else if ( strcmp(argv[idx], "-frames") == 0 ) {
-            if ( (cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) ) {
+        } else if (streq(argv[idx], "-frames")) {
+            if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1)
                 pm_error("invalid -frames option");
-            }
 
-            if ( idx+2 < argc-1 ) {
+            if (idx+2 < argc-1) {
                 int const frameStart = atoi(argv[idx+1]);
                 int const frameEnd = atoi(argv[idx+2]);
 
@@ -177,23 +173,23 @@ parseArgs(int     const argc,
                 idx += 3;
             } else
                 pm_error("-frames needs to be followed by two values");
-        } else if (strcmp(argv[idx], "-combine_gops") == 0) {
-            if ((cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) || 
-                (cmdlineP->specificFrames)) {
+        } else if (streq(argv[idx], "-combine_gops")) {
+            if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1 || 
+                cmdlineP->specificFrames) {
                 pm_error("Invalid -combine_gops option");
             }
 
             cmdlineP->function = COMBINE_GOPS;
-            idx++;
-        } else if (strcmp(argv[idx], "-combine_frames") == 0) {
-            if ((cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) ||
-                (cmdlineP->specificFrames))
+            ++idx;
+        } else if (streq(argv[idx], "-combine_frames")) {
+            if (cmdlineP->function != ENCODE_FRAMES || whichGOP != -1 ||
+                cmdlineP->specificFrames)
                 pm_error("Invalid -combine_frames option");
 
             cmdlineP->function = COMBINE_FRAMES;
-            idx++;
-        } else if ( strcmp(argv[idx], "-child") == 0 ) {
-            if ( idx+7 < argc-1 ) {
+            ++idx;
+        } else if (streq(argv[idx], "-child")) {
+            if (idx+7 < argc-1) {
                 int combinePortNumber;
                     /* This used to be important information, when the child
                        notified the combine server.  Now the master notifies
@@ -215,104 +211,94 @@ parseArgs(int     const argc,
 
             cmdlineP->childProcess = TRUE;
             idx += 8;
-        } else if ( strcmp(argv[idx], "-io_server") == 0 ) {
-            if ( idx+2 < argc-1 ) {
-                cmdlineP->masterHostname = argv[idx+1];
+        } else if (streq(argv[idx], "-io_server")) {
+            if (idx+2 < argc-1) {
+                cmdlineP->masterHostname   = argv[idx+1];
                 cmdlineP->masterPortNumber = atoi(argv[idx+2]);
-            } else {
+            } else
                 pm_error("Invalid -io_server option");
-            }
 
             ioServer = TRUE;
             idx += 3;
-        } else if ( strcmp(argv[idx], "-output_server") == 0 ) {
-            if ( idx+3 < argc-1 ) {
-                cmdlineP->masterHostname = argv[idx+1];
+        } else if (streq(argv[idx], "-output_server")) {
+            if (idx+3 < argc-1) {
+                cmdlineP->masterHostname   = argv[idx+1];
                 cmdlineP->masterPortNumber = atoi(argv[idx+2]);
-                cmdlineP->outputFrames = atoi(argv[idx+3]);
-            } else {
+                cmdlineP->outputFrames     = atoi(argv[idx+3]);
+            } else
                 pm_error("-output_server option requires 3 option values.  "
-                         "You specified %d", argc-1 - idx);
-            }
+                         "You specified %u", argc-1 - idx);
 
             outputServer = TRUE;
             idx += 4;
-        } else if ( strcmp(argv[idx], "-decode_server") == 0 ) {
-            if ( idx+3 < argc-1 ) {
-                cmdlineP->masterHostname = argv[idx+1];
+        } else if (streq(argv[idx], "-decode_server")) {
+            if (idx+3 < argc-1) {
+                cmdlineP->masterHostname   = argv[idx+1];
                 cmdlineP->masterPortNumber = atoi(argv[idx+2]);
-                cmdlineP->outputFrames = atoi(argv[idx+3]);
-            } else {
+                cmdlineP->outputFrames     = atoi(argv[idx+3]);
+            } else
                 pm_error("Invalid -decode_server option");
-            }
 
             cmdlineP->function = COMBINE_FRAMES;
             decodeServer = TRUE;
             idx += 4;
-        } else if ( strcmp(argv[idx], "-nice") == 0 ) {
+        } else if (streq(argv[idx], "-nice")) {
             niceProcesses = TRUE;
             idx++;
-        } else if ( strcmp(argv[idx], "-max_machines") == 0 ) {
-            if ( idx+1 < argc-1 ) {
+        } else if (streq(argv[idx], "-max_machines")) {
+            if (idx+1 < argc-1) {
                 cmdlineP->maxMachines = atoi(argv[idx+1]);
-            } else {
+            } else
                 pm_error("Invalid -max_machines option");
-            }
 
             idx += 2;
-        } else if ( strcmp(argv[idx], "-quiet") == 0 ) {
-            if ( idx+1 < argc-1 ) {
+        } else if (streq(argv[idx], "-quiet")) {
+            if (idx+1 < argc-1)
                 quietTime = atoi(argv[idx+1]);
-            } else {
+            else
                 pm_error("Invalid -quiet option");
-            }
 
             idx += 2;
-        } else if ( strcmp(argv[idx], "-realquiet") == 0 ) {
+        } else if (streq(argv[idx], "-realquiet")) {
             realQuiet = TRUE;
-            idx++;
-        } else if (( strcmp(argv[idx], "-float_dct") == 0 ) ||
-                   ( strcmp(argv[idx], "-float-dct") == 0 )) {
+            ++idx;
+        } else if (streq(argv[idx], "-float_dct") ||
+                   streq(argv[idx], "-float-dct")) {
             pureDCT = TRUE;
             init_idctref();
             init_fdct();
-            idx++;
-        } else if ( strcmp(argv[idx], "-no_frame_summary") == 0 ) {
-            if ( idx < argc-1 ) {
+            ++idx;
+        } else if (streq(argv[idx], "-no_frame_summary")) {
+            if (idx < argc-1)
                 noFrameSummaryOption = TRUE;
-            } else {
+            else
                 pm_error("Invalid -no_frame_summary option");
-            }
-
-            idx++;
-        } else if ( strcmp(argv[idx], "-snr") == 0 ) {
+            ++idx;
+        } else if (streq(argv[idx], "-snr")) {
             printSNR = TRUE;
-            idx++;
-        } else if ( strcmp(argv[idx], "-mse") == 0 ) {
-            printSNR =  printMSE = TRUE;
-            idx++;
-        } else if ( strcmp(argv[idx], "-debug_sockets") == 0 ) {
+            ++idx;
+        } else if (streq(argv[idx], "-mse")) {
+            printSNR = printMSE = TRUE;
+            ++idx;
+        } else if (streq(argv[idx], "-debug_sockets")) {
             debugSockets = TRUE;
-            idx++;
-        } else if ( strcmp(argv[idx], "-debug_machines") == 0 ) {
+            ++idx;
+        } else if (streq(argv[idx], "-debug_machines")) {
             debugMachines = TRUE;
-            idx++;
-        } else if ( strcmp(argv[idx], "-bit_rate_info") == 0 ) {
-            if ( idx+1 < argc-1 ) {
+            ++idx;
+        } else if (streq(argv[idx], "-bit_rate_info")) {
+            if (idx+1 < argc-1) {
                 bitRateInfoOption = TRUE;
                 SetBitRateFileName(argv[idx+1]);
                 idx += 2;
-            } else {
+            } else
                 pm_error("Invalid -bit_rate_info option");
-            }
-        } else if ( strcmp(argv[idx], "-mv_histogram") == 0 ) {
+        } else if (streq(argv[idx], "-mv_histogram")) {
             computeMVHist = TRUE;
-            idx++;
-        } else {
+            ++idx;
+        } else
             pm_error("Unrecognized option: '%s'", argv[idx]);
-        }
     }
-
     cmdlineP->paramFileName = argv[argc-1];
 }
 
@@ -686,8 +672,8 @@ main(int argc, char **argv) {
         DecodeServer(cmdline.outputFrames, outputFileName, 
                      cmdline.masterHostname, cmdline.masterPortNumber);
     } else {
-        if ((!cmdline.specificFrames) &&
-            ((numMachines == 0) || (cmdline.function != ENCODE_FRAMES)) ) {
+        if (!cmdline.specificFrames &&
+            (numMachines == 0 || cmdline.function != ENCODE_FRAMES) ) {
             ofP = fopen(outputFileName, "wb");
             if (ofP == NULL)
                 pm_error("Could not open output file!");
@@ -695,7 +681,7 @@ main(int argc, char **argv) {
             ofP = NULL;
         
         if (cmdline.function == ENCODE_FRAMES) {
-            if ((numMachines == 0) || (cmdline.specificFrames)) {
+            if (numMachines == 0 || cmdline.specificFrames) {
                 encodeFrames(params.inputSourceP,
                              cmdline.childProcess, 
                              cmdline.masterHostname, cmdline.masterPortNumber,
diff --git a/converter/ppm/ppmtompeg/psearch.c b/converter/ppm/ppmtompeg/psearch.c
index aea1a29b..83c62d04 100644
--- a/converter/ppm/ppmtompeg/psearch.c
+++ b/converter/ppm/ppmtompeg/psearch.c
@@ -16,6 +16,8 @@
 #include "prototypes.h"
 #include "fsize.h"
 #include "param.h"
+#include "subsample.h"
+#include "block.h"
 
 
 /*==================*
diff --git a/converter/ppm/ppmtompeg/rate.c b/converter/ppm/ppmtompeg/rate.c
index 3940956c..1a44cb95 100644
--- a/converter/ppm/ppmtompeg/rate.c
+++ b/converter/ppm/ppmtompeg/rate.c
@@ -50,7 +50,6 @@
 
 #include <assert.h>
 #include <sys/types.h>
-#include <sys/times.h>
 
 #include "ppm.h"
 #include "nstring.h"
diff --git a/converter/ppm/ppmtompeg/specifics.c b/converter/ppm/ppmtompeg/specifics.c
index c7bbfb5b..38e8fc43 100644
--- a/converter/ppm/ppmtompeg/specifics.c
+++ b/converter/ppm/ppmtompeg/specifics.c
@@ -47,12 +47,6 @@
 #include <string.h>
 #include "prototypes.h"
 
-/*====================*
- * System Information *
- *====================*/
-
-#define CPP_LOC "/lib/cpp"
-
 /*==================*
  * GLOBAL VARIABLES *
  *==================*/
@@ -153,26 +147,27 @@ static char version = -1;
  *
  *================================================================
  */
-void Specifics_Init()
-{
-  char command[1100];
-  FILE *specificsFP;
-  
-  sprintf(command, "/bin/rm -f %s.cpp", specificsFile);
-  system(command);
-  sprintf(command, "%s -P %s %s %s.cpp",
-	  CPP_LOC, specificsDefines, specificsFile, specificsFile);
-  system(command);
-  strcat(specificsFile, ".cpp");
-  if ((specificsFP = fopen(specificsFile, "r")) == NULL) {
-    fprintf(stderr, "Error with specifics file, cannot open %s\n", specificsFile);
-    exit(1);
-  }
-  printf("Specifics file: %s\n", specificsFile);
-  Parse_Specifics_File(specificsFP);
-  sprintf(command, "/bin/rm -f %s.cpp", specificsFile);
-  system(command);
+void
+Specifics_Init() {
 
+    char command[1100];
+    FILE *specificsFP;
+  
+    sprintf(command, "rm -f %s.cpp", specificsFile);
+    system(command);
+    sprintf(command, "cpp -P %s %s %s.cpp",
+            specificsDefines, specificsFile, specificsFile);
+    system(command);
+    strcat(specificsFile, ".cpp");
+    if ((specificsFP = fopen(specificsFile, "r")) == NULL) {
+        fprintf(stderr, "Error with specifics file, cannot open %s\n",
+                specificsFile);
+        exit(1);
+    }
+    printf("Specifics file: %s\n", specificsFile);
+    Parse_Specifics_File(specificsFP);
+    sprintf(command, "rm -f %s.cpp", specificsFile);
+    system(command);
 }
 
 
diff --git a/converter/ppm/ppmtompeg/subsample.c b/converter/ppm/ppmtompeg/subsample.c
index 5ec71814..69401a1d 100644
--- a/converter/ppm/ppmtompeg/subsample.c
+++ b/converter/ppm/ppmtompeg/subsample.c
@@ -43,6 +43,7 @@
 #include "bitio.h"
 #include "prototypes.h"
 
+#include "subsample.h"
 
 
 static void
diff --git a/converter/ppm/ppmtopcx.c b/converter/ppm/ppmtopcx.c
index bdcfc5c7..edc44149 100644
--- a/converter/ppm/ppmtopcx.c
+++ b/converter/ppm/ppmtopcx.c
@@ -15,6 +15,7 @@
 */
 #include <assert.h>
 
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "shhopt.h"
 #include "mallocvar.h"
diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c
index e2428fb6..1b9f2d5c 100644
--- a/converter/ppm/ppmtopict.c
+++ b/converter/ppm/ppmtopict.c
@@ -282,15 +282,8 @@ int i;
 	(void) putc(i & 0xff, fd);
 }
 
-#if __STDC__
 static void
 putLong( FILE *fd, long i )
-#else /*__STDC__*/
-static void
-putLong(fd, i)
-FILE *fd;
-long i;
-#endif /*__STDC__*/
 {
 	(void) putc((int)((i >> 24) & 0xff), fd);
 	(void) putc(((int)(i >> 16) & 0xff), fd);
@@ -405,7 +398,7 @@ char *packed;
 		*p++ = counttochar(count);
 
 	packcols = p - packed;		/* how many did we write? */
-	if (cols > 250)
+	if (cols > 200)
 	{
 		putShort(fd, packcols);
 		oc = packcols + 2;
@@ -443,7 +436,7 @@ char *packed;
 	bzero(aux, cols); /* aux?? */
 #endif /*notdef*/
 	bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
-	if (bc > 250)
+	if (bc > 200)
 	{
 		putShort(fd, bc);
 		oc = bc + 2;
diff --git a/converter/ppm/ppmtopj.c b/converter/ppm/ppmtopj.c
index 5d449f7a..d116773f 100644
--- a/converter/ppm/ppmtopj.c
+++ b/converter/ppm/ppmtopj.c
@@ -121,7 +121,7 @@ char *argv[];
 		{
 		++argn;
 		for (r = 0; rmode[r] != NULL; r++)
-		     if (STREQ(rmode[r], argv[argn]))
+		     if (streq(rmode[r], argv[argn]))
 			 break;
 		if (rmode[r] != NULL)
 		    render_mode = r;
@@ -131,9 +131,9 @@ char *argv[];
 	    else if ( pm_keymatch(argv[argn],"-back",2) && argn + 1 < argc )
 		{
 		++argn;
-		if (STREQ(argv[argn], "dark"))
+		if (streq(argv[argn], "dark"))
 		    back_scale = C_BACK_SCALE_DARK;
-		else if (STREQ(argv[argn], "lite"))
+		else if (streq(argv[argn], "lite"))
 		    back_scale = C_BACK_SCALE_LIGHT;
 		else
 		    pm_usage(usage);
diff --git a/converter/ppm/ppmtopjxl.c b/converter/ppm/ppmtopjxl.c
index 72d299fd..91cd1a45 100644
--- a/converter/ppm/ppmtopjxl.c
+++ b/converter/ppm/ppmtopjxl.c
@@ -1,4 +1,4 @@
-/* ppmtopcl.c - convert portable pixmap into PCL language for HP PaintJet and
+/* ppmtopcl.c - convert PPM into PCL language for HP PaintJet and
  *              PaintJet XL color printers
  * AJCD 12/3/91
  * 
@@ -17,8 +17,8 @@
 #include <string.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
 #include "nstring.h"
+#include "ppm.h"
 
 #define MAXCOLORS 1024
 
@@ -106,318 +106,306 @@ putbits(b, n) {
       int xo = 0;
       int xc = 0;
       if (cnt+n > 8) {  /* overflowing current byte? */
-	 xc = cnt + n - 8;
-	 xo = (b & ~(-1 << xc)) << (8-xc);
-	 n -= xc;
-	 b >>= xc;
+     xc = cnt + n - 8;
+     xo = (b & ~(-1 << xc)) << (8-xc);
+     n -= xc;
+     b >>= xc;
       }
       cnt += n;
       out |= (b & ~(-1 << n)) << (8-cnt);
       if (cnt >= 8) {
-	 inrow[num++] = out;
-	 out = xo;
-	 cnt = xc;
+     inrow[num++] = out;
+     out = xo;
+     cnt = xc;
       }
    } else { /* flush row */
       int i;
       if (cnt) {
-	 inrow[num++] = out;
-	 out = cnt = 0;
+     inrow[num++] = out;
+     out = cnt = 0;
       }
       for (; num > 0 && inrow[num-1] == 0; num--); /* remove trailing zeros */
       printf("\033*b"); 
       if (num && !nopack) {            /* TIFF 4.0 packbits encoding */
-	 int start = 0;
-	 int next;
-	 runcnt[start] = 0;
-	 for (i = 1; i < num; i++) {
-	    if (inrow[i] == inrow[i-1]) {
-	       if (runcnt[start] <= 0 && runcnt[start] > -127)
-		  runcnt[start]--;
-	       else
-		  runcnt[start = i] = 0;
-	    } else {
-	       if (runcnt[start] >= 0 && runcnt[start] < 127)
-		  runcnt[start]++;
-	       else
-		  runcnt[start = i] = 0;
-	    }
-	 }
-	 start = 0;
-	 for (i = 0; i < num; i = next) {
-	    int count = runcnt[i];
-	    int from = i;
-	    if (count >= 0) { /* merge two-byte runs */
-	       for (;;) {
-		  next = i+1+runcnt[i];
-		  if(next >= num || runcnt[next] < 0 ||
-		     count+runcnt[next]+1 > 127)
-		     break;
-		  count += runcnt[next]+1;
-		  i = next;
-	       }
-	    }
-	    next =  i + 1 + ((runcnt[i] < 0) ? -runcnt[i] : runcnt[i]);
-	    if (next < num && count > 0 &&
-		runcnt[next] < 0 && runcnt[next] > -127) {
-	       count--;
-	       next--;
-	       runcnt[next] = runcnt[next+1]-1;
-	    }
-	    outrow[start++] = count;
-	    if (count >= 0) {
-	       while (count-- >= 0)
-		  outrow[start++] = inrow[from++];
-	    } else
-	       outrow[start++] = inrow[from];
-	 }
-	 if (start < num) {
-	    num = start;
-	    if (!pack) {
-	       printf("2m");
-	       pack = 1;
-	    }
-	 } else {
-	    if (pack) {
-	       printf("0m");
-	       pack = 0;
-	    }
-	 }
+     int start = 0;
+     int next;
+     runcnt[start] = 0;
+     for (i = 1; i < num; i++) {
+        if (inrow[i] == inrow[i-1]) {
+           if (runcnt[start] <= 0 && runcnt[start] > -127)
+          runcnt[start]--;
+           else
+          runcnt[start = i] = 0;
+        } else {
+           if (runcnt[start] >= 0 && runcnt[start] < 127)
+          runcnt[start]++;
+           else
+          runcnt[start = i] = 0;
+        }
+     }
+     start = 0;
+     for (i = 0; i < num; i = next) {
+        int count = runcnt[i];
+        int from = i;
+        if (count >= 0) { /* merge two-byte runs */
+           for (;;) {
+          next = i+1+runcnt[i];
+          if(next >= num || runcnt[next] < 0 ||
+             count+runcnt[next]+1 > 127)
+             break;
+          count += runcnt[next]+1;
+          i = next;
+           }
+        }
+        next =  i + 1 + ((runcnt[i] < 0) ? -runcnt[i] : runcnt[i]);
+        if (next < num && count > 0 &&
+        runcnt[next] < 0 && runcnt[next] > -127) {
+           count--;
+           next--;
+           runcnt[next] = runcnt[next+1]-1;
+        }
+        outrow[start++] = count;
+        if (count >= 0) {
+           while (count-- >= 0)
+          outrow[start++] = inrow[from++];
+        } else
+           outrow[start++] = inrow[from];
+     }
+     if (start < num) {
+        num = start;
+        if (!pack) {
+           printf("2m");
+           pack = 1;
+        }
+     } else {
+        if (pack) {
+           printf("0m");
+           pack = 0;
+        }
+     }
       }
       printf("%dW", num);
       for (i = 0; i < num; i++)
-	 putchar(pack ? outrow[i] : inrow[i]);
+     putchar(pack ? outrow[i] : inrow[i]);
       num = 0; /* new row */
    }
 }
 
+
+
 int
-main(argc, argv)
-     int argc;
-     char *argv[];
-{
-   FILE *ifd;
-   register pixel **pixels, *pixrow;
-   register int  row, col, bpp, i;
-   int rows, cols;
-   pixval maxval;
-   int bpr, bpg, bpb;
-   int render;
-   int colors, pclindex;
-   colorhist_vector chv;
-   colorhash_table cht;
+main(int argc, const char * argv[]) {
+
+    FILE * ifP;
+    pixel ** pixels;
+    unsigned int row;
+    unsigned int bpp;
+    int rows, cols;
+    pixval maxval;
+    int bpr, bpg, bpb;
+    int render;
+    int colors, pclindex;
+    colorhist_vector chv;
+    colorhash_table cht;
    
-   ppm_init( &argc, argv );
-
-   while (argc > 1 && argv[1][0] == '-') {
-      char *c;
-      for (i = 0; i < sizeof(options)/sizeof(struct options); i++) {
-	 if (pm_keymatch(argv[1], options[i].name,
-			 MIN(strlen(argv[1]), strlen(options[i].name)))) {
-	    switch (options[i].type) {
-	    case DIM:
-	       if (++argv, --argc == 1)
-		  pm_usage(usage);
-	       for (c = argv[1]; ISDIGIT(*c); c++);
-	       if (c[0] == 'p' && c[1] == 't') /* points */
-		  *(int *)(options[i].value) = atoi(argv[1])*10;
-	       else if (c[0] == 'd' && c[1] == 'p') /* decipoints */
-		  *(int *)(options[i].value) = atoi(argv[1]);
-	       else if (c[0] == 'i' && c[1] == 'n') /* inches */
-		  *(int *)(options[i].value) = atoi(argv[1])*720;
-	       else if (c[0] == 'c' && c[1] == 'm') /* centimetres */
-		  *(int *)(options[i].value) = atoi(argv[1])*283.46457;
-	       else if (!c[0]) /* dots */
-		  *(int *)(options[i].value) = atoi(argv[1])*4;
-	       else
-		  pm_error("illegal unit of measure %s", c);
-	       break;
-	    case REAL:
-	       if (++argv, --argc == 1)
-		  pm_usage(usage);
-	       *(double *)(options[i].value) = atof(argv[1]);
-	       break;
-	    case BOOL:
-	       *(int *)(options[i].value) = 1;
-	       break;
-	    }
-	    break;
-	 }
-      }
-      if (i >= sizeof(options)/sizeof(struct options))
-	 pm_usage(usage);
-      argv++; argc--;
-   }
-   if (argc > 2)
-      pm_usage(usage);
-   else if (argc == 2)
-      ifd = pm_openr(argv[1]);
-   else
-      ifd = stdin ;
-
-   /* validate arguments */
-   if (diffuse+cluster+dither > 1)
-      pm_error("only one of -diffuse, -dither and -cluster may be used");
-   render = diffuse ? 4 : dither ? 3 : cluster ? 7 : 0;
-
-   if (xsize != 0.0 && xscale != 0.0)
-      pm_error("only one of -xsize and -xscale may be used");
-
-   if (ysize != 0.0 && yscale != 0.0)
-      pm_error("only one of -ysize and -yscale may be used");
-
-   pixels = ppm_readppm( ifd, &cols, &rows, &maxval );
-   pm_close( ifd );
-
-   /* limit checks */
-   if (cols > PCL_MAXWIDTH || rows > PCL_MAXHEIGHT)
-      pm_error("image too large; reduce with ppmscale");
-   if (maxval > PCL_MAXVAL)
-      pm_error("color range too large; reduce with ppmcscale");
-
-   /* Figure out the colormap. */
-   fprintf( stderr, "(Computing colormap..." ); fflush( stderr );
-   chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
-   if ( chv == (colorhist_vector) 0 )
-      pm_error("too many colors; reduce with pnmquant");
-   fprintf( stderr, "  Done.  %d colors found.)\n", colors );
-
-   /* And make a hash table for fast lookup. */
-   cht = ppm_colorhisttocolorhash( chv, colors );
-
-   /* work out color downloading mode */
-   pclindex = bitsperpixel(colors);
-   if (pclindex > 8) /* can't use indexed mode */
-      pclindex = 0;
-   else
-      switch (pclindex) { /* round up to 1,2,4,8 */
-      case 0: /* direct mode (no palette) */
-	 bpp = bitsperpixel(maxval); /* bits per pixel */
-	 bpg = bpp; bpb = bpp;
-	 bpp = (bpp*3+7)>>3;     /* bytes per pixel now */
-	 bpr = (bpp<<3)-bpg-bpb; 
-	 bpp *= cols;            /* bytes per row now */
-	 break;
-      case 5:         pclindex++;
-      case 6:         pclindex++;
-      case 3: case 7: pclindex++;
-      default:
-	 bpp = 8/pclindex;
-	 bpp = (cols+bpp-1)/bpp;      /* bytes per row */
-      }
+    pm_proginit(&argc, argv);
 
-   if ((inrow = (char *)malloc((unsigned)bpp)) == NULL ||
-       (outrow = (char *)malloc((unsigned)bpp*2)) == NULL ||
-       (runcnt = (signed char *)malloc((unsigned)bpp)) == NULL)
-      pm_error("can't allocate space for row");
-
-   /* set up image details */
-   if (xscale != 0.0)
-      xsize = cols * xscale * 4;
-   if (yscale != 0.0)
-      ysize = rows * yscale * 4;
-
-#ifdef DEBUG
-   fprintf(stderr, "dark    =%d\n", dark);
-   fprintf(stderr, "diffuse =%d\n", diffuse);
-   fprintf(stderr, "dither  =%d\n", dither);
-   fprintf(stderr, "cluster =%d\n", cluster);
-   fprintf(stderr, "quality =%d\n", quality);
-   fprintf(stderr, "xsize   =%d\n", xsize);
-   fprintf(stderr, "ysize   =%d\n", ysize);
-   fprintf(stderr, "xshift  =%d\n", xshift);
-   fprintf(stderr, "yshift  =%d\n", yshift);
-   fprintf(stderr, "xscale  =%lf\n", xscale);
-   fprintf(stderr, "yscale  =%lf\n", yscale);
-   fprintf(stderr, "gamma   =%lf\n", gamma_val);
-   fprintf(stderr, "pclindex   =%d\n", pclindex);
-   fprintf(stderr, "nopack  =%d\n", nopack);
-#endif
+    while (argc > 1 && argv[1][0] == '-') {
+        unsigned int i;
+        for (i = 0; i < sizeof(options)/sizeof(struct options); i++) {
+            if (pm_keymatch(argv[1], options[i].name,
+                            MIN(strlen(argv[1]), strlen(options[i].name)))) {
+                const char * c;
+                switch (options[i].type) {
+                case DIM:
+                    if (++argv, --argc == 1)
+                        pm_usage(usage);
+                    for (c = argv[1]; ISDIGIT(*c); c++);
+                    if (c[0] == 'p' && c[1] == 't') /* points */
+                        *(int *)(options[i].value) = atoi(argv[1])*10;
+                    else if (c[0] == 'd' && c[1] == 'p') /* decipoints */
+                        *(int *)(options[i].value) = atoi(argv[1]);
+                    else if (c[0] == 'i' && c[1] == 'n') /* inches */
+                        *(int *)(options[i].value) = atoi(argv[1])*720;
+                    else if (c[0] == 'c' && c[1] == 'm') /* centimetres */
+                        *(int *)(options[i].value) = atoi(argv[1])*283.46457;
+                    else if (!c[0]) /* dots */
+                        *(int *)(options[i].value) = atoi(argv[1])*4;
+                    else
+                        pm_error("illegal unit of measure %s", c);
+                    break;
+                case REAL:
+                    if (++argv, --argc == 1)
+                        pm_usage(usage);
+                    *(double *)(options[i].value) = atof(argv[1]);
+                    break;
+                case BOOL:
+                    *(int *)(options[i].value) = 1;
+                    break;
+                }
+                break;
+            }
+        }
+        if (i >= sizeof(options)/sizeof(struct options))
+            pm_usage(usage);
+        argv++; argc--;
+    }
+    if (argc > 2)
+        pm_usage(usage);
+    else if (argc == 2)
+        ifP = pm_openr(argv[1]);
+    else
+        ifP = stdin ;
+
+    /* validate arguments */
+    if (diffuse+cluster+dither > 1)
+        pm_error("only one of -diffuse, -dither and -cluster may be used");
+    render = diffuse ? 4 : dither ? 3 : cluster ? 7 : 0;
+
+    if (xsize != 0.0 && xscale != 0.0)
+        pm_error("only one of -xsize and -xscale may be used");
+
+    if (ysize != 0.0 && yscale != 0.0)
+        pm_error("only one of -ysize and -yscale may be used");
+
+    pixels = ppm_readppm(ifP, &cols, &rows, &maxval);
+    pm_close(ifP);
+
+    /* limit checks */
+    if (cols > PCL_MAXWIDTH || rows > PCL_MAXHEIGHT)
+        pm_error("image too large; reduce with ppmscale");
+    if (maxval > PCL_MAXVAL)
+        pm_error("color range too large; reduce with ppmcscale");
 
-   /* write PCL header */
+    /* Figure out the colormap. */
+    pm_message("Computing colormap...");
+    chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
+    if (!chv)
+        pm_error("too many colors; reduce with pnmquant");
+    pm_message("... Done.  %u colors found.", colors);
+
+    /* And make a hash table for fast lookup. */
+    cht = ppm_colorhisttocolorhash(chv, colors);
+
+    /* work out color downloading mode */
+    pclindex = bitsperpixel(colors);
+    if (pclindex > 8) /* can't use indexed mode */
+        pclindex = 0;
+    else {
+        switch (pclindex) { /* round up to 1,2,4,8 */
+        case 0: /* direct mode (no palette) */
+            bpp = bitsperpixel(maxval); /* bits per pixel */
+            bpg = bpp; bpb = bpp;
+            bpp = (bpp*3+7)>>3;     /* bytes per pixel now */
+            bpr = (bpp<<3)-bpg-bpb; 
+            bpp *= cols;            /* bytes per row now */
+            break;
+        case 5:         pclindex++;
+        case 6:         pclindex++;
+        case 3: case 7: pclindex++;
+        default:
+            bpp = 8/pclindex;
+            bpp = (cols+bpp-1)/bpp;      /* bytes per row */
+        }
+    }
+    inrow = (char *)malloc((unsigned)bpp);
+    outrow = (char *)malloc((unsigned)bpp*2);
+    runcnt = (signed char *)malloc((unsigned)bpp);
+    if (inrow == NULL || outrow == NULL || runcnt == NULL)
+        pm_error("can't allocate space for row");
+
+    /* set up image details */
+    if (xscale != 0.0)
+        xsize = cols * xscale * 4;
+    if (yscale != 0.0)
+        ysize = rows * yscale * 4;
+
+    /* write PCL header */
 #if 0
-   printf("\033&l26A");                         /* paper size */
+    printf("\033&l26A");                         /* paper size */
 #endif
-   printf("\033*r%ds%dT", cols, rows);          /* source width, height */
-   if (xshift != 0 || yshift != 0)
-      printf("\033&a%+dh%+dV", xshift, yshift); /* xshift, yshift */
-   if (quality)
-      printf("\033*o%dQ", quality);             /* print quality */
-   printf("\033*t");
-   if (xsize == 0 && ysize == 0)
-      printf("180r");                   /* resolution */
-   else {                               /* destination width, height */
-      if (xsize != 0)
-	 printf("%dh", xsize);
-      if (ysize != 0)
-	 printf("%dv", ysize);
-   }
-   if (gamma_val != 0)
-      printf("%.3fi", gamma_val);                    /* gamma correction */
-   if (dark)
-      printf("%dk", dark);              /* scaling algorithms */
-   printf("%dJ", render);               /* rendering algorithm */
-   printf("\033*v18W");                           /* configure image data */
-      putchar(0); /* relative colors */
-      putchar(pclindex ? 1 : 3); /* index/direct pixel mode */
-      putchar(pclindex); /* ignored in direct pixel mode */
-      if (pclindex) {
-	 putchar(0);
-	 putchar(0);
-	 putchar(0);
-      } else {
-	 putchar(bpr); /* bits per red */
-	 putchar(bpg); /* bits per green */
-	 putchar(bpb); /* bits per blue */
-      }
-      putword(maxval); /* max red reference */
-      putword(maxval); /* max green reference */
-      putword(maxval); /* max blue reference */
-      putword(0); /* min red reference */
-      putword(0); /* min green reference */
-      putword(0); /* min blue reference */
-   if (pclindex) {                        /* set palette */
-      for (i = 0; i < colors; i++) {
-	 int r, g, b;
-	 r = PPM_GETR( chv[i].color );
-	 g = PPM_GETG( chv[i].color );
-	 b = PPM_GETB( chv[i].color );
-	 if (i == 0)
-	    printf("\033*v");
-	 if (r)
-	    printf("%da", r);
-	 if (g)
-	    printf("%db", g);
-	 if (b)
-	    printf("%dc", b);
-	 if (i == colors-1)
-	    printf("%dI", i);    /* assign color index */
-	 else
-	    printf("%di", i);    /* assign color index */
-      }
-   }
-   ppm_freecolorhist( chv );
-
-   /* start raster graphics at CAP */
-   printf("\033*r%dA", (xsize != 0 || ysize != 0) ? 3 : 1);
-
-   for (row = 0; row < rows; row++) {
-      if (pclindex) { /* indexed color mode */
-	 int out, cnt;
-	 out = cnt = 0;
-	 for (col = 0, pixrow=pixels[row]; col < cols; col++, pixrow++) {
-	    putbits(ppm_lookupcolor( cht, pixrow ), pclindex);
-	 }
-	 putbits(0, 0); /* flush row */
-      } else { /* direct color mode */
-	 for (col = 0, pixrow=pixels[row]; col < cols; col++, pixrow++) {
-	    putbits(PPM_GETR( *pixrow ), bpr);
-	    putbits(PPM_GETG( *pixrow ), bpg);
-	    putbits(PPM_GETB( *pixrow ), bpb); /* don't need to flush */
-	 }
-	 putbits(0, 0); /* flush row */
-      }
-   }
-   printf("\033*rC"); /* end raster graphics */
-   exit(0);
+    printf("\033*r%ds%dT", cols, rows);          /* source width, height */
+    if (xshift != 0 || yshift != 0)
+        printf("\033&a%+dh%+dV", xshift, yshift); /* xshift, yshift */
+    if (quality)
+        printf("\033*o%dQ", quality);             /* print quality */
+    printf("\033*t");
+    if (xsize == 0 && ysize == 0)
+        printf("180r");                   /* resolution */
+    else {                               /* destination width, height */
+        if (xsize != 0)
+            printf("%dh", xsize);
+        if (ysize != 0)
+            printf("%dv", ysize);
+    }
+    if (gamma_val != 0)
+        printf("%.3fi", gamma_val);                    /* gamma correction */
+    if (dark)
+        printf("%dk", dark);              /* scaling algorithms */
+    printf("%dJ", render);               /* rendering algorithm */
+    printf("\033*v18W");                           /* configure image data */
+    putchar(0); /* relative colors */
+    putchar(pclindex ? 1 : 3); /* index/direct pixel mode */
+    putchar(pclindex); /* ignored in direct pixel mode */
+    if (pclindex) {
+        putchar(0);
+        putchar(0);
+        putchar(0);
+    } else {
+        putchar(bpr); /* bits per red */
+        putchar(bpg); /* bits per green */
+        putchar(bpb); /* bits per blue */
+    }
+    putword(maxval); /* max red reference */
+    putword(maxval); /* max green reference */
+    putword(maxval); /* max blue reference */
+    putword(0); /* min red reference */
+    putword(0); /* min green reference */
+    putword(0); /* min blue reference */
+    if (pclindex) {                        /* set palette */
+        unsigned int i;
+        for (i = 0; i < colors; ++i) {
+            int const r = PPM_GETR( chv[i].color);
+            int const g = PPM_GETG( chv[i].color);
+            int const b = PPM_GETB( chv[i].color);
+            if (i == 0)
+                printf("\033*v");
+            if (r)
+                printf("%da", r);
+            if (g)
+                printf("%db", g);
+            if (b)
+                printf("%dc", b);
+            if (i == colors-1)
+                printf("%dI", i);    /* assign color index */
+            else
+                printf("%di", i);    /* assign color index */
+        }
+    }
+    ppm_freecolorhist(chv);
+
+    /* start raster graphics at CAP */
+    printf("\033*r%dA", (xsize != 0 || ysize != 0) ? 3 : 1);
+
+    for (row = 0; row < rows; row++) {
+        pixel * const pixrow = pixels[row];
+        if (pclindex) { /* indexed color mode */
+            unsigned int col;
+            for (col = 0; col < cols; ++col)
+                putbits(ppm_lookupcolor(cht, &pixrow[col]), pclindex);
+            putbits(0, 0); /* flush row */
+        } else { /* direct color mode */
+            unsigned int col;
+            for (col = 0; col < cols; ++col) {
+                putbits(PPM_GETR(pixrow[col]), bpr);
+                putbits(PPM_GETG(pixrow[col]), bpg);
+                putbits(PPM_GETB(pixrow[col]), bpb);
+                /* don't need to flush */
+            }
+            putbits(0, 0); /* flush row */
+        }
+    }
+    printf("\033*rC"); /* end raster graphics */
+
+    return 0;
 }
diff --git a/converter/ppm/ppmtoterm.c b/converter/ppm/ppmtoterm.c
index 72105705..81df614e 100644
--- a/converter/ppm/ppmtoterm.c
+++ b/converter/ppm/ppmtoterm.c
@@ -21,6 +21,7 @@
 
 #include <string.h>
 
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "shhopt.h"
 
diff --git a/converter/ppm/ppmtowinicon.c b/converter/ppm/ppmtowinicon.c
index d7f12dd0..a96840a1 100644
--- a/converter/ppm/ppmtowinicon.c
+++ b/converter/ppm/ppmtowinicon.c
@@ -13,6 +13,7 @@
 #include <math.h>
 #include <string.h>
 
+#include "pm_c_util.h"
 #include "winico.h"
 #include "ppm.h"
 #include "mallocvar.h"
@@ -203,8 +204,6 @@ createAndBitmap (gray ** const ba, int const cols, int const rows,
     * How wide should the u1 string for each row be?
     * each byte is 8 pixels, but must be a multiple of 4 bytes.
     */
-
-#define ROUNDUP(X,M) (((X)+(M)-1)/(M)*(M))
    unsigned int const xBytes = ROUNDUP(cols, 32)/8;
    ICON_bmp icBitmap;
    int y,x;
diff --git a/converter/ppm/ppmtoxpm.c b/converter/ppm/ppmtoxpm.c
index 630653df..fc8ba9d7 100644
--- a/converter/ppm/ppmtoxpm.c
+++ b/converter/ppm/ppmtoxpm.c
@@ -39,6 +39,8 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
+
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "shhopt.h"
 #include "nstring.h"
@@ -138,7 +140,7 @@ parseCommandLine(int argc, char ** argv,
     /* If output filename not specified, use input filename as default. */
     if (nameSpec)
         cmdlineP->name = nameOpt;
-    else if (STREQ(cmdlineP->inputFilename, "-"))
+    else if (streq(cmdlineP->inputFilename, "-"))
         cmdlineP->name = "noname";
     else {
         static char name[80+1];
diff --git a/converter/ppm/ppmtoyuvsplit.c b/converter/ppm/ppmtoyuvsplit.c
index 133161c1..b5809d0b 100644
--- a/converter/ppm/ppmtoyuvsplit.c
+++ b/converter/ppm/ppmtoyuvsplit.c
@@ -4,7 +4,7 @@
 ** - basename.V : The Chrominance chunk V at 1/4
 ** The subsampled U and V values are made by arithmetic mean.
 **
-** If CCIR601 is defined, the produced YUV triples are scaled again
+** The produced YUV triples are scaled again
 ** to fit into the smaller range of values for this standard.
 **
 ** by A.Beck
@@ -20,12 +20,6 @@
 ** implied warranty.
 */
 
-/* Wether to create YUV in JFIF(JPEG) or CCIR.601(MPEG) scale */
-#define CCIR601
-
-/* Wether to use pm_close() or fake it -- don't ask me why */
-/* #define ORIGINAL */
-
 /* ALPHA Kludge by Franky */
 
 #ifdef __alpha
@@ -70,156 +64,148 @@ termFileNameSet(struct FileNameSet const fname) {
 
 
 int
-main(argc, argv)
-char **argv;
-{
-        FILE *ifp,*vf,*uf,*yf;
-        pixel          *pixelrow1,*pixelrow2;
-        register pixel *pP1,*pP2;
-        int             rows, cols, format, row;
-        register int    col;
-        pixval          maxval;
-        myLONG u,v,y0,y1,y2,y3,u0,u1,u2,u3,v0,v1,v2,v3;
-        unsigned char  *y1buf,*y2buf,*ubuf,*vbuf;
-        struct FileNameSet fname;
-            /* Output file names - .U, .V, .Y */
-
-        ppm_init(&argc, argv);
-
-        if ((argc>3)||(argc<2)) pm_usage("basename [ppmfile]");
-
-        if (argc == 3) ifp = pm_openr(argv[2]);
-        else ifp = stdin;
-
-        makeOutputFileName(argv[1], &fname);
-
-        uf = pm_openw(fname.u);
-        vf = pm_openw(fname.v);
-        yf = pm_openw(fname.y);
-
-        termFileNameSet(fname);
-
-        if(!(uf && vf && yf)) {
-         perror("error opening output files");
-         exit(0);
-        }
-        ppm_readppminit(ifp, &cols, &rows, &maxval, &format);
-
-        if(cols & 1) fprintf(stderr,
-                             "%s: Warning: odd columns count, exceed ignored\n",
-                             argv[0]);
-        if(rows & 1) fprintf(stderr,
-                             "%s: Warning: odd rows count, exceed ignored\n",
-                             argv[0]);
-
-        pixelrow1 = ((pixel*) pm_allocrow( cols, sizeof(pixel) ));
-        pixelrow2 = ((pixel*) pm_allocrow( cols, sizeof(pixel) ));
-
-        y1buf = (unsigned char *) pm_allocrow( cols, 1 );
-        y2buf = (unsigned char *) pm_allocrow( cols, 1 );
-        ubuf = (unsigned char *) pm_allocrow( cols, 1 );
-        vbuf = (unsigned char *) pm_allocrow( cols, 1 );
-
-        for (row = 0; row < (rows & ~1); row += 2) {
-                unsigned char *y1ptr,*y2ptr,*uptr,*vptr;
-
-                ppm_readppmrow(ifp, pixelrow1, cols, maxval, format);
-                ppm_readppmrow(ifp, pixelrow2, cols, maxval, format);
-
-                pP1 = pixelrow1; pP2 = pixelrow2;
-                y1ptr = y1buf; y2ptr = y2buf; vptr = vbuf; uptr = ubuf;
-
-                for (col = 0 ; col < (cols & ~1); col += 2) {
-                        pixval r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3;
-
-                        /* first pixel */
-                        r0 = PPM_GETR(*pP1);
-                        g0 = PPM_GETG(*pP1);
-                        b0 = PPM_GETB(*pP1);
-                        pP1++;
-                        /* 2nd pixel */
-                        r1 = PPM_GETR(*pP1);
-                        g1 = PPM_GETG(*pP1);
-                        b1 = PPM_GETB(*pP1);
-                        pP1++;
-                        /* 3rd pixel */
-                        r2 = PPM_GETR(*pP2);
-                        g2 = PPM_GETG(*pP2);
-                        b2 = PPM_GETB(*pP2);
-                        pP2++;
-                        /* 4th pixel */
-                        r3 = PPM_GETR(*pP2);
-                        g3 = PPM_GETG(*pP2);
-                        b3 = PPM_GETB(*pP2);
-                        pP2++;
-
-
-/* The JFIF RGB to YUV Matrix for $00010000 = 1.0
-
-[Y]   [19595   38469    7471][R]
-[U] = [-11056  -21712  32768][G]
-[V]   [32768   -27440  -5328][B]
+main(int argc, const char ** argv) {
+
+    FILE * ifP;
+    FILE *vf, *uf, *yf;
+    pixel *pixelrow1, *pixelrow2;
+    int rows, cols;
+    int format;
+    unsigned int row;
+    pixval maxval;
+    unsigned char *y1buf, *y2buf, *ubuf, *vbuf;
+    struct FileNameSet fname;
+        /* Output file names - .U, .V, .Y */
+
+    pm_proginit(&argc, argv);
 
-*/
+    if ((argc-1 > 2) || (argc-1 < 1))
+        pm_error("Wrong number of arguments: %u.  "
+                 "Arguments are basename for output files "
+                 "and optional input file name", argc-1);
+
+    if (argc-1 == 2)
+        ifP = pm_openr(argv[2]);
+    else
+        ifP = stdin;
+
+    makeOutputFileName(argv[1], &fname);
+
+    uf = pm_openw(fname.u);
+    vf = pm_openw(fname.v);
+    yf = pm_openw(fname.y);
 
-                        y0 =  19595 * r0 + 38469 * g0 +  7471 * b0;
-                        u0 = -11056 * r0 - 21712 * g0 + 32768 * b0;
-                        v0 =  32768 * r0 - 27440 * g0 -  5328 * b0;
+    termFileNameSet(fname);
 
-                        y1 =  19595 * r1 + 38469 * g1 +  7471 * b1;
-                        u1 = -11056 * r1 - 21712 * g1 + 32768 * b1;
-                        v1 =  32768 * r1 - 27440 * g1 -  5328 * b1;
+    ppm_readppminit(ifP, &cols, &rows, &maxval, &format);
 
-                        y2 =  19595 * r2 + 38469 * g2 +  7471 * b2;
-                        u2 = -11056 * r2 - 21712 * g2 + 32768 * b2;
-                        v2 =  32768 * r2 - 27440 * g2 -  5328 * b2;
+    if (cols % 2 == 1)
+        pm_message("Warning: odd columns count %u, excess ignored", cols);
 
-                        y3 =  19595 * r3 + 38469 * g3 +  7471 * b3;
-                        u3 = -11056 * r3 - 21712 * g3 + 32768 * b3;
-                        v3 =  32768 * r3 - 27440 * g3 -  5328 * b3;
+    if (rows % 2 == 1)
+        pm_message("Warning: odd rows count %u, excess ignored", rows);
 
-                        /* mean the chroma for subsampling */
+    pixelrow1 = ((pixel*) pm_allocrow(cols, sizeof(pixel)));
+    pixelrow2 = ((pixel*) pm_allocrow(cols, sizeof(pixel)));
 
-                        u  = (u0+u1+u2+u3)>>2;
-                        v  = (v0+v1+v2+v3)>>2;
+    y1buf = (unsigned char *) pm_allocrow(cols, 1);
+    y2buf = (unsigned char *) pm_allocrow(cols, 1);
+    ubuf = (unsigned char *) pm_allocrow(cols, 1);
+    vbuf = (unsigned char *) pm_allocrow(cols, 1);
 
-#ifdef CCIR601
+    for (row = 0; row < (rows & ~1); row += 2) {
+        unsigned char *y1ptr, *y2ptr, *uptr, *vptr;
+        pixel *pP1, *pP2;
+        unsigned int col;
 
-                        y0 = (y0 * 219)/255 + 1048576;
-                        y1 = (y1 * 219)/255 + 1048576;
-                        y2 = (y2 * 219)/255 + 1048576;
-                        y3 = (y3 * 219)/255 + 1048576;
+        ppm_readppmrow(ifP, pixelrow1, cols, maxval, format);
+        ppm_readppmrow(ifP, pixelrow2, cols, maxval, format);
 
-                        u  = (u * 224)/255 ;
-                        v  = (v * 224)/255 ;
-#endif
+        pP1 = &pixelrow1[0]; pP2 = &pixelrow2[0];
+        y1ptr = y1buf; y2ptr = y2buf; vptr = vbuf; uptr = ubuf;
 
+        for (col = 0 ; col < (cols & ~1); col += 2) {
+            pixval r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3;
+            myLONG u, v, y0, y1, y2, y3, u0, u1, u2, u3, v0, v1, v2, v3;
 
-                        *y1ptr++  = (y0 >> 16) ;
-                        *y1ptr++  = (y1 >> 16) ;
-                        *y2ptr++  = (y2 >> 16) ;
-                        *y2ptr++  = (y3 >> 16) ;
+            /* first pixel */
+            r0 = PPM_GETR(*pP1);
+            g0 = PPM_GETG(*pP1);
+            b0 = PPM_GETB(*pP1);
+            pP1++;
+            /* 2nd pixel */
+            r1 = PPM_GETR(*pP1);
+            g1 = PPM_GETG(*pP1);
+            b1 = PPM_GETB(*pP1);
+            pP1++;
+            /* 3rd pixel */
+            r2 = PPM_GETR(*pP2);
+            g2 = PPM_GETG(*pP2);
+            b2 = PPM_GETB(*pP2);
+            pP2++;
+            /* 4th pixel */
+            r3 = PPM_GETR(*pP2);
+            g3 = PPM_GETG(*pP2);
+            b3 = PPM_GETB(*pP2);
+            pP2++;
 
 
-                        *uptr++   = (u >> 16)+128 ;
-                        *vptr++   = (v >> 16)+128 ;
+            /* The JFIF RGB to YUV Matrix for $00010000 = 1.0
 
-                }
-                fwrite(y1buf, (cols & ~1), 1, yf);
-                fwrite(y2buf, (cols & ~1), 1, yf);
-                fwrite(ubuf, cols/2, 1, uf);
-                fwrite(vbuf, cols/2, 1, vf);
-        }
+               [Y]   [19595   38469    7471][R]
+               [U] = [-11056  -21712  32768][G]
+               [V]   [32768   -27440  -5328][B]
 
-/* I dunno why pm_close sees an error... get rid of it */
+            */
 
-#ifdef ORIGINAL
-        pm_close(ifp);
-#else
-        if(ifp != stdin) fclose(ifp);
-#endif
-        fclose(yf);
-        fclose(uf);
-        fclose(vf);
-        exit(0);
+            y0 =  19595 * r0 + 38469 * g0 +  7471 * b0;
+            u0 = -11056 * r0 - 21712 * g0 + 32768 * b0;
+            v0 =  32768 * r0 - 27440 * g0 -  5328 * b0;
+
+            y1 =  19595 * r1 + 38469 * g1 +  7471 * b1;
+            u1 = -11056 * r1 - 21712 * g1 + 32768 * b1;
+            v1 =  32768 * r1 - 27440 * g1 -  5328 * b1;
+
+            y2 =  19595 * r2 + 38469 * g2 +  7471 * b2;
+            u2 = -11056 * r2 - 21712 * g2 + 32768 * b2;
+            v2 =  32768 * r2 - 27440 * g2 -  5328 * b2;
+
+            y3 =  19595 * r3 + 38469 * g3 +  7471 * b3;
+            u3 = -11056 * r3 - 21712 * g3 + 32768 * b3;
+            v3 =  32768 * r3 - 27440 * g3 -  5328 * b3;
+
+            /* mean the chroma for subsampling */
+
+            u  = (u0+u1+u2+u3)>>2;
+            v  = (v0+v1+v2+v3)>>2;
+
+            y0 = (y0 * 219)/255 + 1048576;
+            y1 = (y1 * 219)/255 + 1048576;
+            y2 = (y2 * 219)/255 + 1048576;
+            y3 = (y3 * 219)/255 + 1048576;
+
+            u  = (u * 224)/255 ;
+            v  = (v * 224)/255 ;
+
+            *y1ptr++  = (y0 >> 16) ;
+            *y1ptr++  = (y1 >> 16) ;
+            *y2ptr++  = (y2 >> 16) ;
+            *y2ptr++  = (y3 >> 16) ;
+
+
+            *uptr++   = (u >> 16)+128 ;
+            *vptr++   = (v >> 16)+128 ;
+
+        }
+        fwrite(y1buf, (cols & ~1), 1, yf);
+        fwrite(y2buf, (cols & ~1), 1, yf);
+        fwrite(ubuf, cols/2, 1, uf);
+        fwrite(vbuf, cols/2, 1, vf);
+    }
+
+    pm_close(ifP);
+    fclose(yf);
+    fclose(uf);
+    fclose(vf);
+    return 0;
 }
diff --git a/converter/ppm/rawtoppm.c b/converter/ppm/rawtoppm.c
index 8d6c3b2c..44e856da 100644
--- a/converter/ppm/rawtoppm.c
+++ b/converter/ppm/rawtoppm.c
@@ -13,39 +13,148 @@
 #include <math.h>
 #include "ppm.h"
 
-static void dorowskip ARGS(( FILE* ifp, int rowskip ));
+enum order { ORD_RGB, ORD_RBG, ORD_GRB, ORD_GBR, ORD_BRG, ORD_BGR };
+
+enum interleave { INT_PIX, INT_ROW };
+
+static void
+dorowskip(FILE * const ifP,
+          int    const rowskip) {
+
+    unsigned int i;
+
+    for (i = 0; i < rowskip; ++i) {
+        int const val = getc(ifP);
+        if (val == EOF)
+            pm_error("EOF / read error");
+    }
+}
+
+
+
+static void
+doRowPixInterleave(pixel *      const pixrow,
+                   unsigned int const cols,
+                   FILE *       const ifP,
+                   enum order   const order,
+                   int          const rowskip) {
+
+    unsigned int col;
+
+    for (col = 0; col < cols; ++col) {
+        int const val1 = getc(ifP);
+        int const val2 = getc(ifP);
+        int const val3 = getc(ifP);
+
+        if (val1 == EOF)
+            pm_error("EOF / read error");
+        if (val2 == EOF)
+            pm_error("EOF / read error");
+        if (val3 == EOF)
+            pm_error("EOF / read error");
+
+        switch (order) {
+        case ORD_RGB:
+            PPM_ASSIGN(pixrow[col], val1, val2, val3);
+            break;
+        case ORD_RBG:
+            PPM_ASSIGN(pixrow[col], val1, val3, val2);
+            break;
+        case ORD_GRB:
+            PPM_ASSIGN(pixrow[col], val2, val1, val3);
+            break;
+        case ORD_GBR:
+            PPM_ASSIGN(pixrow[col], val3, val1, val2);
+            break;
+        case ORD_BRG:
+            PPM_ASSIGN(pixrow[col], val2, val3, val1);
+            break;
+        case ORD_BGR:
+            PPM_ASSIGN(pixrow[col], val3, val2, val1);
+            break;
+        }
+    }
+    dorowskip(ifP, rowskip);
+}
+
+
+
+static void
+doRowRowInterleave(pixel *      const pixrow,
+                   unsigned int const cols,
+                   FILE *       const ifP,
+                   enum order   const order,
+                   int          const rowskip,
+                   pixval *     const grow1,
+                   pixval *     const grow2,
+                   pixval *     const grow3) {
+
+    unsigned int col;
+
+    for (col = 0; col < cols; ++col) {
+        int const val1 = getc(ifP);
+        if (val1 == EOF)
+            pm_error("EOF / read error");
+        grow1[col] = val1;
+    }
+    dorowskip(ifP, rowskip);
+    for (col = 0; col < cols; ++col) {
+        int const val2 = getc(ifP);
+        if (val2 == EOF)
+            pm_error( "EOF / read error" );
+        grow2[col] = val2;
+    }
+    dorowskip(ifP, rowskip);
+    for (col = 0; col < cols; ++col) {
+        int const val3 = getc(ifP);
+        if (val3 == EOF)
+            pm_error( "EOF / read error" );
+        grow3[col] = val3;
+    }
+    dorowskip(ifP, rowskip);
+
+    for (col = 0; col < cols; ++col) {
+        switch (order) {
+        case ORD_RGB:
+            PPM_ASSIGN(pixrow[col], grow1[col], grow2[col], grow3[col]);
+            break;
+        case ORD_RBG:
+            PPM_ASSIGN(pixrow[col], grow1[col], grow3[col], grow2[col]);
+            break;
+        case ORD_GRB:
+            PPM_ASSIGN(pixrow[col], grow2[col], grow1[col], grow3[col]);
+            break;
+        case ORD_GBR:
+            PPM_ASSIGN(pixrow[col], grow3[col], grow1[col], grow2[col]);
+            break;
+        case ORD_BRG:
+            PPM_ASSIGN(pixrow[col], grow2[col], grow3[col], grow1[col]);
+            break;
+        case ORD_BGR:
+            PPM_ASSIGN(pixrow[col], grow3[col], grow2[col], grow1[col]);
+            break;
+        }
+    }
+}
+
+
 
 int
-main( argc, argv )
-    int argc;
-    char* argv[];
-    {
-    FILE* ifp;
-    pixel* pixrow;
-    register pixel* pP;
+main(int argc, const char * argv[]) {
+
+    pixval const maxval = 255;
+
+    FILE * ifP;
+    pixel * pixrow;
     int argn, headerskip, rowskip, rows, cols, row, i;
-    register int col;
-    int order;
-#define ORD_RGB 1
-#define ORD_RBG 2
-#define ORD_GRB 3
-#define ORD_GBR 4
-#define ORD_BRG 5
-#define ORD_BGR 6
-int interleave;
-#define INT_PIX 1
-#define INT_ROW 2
-    int val1, val2, val3;
-    gray* grow1;
-    gray* grow2;
-    gray* grow3;
-    register gray* g1P;
-    register gray* g2P;
-    register gray* g3P;
+    enum order order;
+    enum interleave interleave;
+    gray * grow1;
+    gray * grow2;
+    gray * grow3;
     const char* const usage = "[-headerskip N] [-rowskip N] [-rgb|-rbg|-grb|-gbr|-brg|-bgr] [-interpixel|-interrow] <width> <height> [rawfile]";
 
-
-    ppm_init( &argc, argv );
+    pm_proginit(&argc, argv);
 
     argn = 1;
     headerskip = 0;
@@ -54,191 +163,90 @@ int interleave;
     interleave = INT_PIX;
 
     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
-	{
-	if ( pm_keymatch( argv[argn], "-headerskip", 2 ) )
-	    {
-	    ++argn;
-	    if ( argn >= argc )
-		pm_usage( usage );
-	    headerskip = atoi( argv[argn] );
-	    }
-	else if ( pm_keymatch( argv[argn], "-rowskip", 3 ) )
-	    {
-	    ++argn;
-	    if ( argn >= argc )
-		pm_usage( usage );
-	    rowskip = atoi( argv[argn] );
-	    }
-	else if ( pm_keymatch( argv[argn], "-rgb", 3 ) )
-	    order = ORD_RGB;
-	else if ( pm_keymatch( argv[argn], "-rbg", 3 ) )
-	    order = ORD_RBG;
-	else if ( pm_keymatch( argv[argn], "-grb", 3 ) )
-	    order = ORD_GRB;
-	else if ( pm_keymatch( argv[argn], "-gbr", 3 ) )
-	    order = ORD_GBR;
-	else if ( pm_keymatch( argv[argn], "-brg", 3 ) )
-	    order = ORD_BRG;
-	else if ( pm_keymatch( argv[argn], "-bgr", 3 ) )
-	    order = ORD_BGR;
-	else if ( pm_keymatch( argv[argn], "-interpixel", 7 ) )
-	    interleave = INT_PIX;
-	else if ( pm_keymatch( argv[argn], "-interrow", 7 ) )
-	    interleave = INT_ROW;
-	else
-	    pm_usage( usage );
-	++argn;
-	}
+        {
+        if ( pm_keymatch( argv[argn], "-headerskip", 2 ) )
+            {
+            ++argn;
+            if ( argn >= argc )
+                pm_usage( usage );
+            headerskip = atoi( argv[argn] );
+            }
+        else if ( pm_keymatch( argv[argn], "-rowskip", 3 ) )
+            {
+            ++argn;
+            if ( argn >= argc )
+                pm_usage( usage );
+            rowskip = atoi( argv[argn] );
+            }
+        else if ( pm_keymatch( argv[argn], "-rgb", 3 ) )
+            order = ORD_RGB;
+        else if ( pm_keymatch( argv[argn], "-rbg", 3 ) )
+            order = ORD_RBG;
+        else if ( pm_keymatch( argv[argn], "-grb", 3 ) )
+            order = ORD_GRB;
+        else if ( pm_keymatch( argv[argn], "-gbr", 3 ) )
+            order = ORD_GBR;
+        else if ( pm_keymatch( argv[argn], "-brg", 3 ) )
+            order = ORD_BRG;
+        else if ( pm_keymatch( argv[argn], "-bgr", 3 ) )
+            order = ORD_BGR;
+        else if ( pm_keymatch( argv[argn], "-interpixel", 7 ) )
+            interleave = INT_PIX;
+        else if ( pm_keymatch( argv[argn], "-interrow", 7 ) )
+            interleave = INT_ROW;
+        else
+            pm_usage( usage );
+        ++argn;
+        }
 
     if ( argn + 2 > argc )
-	pm_usage( usage );
-
-    cols = atoi( argv[argn++] );
-    rows = atoi( argv[argn++] );
-    if ( cols <= 0 || rows <= 0 )
-	pm_usage( usage );
+        pm_usage( usage );
+    
+    cols = pm_parse_width(argv[argn++]);
+    rows = pm_parse_height(argv[argn++]);
 
     if ( argn < argc )
-	{
-	ifp = pm_openr( argv[argn] );
-	++argn;
-	}
+        {
+        ifP = pm_openr( argv[argn] );
+        ++argn;
+        }
     else
-	ifp = stdin;
+        ifP = stdin;
 
     if ( argn != argc )
-	pm_usage( usage );
-
-    ppm_writeppminit( stdout, cols, rows, (pixval) 255, 0 );
-    pixrow = ppm_allocrow( cols );
-
-    if ( interleave == INT_ROW )
-	{
-	grow1 = pgm_allocrow( cols );
-	grow2 = pgm_allocrow( cols );
-	grow3 = pgm_allocrow( cols );
-	}
-
-    for ( i = 0; i < headerskip; ++i )
-	{
-	val1 = getc( ifp );
-	if ( val1 == EOF )
-	    pm_error( "EOF / read error" );
-	}
-
-    for ( row = 0; row < rows; ++row)
-	{
-	switch ( interleave )
-	    {
-	    case INT_PIX:
-	    for ( col = 0, pP = pixrow; col < cols; ++col, ++pP )
-		{
-		val1 = getc( ifp );
-		if ( val1 == EOF )
-		    pm_error( "EOF / read error" );
-		val2 = getc( ifp );
-		if ( val2 == EOF )
-		    pm_error( "EOF / read error" );
-		val3 = getc( ifp );
-		if ( val3 == EOF )
-		    pm_error( "EOF / read error" );
-		switch ( order )
-		    {
-		    case ORD_RGB:
-		    PPM_ASSIGN( *pP, val1, val2, val3 );
-		    break;
-		    case ORD_RBG:
-		    PPM_ASSIGN( *pP, val1, val3, val2 );
-		    break;
-		    case ORD_GRB:
-		    PPM_ASSIGN( *pP, val2, val1, val3 );
-		    break;
-		    case ORD_GBR:
-		    PPM_ASSIGN( *pP, val3, val1, val2 );
-		    break;
-		    case ORD_BRG:
-		    PPM_ASSIGN( *pP, val2, val3, val1 );
-		    break;
-		    case ORD_BGR:
-		    PPM_ASSIGN( *pP, val3, val2, val1 );
-		    break;
-		    }
-		}
-	    dorowskip( ifp, rowskip );
-	    break;
-
-	    case INT_ROW:
-	    for ( col = 0, g1P = grow1; col < cols; ++col, ++g1P )
-		{
-		val1 = getc( ifp );
-		if ( val1 == EOF )
-		    pm_error( "EOF / read error" );
-		*g1P = val1;
-		}
-	    dorowskip( ifp, rowskip );
-	    for ( col = 0, g2P = grow2; col < cols; ++col, ++g2P )
-		{
-		val2 = getc( ifp );
-		if ( val2 == EOF )
-		    pm_error( "EOF / read error" );
-		*g2P = val2;
-		}
-	    dorowskip( ifp, rowskip );
-	    for ( col = 0, g3P = grow3; col < cols; ++col, ++g3P )
-		{
-		val3 = getc( ifp );
-		if ( val3 == EOF )
-		    pm_error( "EOF / read error" );
-		*g3P = val3;
-		}
-	    dorowskip( ifp, rowskip );
-	    for ( col = 0, pP = pixrow, g1P = grow1, g2P = grow2, g3P = grow3;
-		  col < cols; ++col, ++pP, ++g1P, ++g2P, ++g3P )
-		{
-		switch ( order )
-		    {
-		    case ORD_RGB:
-		    PPM_ASSIGN( *pP, *g1P, *g2P, *g3P );
-		    break;
-		    case ORD_RBG:
-		    PPM_ASSIGN( *pP, *g1P, *g3P, *g2P );
-		    break;
-		    case ORD_GRB:
-		    PPM_ASSIGN( *pP, *g2P, *g1P, *g3P );
-		    break;
-		    case ORD_GBR:
-		    PPM_ASSIGN( *pP, *g3P, *g1P, *g2P );
-		    break;
-		    case ORD_BRG:
-		    PPM_ASSIGN( *pP, *g2P, *g3P, *g1P );
-		    break;
-		    case ORD_BGR:
-		    PPM_ASSIGN( *pP, *g3P, *g2P, *g1P );
-		    break;
-		    }
-		}
-	    break;
-	    }
-	ppm_writeppmrow( stdout, pixrow, cols, (pixval) 255, 0 );
-	}
-
-    pm_close( ifp );
-    pm_close( stdout );
+        pm_usage( usage );
 
-    exit( 0 );
+    ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0);
+    pixrow = ppm_allocrow(cols);
+
+    if (interleave == INT_ROW) {
+        grow1 = pgm_allocrow(cols);
+        grow2 = pgm_allocrow(cols);
+        grow3 = pgm_allocrow(cols);
     }
 
-static void
-dorowskip( ifp, rowskip )
-    FILE* ifp;
-    int rowskip;
-    {
-    int i, val;
-
-    for ( i = 0; i < rowskip; ++i )
-	{
-	val = getc( ifp );
-	if ( val == EOF )
-	    pm_error( "EOF / read error" );
-	}
+    for (i = 0; i < headerskip; ++i) {
+        int const val = getc(ifP);
+        if (val == EOF)
+            pm_error("EOF / read error");
+    }
+
+    for (row = 0; row < rows; ++row) {
+        switch (interleave) {
+        case INT_PIX:
+            doRowPixInterleave(pixrow, cols, ifP, order, rowskip);
+            break;
+
+        case INT_ROW:
+            doRowRowInterleave(pixrow, cols, ifP, order, rowskip,
+                               grow1, grow2, grow3);
+            break;
+        }
+        ppm_writeppmrow(stdout, pixrow, cols, maxval, 0);
+    }
+
+    pm_close( ifP );
+    pm_close( stdout );
+
+    exit( 0 );
     }
diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c
index 6b51f291..ad16a649 100644
--- a/converter/ppm/sldtoppm.c
+++ b/converter/ppm/sldtoppm.c
@@ -66,15 +66,9 @@ struct svector {
     struct spoint t;          /* To point */
 };
 
-static int extend ARGS((smallint ch));
-static int sli ARGS((void));
-static int slib ARGS((void));
-static void vscale ARGS((int *px, int *py));
-static void slider ARGS((void (*slvec) ARGS((struct svector *vec, int color)),
-                    void (*slflood) ARGS((struct spolygon *poly, int color)) ));
-static void slidefind ARGS((char *sname, int dironly, int ucasen));
-static void draw ARGS((struct svector *vec, int color));
-static void flood ARGS((struct spolygon *const poly, int const color));
+typedef void (slvecfn)(struct svector * vec, int color);
+typedef void (slfloodfn)(struct spolygon * poly, int color);
+
 
 static int ixdots, iydots;        /* Screen size in dots */
 static FILE *slfile;              /* Slide file descriptor */
@@ -104,21 +98,26 @@ static int adjust = FALSE;        /* Adjust to correct aspect ratio ? */
 static struct slhead slfrof;          /* Slide file header */
 static long xfac, yfac;           /* Aspect ratio scale factors */
 
-static int sdrawkcab;             /* Slide drawing kinematic conversion of
-                     ass-backwards data flag */
+static int sdrawkcab;
+    /* Slide drawing kinematic conversion of ass-backwards data flag */
+
+
 
 /*  EXTEND  --  Turn a smallint into an int with sign extension, whether
-        or not that happens automatically.  */
+    or not that happens automatically.
+*/
 
-static int extend(smallint ch)
-{
+static int
+extend(smallint ch) {
     return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch));
 }
 
+
+
 /*  SLI  --  Input word from slide file  */
 
-static int sli()
-{
+static int
+sli(void) {
     short wd;
 
     if (fread(&wd, sizeof wd, 1, slfile) != 1) {
@@ -131,10 +130,12 @@ static int sli()
     return wd;
 }
 
+
+
 /*  SLIB  --  Input byte from slide file  */
 
-static int slib()
-{
+static int 
+slib(void) {
     smallint ch = 0;
 
     if (fread(&ch, sizeof ch, 1, slfile) != 1) {
@@ -143,25 +144,171 @@ static int slib()
     return extend(ch);
 }
 
+
+
 /*  VSCALE -- scale screen coordinates for mismatched display.  */
 
-static void vscale(px, py)
-  int *px, *py;
-{
+static void
+vscale(int * const px,
+       int * const py) {
+
     *px = (((unsigned) *px) * xfac) >> 16;
     *py = (((unsigned) *py) * yfac) >> 16;
 }
 
+
+
+/*  SLIDEFIND  --  Find  a  slide  in  a  library  or,  if  DIRONLY is
+           nonzero, print a directory listing of the  library.
+           If  UCASEN  is nonzero, the requested slide name is
+           converted to upper case. */
+
+static void
+slidefind(const char * const sname,
+          bool         const dironly,
+          bool         const ucasen) {
+
+    char uname[32];
+    unsigned char libent[36];
+    long pos;
+
+    if (dironly)
+        pm_message("Slides in library:");
+    else {
+        int i;
+        const char * ip;
+        
+        ip = sname; /* initial value */
+        
+        for (i = 0; i < 31; i++) {
+            char ch = *ip++;
+            if (ch == EOS)
+                break;
+            if (ucasen && ISLOWER(ch))
+                ch = TOUPPER(ch);
+            uname[i] = ch;
+        }
+        uname[i] = EOS;
+    }
+    
+    /* Read slide library header and verify. */
+    
+    if ((fread(libent, 32, 1, slfile) != 1) ||
+        (!streq((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) {
+        pm_error("not an AutoCAD slide library file.");
+    }
+    pos = 32;
+    
+    /* Search for a slide with the requested name. */
+    
+    while (TRUE) {
+        if ((fread(libent, 36, 1, slfile) != 1) ||
+            (strlen((char *)libent) == 0)) {
+            if (dironly) {
+                return;
+            }
+            pm_error("slide %s not in library.", sname);
+        }
+        pos += 36;
+        if (dironly) {
+            pm_message("  %s", libent);
+        } else if (streq((char *)libent, uname)) {
+            long dpos = (((((libent[35] << 8) | libent[34]) << 8) |
+                          libent[33]) << 8) | libent[32];
+            if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
+                dpos -= pos;
+        
+                while (dpos-- > 0)
+                    getc(slfile);
+            }
+            break;
+        }
+    }
+}
+
+
+
+/*  DRAW  --  Draw a vector in the given AutoCAD color.  */
+
+static slvecfn draw;
+
+static void
+draw(struct svector * vec,
+     int              color) {
+
+    pixel rgbcolor;
+
+    if (blither) {
+        pm_message("Vector (%d, %d) - (%d, %d)  Color %d",
+           vec->f.x, vec->f.y, vec->t.x, vec->t.y, color);
+    }
+    assert(vec->f.x >= 0 && vec->f.x < pixcols);
+    assert(vec->f.y >= 0 && vec->f.y < pixrows);
+    assert(vec->t.x >= 0 && vec->t.x < pixcols);
+    assert(vec->t.y >= 0 && vec->t.y < pixrows);
+    PPM_ASSIGN(rgbcolor,
+               acadcol[color][0], acadcol[color][1], acadcol[color][2]);
+    ppmd_line(pixels, pixcols, pixrows, pixmaxval,
+              vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y,
+              PPMD_NULLDRAWPROC,
+              (char *) &rgbcolor);
+}
+
+
+
+/*  FLOOD  --  Draw a filled polygon.  */
+
+static slfloodfn flood;
+
+static void
+flood(struct spolygon * const poly,
+      int               const color) {
+
+    unsigned int i;
+    struct fillobj * handle;
+    pixel rgbcolor;
+
+    handle = ppmd_fill_create();
+
+    if (blither) {
+        unsigned int i;
+        pm_message("Polygon: %d points, fill type %d, color %d",
+                   poly->npoints, poly->fill, color);
+        for (i = 0; i < poly->npoints; i++) {
+            pm_message("   Point %d:  (%d, %d)", i + 1,
+                       poly->pt[i].x, poly->pt[i].y);
+        }
+    }
+
+    PPM_ASSIGN(rgbcolor,
+               acadcol[color][0], acadcol[color][1], acadcol[color][2]);
+    for (i = 0; i < poly->npoints; i++) {
+        assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols);
+        assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows);
+        ppmd_line(pixels, pixcols, pixrows, pixmaxval,
+                  poly->pt[i].x, iydots - poly->pt[i].y, 
+                  poly->pt[(i + 1) % poly->npoints].x,
+                  iydots - poly->pt[(i + 1) % poly->npoints].y,
+                  ppmd_fill_drawproc, handle);
+    }
+    ppmd_fill(pixels, pixcols, pixrows, pixmaxval,
+              handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor);
+    
+    ppmd_fill_destroy(handle);
+}
+
+
+
 /*  SLIDER  --  Read slide file.  This is called with the name of the
         file to be read and function pointers to the routines
         which process vectors and polygon fill requests
         respectively.
 */
 
-static void slider(slvec, slflood)
-  void (*slvec) ARGS((struct svector *vec, int color));
-  void (*slflood) ARGS((struct spolygon *poly, int color));
-{
+static void
+slider(slvecfn   slvec,
+       slfloodfn slflood) {
+
     int i, rescale;
     unsigned char ubfr[4];        /* Utility character buffer */
     int lx, ly;               /* Last x and y point */
@@ -174,14 +321,14 @@ static void slider(slvec, slflood)
     short rtest;              /* Value to test byte reversal */
     short btest = 0x1234;         /* Value to test byte-reversal */
     static struct slhead slhi =       /* Master slide header sample */
-        {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0};
+    {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0};
     int curcolor = 7;             /* Current vector color */
     pixel rgbcolor;           /* Pixel used to clear pixmap */
-
+    
     lx = ly = 32000;
-
+    
     /* Process the header of the slide file.  */
-
+    
     sdrawkcab = FALSE;            /* Initially guess byte order is OK */
     fread(slfrof.slh, 17, 1, slfile);
     fread(&slfrof.sntype, sizeof(char), 1, slfile);
@@ -194,48 +341,46 @@ static void slider(slvec, slflood)
 
     /* Verify that slide format is compatible with this program. */
 
-    if (STREQ(slfrof.slh, slhi.slh)) {
+    if (streq(slfrof.slh, slhi.slh))
         pm_error("this is not an AutoCAD slide file.");
-    }
 
     /* Verify that the number format and file level in the header  are
        compatible.  All slides written by versions of AutoCAD released
        since September of 1987 are compatible with this format.  */
 
-    if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel)) {
+    if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel))
         pm_error("incompatible slide file format");
-    }
 
     /* Build SDSAR value from long scaled version. */
-
+    
     ldsar = 0L;
-    for (i = 3; i >= 0; i--) {
-    ldsar = (ldsar << 8) | ubfr[i];
-    }
+    for (i = 3; i >= 0; --i)
+        ldsar = (ldsar << 8) | ubfr[i];
     slfrof.sdsar = ((double) ldsar) / 1E7;
-
+    
     /* Examine the byte order test value.   If it's backwards, set the
        byte-reversal flag and correct all of the values we've read  in
-       so far. */
+       so far.
+    */
 
     if (btest != rtest) {
-    sdrawkcab = TRUE;
+        sdrawkcab = TRUE;
 #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8)
-    rshort(slfrof.sxdots);
-    rshort(slfrof.sydots);
-    rshort(slfrof.shwfill);
+        rshort(slfrof.sxdots);
+        rshort(slfrof.sydots);
+        rshort(slfrof.shwfill);
 #undef rshort
     }
-
+    
     /* Dump the header if we're blithering. */
 
     if (blither || info) {
         pm_message("Slide file type %d, level %d, hwfill type %d.",
-        slfrof.sntype, slfrof.slevel, slfrof.shwfill);
+                   slfrof.sntype, slfrof.slevel, slfrof.shwfill);
         pm_message("Original screen size %dx%d, aspect ratio %.3f.",
-        slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar);
+                   slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar);
         pm_message("Byte order is %s.",
-            sdrawkcab ? "being reversed" : "the same");
+                   sdrawkcab ? "being reversed" : "the same");
     }
 
     /* If the display aspect ratio indicates that the  pixels  on  the
@@ -246,405 +391,284 @@ static void slider(slvec, slflood)
        We  always  correct  the aspect ratio by adjusting the width of
        the image.  This guarantees that output from the SHADE command,
        which  is  essentially  scan-line  data written in vector form,
-       will not be corrupted. */
+       will not be corrupted.
+    */
 
     dsar = ((double) slfrof.sxdots) / slfrof.sydots;
     if (fabs(slfrof.sdsar - dsar) > 0.0001) {
-    if (adjust) {
-        ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5;
-        iydots = slfrof.sydots;
-        dsar = ((double) ixdots) / iydots;
+        if (adjust) {
+            ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5;
+            iydots = slfrof.sydots;
+            dsar = ((double) ixdots) / iydots;
+        } else {
+            pm_message("Warning - pixels on source screen were non-square.  "
+                       "Specifying -adjust will correct image width "
+                       "to compensate.");
+            ixdots = slfrof.sxdots;
+            iydots = slfrof.sydots;
+            dsar = slfrof.sdsar;
+        }
     } else {
-            pm_message("Warning - pixels on source screen were non-square.");
-            pm_message("          Specifying -adjust will correct image width to compensate.");
+        /* Source pixels were square. */
         ixdots = slfrof.sxdots;
         iydots = slfrof.sydots;
         dsar = slfrof.sdsar;
-    }
-    } else {
-    /* Source pixels were square. */
-    ixdots = slfrof.sxdots;
-    iydots = slfrof.sydots;
-    dsar = slfrof.sdsar;
-    adjust = FALSE;           /* Mark no adjustment needed */
+        adjust = FALSE;           /* Mark no adjustment needed */
     }
 
     /* If there's a uniform scale factor specified, apply it. */
 
     if (uscale > 0) {
-    ixdots = (ixdots * uscale) + 0.5;
-    iydots = (iydots * uscale) + 0.5;
+        ixdots = (ixdots * uscale) + 0.5;
+        iydots = (iydots * uscale) + 0.5;
     }
 
     /* If the image is to be stretched  to  a  given  width,  set  the
        output  image  sizes accordingly.  If only a height or width is
        given, scale the other direction proportionally to preserve the
-       aspect ratio. */
+       aspect ratio.
+    */
 
     if (sxsize > 0) {
-    if (sysize > 0) {
-        iydots = sysize - 1;
-    } else {
-        iydots = ((((long) iydots) * (sxsize - 1)) +
-              (iydots / 2)) / ixdots;
-    }
-    ixdots = sxsize - 1;
-    } else if (sysize > 0) {
-    if (sxsize > 0) {
+        if (sysize > 0) {
+            iydots = sysize - 1;
+        } else {
+            iydots = ((((long) iydots) * (sxsize - 1)) +
+                      (iydots / 2)) / ixdots;
+        }
         ixdots = sxsize - 1;
-    } else {
-        ixdots = ((((long) ixdots) * (sysize - 1)) +
-              (ixdots / 2)) / iydots;
-    }
-    iydots = sysize - 1;
+    } else if (sysize > 0) {
+        if (sxsize > 0) {
+            ixdots = sxsize - 1;
+        } else {
+            ixdots = ((((long) ixdots) * (sysize - 1)) +
+                      (ixdots / 2)) / iydots;
+        }
+        iydots = sysize - 1;
     }
-
+    
     if (adjust) {
-    pm_message(
+        pm_message(
             "Resized from %dx%d to %dx%d to correct pixel aspect ratio.",
-        slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1);
+            slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1);
     }
-
+    
     /* Allocate image buffer and clear it to black. */
-
+    
     pixels = ppm_allocarray(pixcols = ixdots + 1, pixrows = iydots + 1);
     PPM_ASSIGN(rgbcolor, 0, 0, 0);
     ppmd_filledrectangle(pixels, pixcols, pixrows, pixmaxval, 0, 0,
                          pixcols, pixrows, PPMD_NULLDRAWPROC,
                          (char *) &rgbcolor);
-
+    
     if ((rescale = slfrof.sxdots != ixdots ||
-    slfrof.sydots != iydots ||
-    slfrof.sdsar != dsar) != 0) {
-
+         slfrof.sydots != iydots ||
+         slfrof.sdsar != dsar) != 0) {
+        
         /* Rescale all coords. so they'll look (more or less)
-       right on this display.  */
-
-    xfac = (ixdots + 1) * 0x10000L;
-    xfac /= (long) (slfrof.sxdots + 1);
-    yfac = (iydots + 1) * 0x10000L;
-    yfac /= (long) (slfrof.sydots + 1);
-    if (dsar < slfrof.sdsar) {
-        yfac = yfac * dsar / slfrof.sdsar;
-       } else {
-        xfac = xfac * slfrof.sdsar / dsar;
-    }
+           right on this display.
+        */
+        
+        xfac = (ixdots + 1) * 0x10000L;
+        xfac /= (long) (slfrof.sxdots + 1);
+        yfac = (iydots + 1) * 0x10000L;
+        yfac /= (long) (slfrof.sydots + 1);
+        if (dsar < slfrof.sdsar) {
+            yfac = yfac * dsar / slfrof.sdsar;
+        } else {
+            xfac = xfac * slfrof.sdsar / dsar;
+        }
     }
 
     poly.npoints = 0;             /* No flood in progress. */
-
+    
     while ((cw = sli()) != 0xFC00) {
-    switch (cw & 0xFF00) {
+        switch (cw & 0xFF00) {
         case 0xFB00:          /*  Short vector compressed  */
-        vec.f.x = lx + extend(cw & 0xFF);
-        vec.f.y = ly + slib();
-        vec.t.x = lx + slib();
-        vec.t.y = ly + slib();
-        lx = vec.f.x;
-        ly = vec.f.y;
-        if (rescale) {
-            vscale(&vec.f.x, &vec.f.y);
-            vscale(&vec.t.x, &vec.t.y);
-        }
-        (*slvec)(&vec, curcolor);/* Draw vector on screen */
-        slx = vec.f.x;        /* Save scaled point */
-        sly = vec.f.y;
-        break;
-
+            vec.f.x = lx + extend(cw & 0xFF);
+            vec.f.y = ly + slib();
+            vec.t.x = lx + slib();
+            vec.t.y = ly + slib();
+            lx = vec.f.x;
+            ly = vec.f.y;
+            if (rescale) {
+                vscale(&vec.f.x, &vec.f.y);
+                vscale(&vec.t.x, &vec.t.y);
+            }
+            (*slvec)(&vec, curcolor);/* Draw vector on screen */
+            slx = vec.f.x;        /* Save scaled point */
+            sly = vec.f.y;
+            break;
+            
         case 0xFC00:          /*  End of file  */
-        break;
-
+            break;
+            
         case 0xFD00:          /*  Flood command  */
-        vec.f.x = sli();
-        vec.f.y = sli();
-        if ((int) vec.f.y < 0) { /* start or end */
-            if (poly.npoints != 0) { /* end?  */
-            if (poly.npoints > 2 && poly.npoints < 11) {
-                (*slflood)(&poly, curcolor);
-            } else {
-                            pm_error("Bad polygon vertex count (%d)",
-                   poly.npoints);
-            }
-            poly.npoints = 0;
-            } else {
-            poly.fill = -vec.f.y;  /* Start */
+            vec.f.x = sli();
+            vec.f.y = sli();
+            if ((int) vec.f.y < 0) { /* start or end */
+                if (poly.npoints != 0) { /* end?  */
+                    if (poly.npoints > 2 && poly.npoints < 11) {
+                        (*slflood)(&poly, curcolor);
+                    } else {
+                        pm_error("Bad polygon vertex count (%d)",
+                                 poly.npoints);
+                    }
+                    poly.npoints = 0;
+                } else {
+                    poly.fill = -vec.f.y;  /* Start */
+                }
+            } else {          /* Polygon vertex */
+                if (poly.npoints < 10) {
+                    if (rescale) {
+                        vscale(&vec.f.x, &vec.f.y);
+                    }
+                    poly.pt[poly.npoints].x = vec.f.x;
+                    poly.pt[poly.npoints].y = vec.f.y;
+                }
+                poly.npoints++;
             }
-        } else {          /* Polygon vertex */
-            if (poly.npoints < 10) {
+            break;
+            
+        case 0xFE00:          /*  Common endpoint compressed  */
+            vec.f.x = lx + extend(cw & 0xFF);
+            vec.f.y = ly + slib();
+            lx = vec.f.x;
+            ly = vec.f.y;
+            vec.t.x = slx;
+            vec.t.y = sly;
             if (rescale) {
                 vscale(&vec.f.x, &vec.f.y);
             }
-            poly.pt[poly.npoints].x = vec.f.x;
-            poly.pt[poly.npoints].y = vec.f.y;
-            }
-            poly.npoints++;
-        }
-        break;
-
-        case 0xFE00:          /*  Common endpoint compressed  */
-        vec.f.x = lx + extend(cw & 0xFF);
-        vec.f.y = ly + slib();
-        lx = vec.f.x;
-        ly = vec.f.y;
-        vec.t.x = slx;
-        vec.t.y = sly;
-        if (rescale) {
-            vscale(&vec.f.x, &vec.f.y);
-        }
-        (*slvec)(&vec, curcolor);/* Draw vector */
-        slx = vec.f.x;        /* Save scaled point */
-        sly = vec.f.y;
-        break;
-
+            (*slvec)(&vec, curcolor);/* Draw vector */
+            slx = vec.f.x;        /* Save scaled point */
+            sly = vec.f.y;
+            break;
+            
         case 0xFF00:          /*  Change color  */
-        curcolor = cw & 0xFF;
-        break;
+            curcolor = cw & 0xFF;
+            break;
 
         default:              /*  Co-ordinates  */
-        lx = vec.f.x = cw;
-        ly = vec.f.y = sli();
-        vec.t.x = sli();
-        vec.t.y = sli();
-        if (rescale) {
-           vscale(&vec.f.x, &vec.f.y);
-           vscale(&vec.t.x, &vec.t.y);
-        }
-        (*slvec)(&vec, curcolor);
-        slx = vec.f.x;        /* Save scaled point */
-        sly = vec.f.y;
-        break;
-    }
-    }
-}
-
-/*  SLIDEFIND  --  Find  a  slide  in  a  library  or,  if  DIRONLY is
-           nonzero, print a directory listing of the  library.
-           If  UCASEN  is nonzero, the requested slide name is
-           converted to upper case. */
-
-static void slidefind(sname, dironly, ucasen)
-  char *sname;
-  int dironly, ucasen;
-{
-    char uname[32];
-    unsigned char libent[36];
-    long pos;
-
-    if (dironly) {
-        pm_message("Slides in library:");
-    } else {
-    int i;
-    char *ip = sname;
-
-    for (i = 0; i < 31; i++) {
-        char ch = *ip++;
-        if (ch == EOS) {
-        break;
-        }
-        if (ucasen && ISLOWER(ch)) {
-        ch = TOUPPER(ch);
-        }
-        uname[i] = ch;
-    }
-    uname[i] = EOS;
-    }
-
-    /* Read slide library header and verify. */
-
-    if ((fread(libent, 32, 1, slfile) != 1) ||
-        (!STREQ((char *)libent, "AutoCAD Slide Library 1.0\015\012\32"))) {
-        pm_error("not an AutoCAD slide library file.");
-    }
-    pos = 32;
-
-    /* Search for a slide with the requested name. */
-
-    while (TRUE) {
-    if ((fread(libent, 36, 1, slfile) != 1) ||
-        (strlen((char *)libent) == 0)) {
-        if (dironly) {
-        return;
-        }
-            pm_error("slide %s not in library.", sname);
-    }
-    pos += 36;
-    if (dironly) {
-            pm_message("  %s", libent);
-    } else if (STREQ((char *)libent, uname)) {
-        long dpos = (((((libent[35] << 8) | libent[34]) << 8) |
-                 libent[33]) << 8) | libent[32];
-        if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
-        dpos -= pos;
-
-        while (dpos-- > 0) {
-            (void) getc(slfile);
-        }
+            lx = vec.f.x = cw;
+            ly = vec.f.y = sli();
+            vec.t.x = sli();
+            vec.t.y = sli();
+            if (rescale) {
+                vscale(&vec.f.x, &vec.f.y);
+                vscale(&vec.t.x, &vec.t.y);
+            }
+            (*slvec)(&vec, curcolor);
+            slx = vec.f.x;        /* Save scaled point */
+            sly = vec.f.y;
+            break;
         }
-        break;
-    }
     }
 }
 
-/*  DRAW  --  Draw a vector in the given AutoCAD color.  */
-
-static void draw(vec, color)
-  struct svector *vec;
-  int color;
-{
-    pixel rgbcolor;
-
-    if (blither) {
-        pm_message("Vector (%d, %d) - (%d, %d)  Color %d",
-           vec->f.x, vec->f.y, vec->t.x, vec->t.y, color);
-    }
-    assert(vec->f.x >= 0 && vec->f.x < pixcols);
-    assert(vec->f.y >= 0 && vec->f.y < pixrows);
-    assert(vec->t.x >= 0 && vec->t.x < pixcols);
-    assert(vec->t.y >= 0 && vec->t.y < pixrows);
-    PPM_ASSIGN(rgbcolor,
-           acadcol[color][0], acadcol[color][1], acadcol[color][2]);
-    ppmd_line(pixels, pixcols, pixrows, pixmaxval,
-          vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y,
-          PPMD_NULLDRAWPROC,
-          (char *) &rgbcolor);
-}
-
-/*  FLOOD  --  Draw a filled polygon.  */
-
-static void
-flood(struct spolygon * const poly,
-      int               const color) {
-
-    int i;
-    struct fillobj * handle;
-    pixel rgbcolor;
-
-    handle = ppmd_fill_create();
-
-    if (blither) {
-        pm_message("Polygon: %d points, fill type %d, color %d",
-                   poly->npoints, poly->fill, color);
-        for (i = 0; i < poly->npoints; i++) {
-            pm_message("   Point %d:  (%d, %d)", i + 1,
-                       poly->pt[i].x, poly->pt[i].y);
-        }
-    }
-
-    PPM_ASSIGN(rgbcolor,
-               acadcol[color][0], acadcol[color][1], acadcol[color][2]);
-    for (i = 0; i < poly->npoints; i++) {
-        assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols);
-        assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows);
-        ppmd_line(pixels, pixcols, pixrows, pixmaxval,
-                  poly->pt[i].x, iydots - poly->pt[i].y, 
-                  poly->pt[(i + 1) % poly->npoints].x,
-                  iydots - poly->pt[(i + 1) % poly->npoints].y,
-                  ppmd_fill_drawproc, handle);
-    }
-    ppmd_fill(pixels, pixcols, pixrows, pixmaxval,
-              handle, PPMD_NULLDRAWPROC, (char *) &rgbcolor);
 
-    ppmd_fill_destroy(handle);
-}
 
 /*  Main program. */
 
-int main(argc, argv)
-  int argc;
-  char *argv[];
-{
+int
+main(int    argc,
+     char * argv[]) {
+
     int argn;
     const char * const usage = "[-verbose] [-info] [-adjust] [-scale <s>]\n\
-                 [-dir] [-lib|-Lib <name>]\n\
-                 [-xsize|-width <x>] [-ysize|-height <y>] [sldfile]";
+[-dir] [-lib|-Lib <name>]\n\
+[-xsize|-width <x>] [-ysize|-height <y>] [sldfile]";
     int scalespec = FALSE, widspec = FALSE, hgtspec = FALSE, dironly = FALSE,
-    ucasen;
-    char *slobber = (char *) 0;       /* Slide library item */
+        ucasen;
+    const char * slobber;       /* Slide library item */
 
 
+    slobber = NULL;
+
     ppm_init(&argc, argv);
     argn = 1;
 
     while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
         if (pm_keymatch(argv[argn], "-verbose", 2)) {
-        blither = TRUE;
+            blither = TRUE;
         } else if (pm_keymatch(argv[argn], "-adjust", 2)) {
-        adjust = TRUE;
+            adjust = TRUE;
         } else if (pm_keymatch(argv[argn], "-dir", 2)) {
-        dironly = TRUE;
+            dironly = TRUE;
         } else if (pm_keymatch(argv[argn], "-info", 2)) {
-        info = TRUE;
+            info = TRUE;
         } else if (pm_keymatch(argv[argn], "-lib", 2)) {
-        if (slobber != (char *) 0) {
+            if (slobber)
                 pm_error("already specified a library item");
-        }
             ucasen = argv[argn][1] != 'L';
-        argn++;
-        if (argn == argc) {
-        pm_usage(usage);
-        }
-        slobber = argv[argn];
+            argn++;
+            if (argn == argc) {
+                pm_usage(usage);
+            }
+            slobber = argv[argn];
         } else if (pm_keymatch(argv[argn], "-scale", 2)) {
-        if (scalespec) {
+            if (scalespec) {
                 pm_error("already specified a scale factor");
-        }
-        argn++;
+            }
+            argn++;
             if ((argn == argc) || (sscanf(argv[argn], "%lf", &uscale) != 1))
-        pm_usage(usage);
-        if (uscale <= 0.0) {
+                pm_usage(usage);
+            if (uscale <= 0.0) {
                 pm_error("scale factor must be greater than 0");
-        }
-        scalespec = TRUE;
+            }
+            scalespec = TRUE;
         } else if (pm_keymatch(argv[argn], "-xsize", 2) ||
                    pm_keymatch(argv[argn], "-width", 2)) {
-        if (widspec) {
+            if (widspec) {
                 pm_error("already specified a width/xsize");
-        }
-        argn++;
+            }
+            argn++;
             if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1))
-        pm_usage(usage);
-        widspec = TRUE;
+                pm_usage(usage);
+            widspec = TRUE;
         } else if (pm_keymatch(argv[argn], "-ysize", 2) ||
                    pm_keymatch(argv[argn], "-height", 2)) {
-        if (hgtspec) {
+            if (hgtspec) {
                 pm_error("already specified a height/ysize");
+            }
+            argn++;
+            if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1))
+                pm_usage(usage);
+            hgtspec = TRUE;
+        } else {
+            pm_usage(usage);
         }
         argn++;
-            if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1))
-        pm_usage(usage);
-        hgtspec = TRUE;
-    } else {
-        pm_usage(usage);
-    }
-    argn++;
     }
 
     /* If a file name is specified, open it.  Otherwise read from
-       standard input. */
+       standard input. 
+    */
 
     if (argn < argc) {
-    slfile = pm_openr(argv[argn]);
-    argn++;
+        slfile = pm_openr(argv[argn]);
+        argn++;
     } else {
-    slfile = stdin;
+        slfile = stdin;
     }
-
+    
     if (argn != argc) {           /* Extra bogus arguments ? */
-    pm_usage(usage);
+        pm_usage(usage);
     }
-
+    
     /* If we're extracting an item from a slide library, position the
-       input stream to the start of the chosen slide. */
-
-    if (dironly || (slobber != (char *) 0)) {
-    slidefind(slobber, dironly, ucasen);
-    }
-
+       input stream to the start of the chosen slide.
+    */
+ 
+    if (dironly || slobber)
+        slidefind(slobber, dironly, ucasen);
+ 
     if (!dironly) {
-    slider(draw, flood);
-    ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE);
+        slider(draw, flood);
+        ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE);
     }
     pm_close(slfile);
     pm_close(stdout);
-    exit(0);
+    
+    return 0;
 }
diff --git a/converter/ppm/spctoppm.c b/converter/ppm/spctoppm.c
index 3eea7821..d2a48187 100644
--- a/converter/ppm/spctoppm.c
+++ b/converter/ppm/spctoppm.c
@@ -165,15 +165,8 @@ DoBitmap( ifp )
 	sscreen[i] = ( screen[i<<1] << 8 ) + ( 0xff & screen[(i<<1)+1] );
     }
 
-#if __STDC__
 static void
 DoChar( int n, char c )
-#else /*__STDC__*/
-static void
-DoChar( n, c )
-    int n;
-    char c;
-#endif /*__STDC__*/
     {
     int i;
 
diff --git a/converter/ppm/tgatoppm.c b/converter/ppm/tgatoppm.c
index 8a559848..f8538214 100644
--- a/converter/ppm/tgatoppm.c
+++ b/converter/ppm/tgatoppm.c
@@ -16,6 +16,8 @@
 #define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 
 #include <string.h>
+
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "tga.h"
 #include "shhopt.h"
@@ -81,7 +83,7 @@ parseCommandLine(int argc, char ** argv,
                  "is the input file specification");
 
     if (alpha_spec &&
-        STREQ(cmdlineP->alpha_filename, "-"))
+        streq(cmdlineP->alpha_filename, "-"))
         cmdlineP->alpha_stdout = 1;
     else 
         cmdlineP->alpha_stdout = 0;
diff --git a/converter/ppm/winicontoppm.c b/converter/ppm/winicontoppm.c
index 2d9de567..ad859c94 100644
--- a/converter/ppm/winicontoppm.c
+++ b/converter/ppm/winicontoppm.c
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <assert.h>
 
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "shhopt.h"
 #include "nstring.h"
@@ -572,7 +573,7 @@ trimOutputName(const char inputName[])
      * oh, for =~ ... :)
      */
     char * outFile = strdup(inputName);
-    if (STREQ(outFile + (strlen (outFile) - 4), ".ppm")) {
+    if (streq(outFile + (strlen (outFile) - 4), ".ppm")) {
         *(outFile + (strlen (outFile) - 4)) = 0;
     }
     return outFile;
@@ -828,7 +829,7 @@ main(int argc, char *argv[]) {
         pm_message("-bestqual doesn't make sense with -allicons.  "
                    "Ignoring -bestqual.");
    
-    if (STREQ(cmdline.outputFilespec, "-"))
+    if (streq(cmdline.outputFilespec, "-"))
         outputFileBase = NULL;
     else
         outputFileBase = trimOutputName(cmdline.outputFilespec);
diff --git a/converter/ppm/ximtoppm.c b/converter/ppm/ximtoppm.c
index 28c9b674..15589c16 100644
--- a/converter/ppm/ximtoppm.c
+++ b/converter/ppm/ximtoppm.c
@@ -14,6 +14,8 @@
 #define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 
 #include <string.h>
+
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "xim.h"
 #include "shhopt.h"
@@ -69,7 +71,7 @@ parseCommandLine(int argc, char ** argv,
                  "is the input file specification");
 
     if (cmdlineP->alpha_filename && 
-        STREQ(cmdlineP->alpha_filename, "-"))
+        streq(cmdlineP->alpha_filename, "-"))
         cmdlineP->alpha_stdout = TRUE;
     else 
         cmdlineP->alpha_stdout = FALSE;
diff --git a/converter/ppm/xpmtoppm.c b/converter/ppm/xpmtoppm.c
index bb6a7a0d..235c3867 100644
--- a/converter/ppm/xpmtoppm.c
+++ b/converter/ppm/xpmtoppm.c
@@ -33,6 +33,7 @@
 
 #include <string.h>
 
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "shhopt.h"
 #include "nstring.h"
@@ -104,7 +105,7 @@ parse_command_line(int argc, char ** argv,
                  "is the input file specification");
 
     if (cmdline_p->alpha_filename && 
-        STREQ(cmdline_p->alpha_filename, "-"))
+        streq(cmdline_p->alpha_filename, "-"))
         cmdline_p->alpha_stdout = TRUE;
     else 
         cmdline_p->alpha_stdout = FALSE;
@@ -293,7 +294,7 @@ interpretXpm3ColorTableLine(char line[], int const seqNum,
                number if so)
             */
             for (key = 1; 
-                 key <= NKEYS && !STREQ(xpmColorKeys[key - 1], str2); 
+                 key <= NKEYS && !streq(xpmColorKeys[key - 1], str2); 
                  key++);
             isKey = (key <= NKEYS);
 
@@ -484,15 +485,15 @@ readXpm1Header(FILE * const stream, int * const widthP, int * const heightP,
                 t1 = str1;
             else
                 ++t1;
-            if (STREQ(t1, "format"))
+            if (streq(t1, "format"))
                 format = v;
-            else if (STREQ(t1, "width"))
+            else if (streq(t1, "width"))
                 *widthP = v;
-            else if (STREQ(t1, "height"))
+            else if (streq(t1, "height"))
                 *heightP = v;
-            else if (STREQ(t1, "ncolors"))
+            else if (streq(t1, "ncolors"))
                 *ncolorsP = v;
-            else if (STREQ(t1, "pixel"))
+            else if (streq(t1, "pixel"))
                 *chars_per_pixelP = v;
         } else if (!strncmp(line, "static char", 11)) {
             if ((t1 = strrchr(line, '_')) == NULL)
diff --git a/converter/ppm/xvminitoppm.c b/converter/ppm/xvminitoppm.c
index 935ab177..d76bea87 100644
--- a/converter/ppm/xvminitoppm.c
+++ b/converter/ppm/xvminitoppm.c
@@ -12,6 +12,7 @@
 
 #include <assert.h>
 #include <string.h>
+#include <errno.h>
 
 #include "pm_c_util.h"
 #include "nstring.h"
@@ -61,7 +62,8 @@ getLine(FILE * const ifP,
     rc = fgets(buf, size, ifP);
     if (rc == NULL) {
         if (ferror(ifP))
-            pm_perror("read error");
+            pm_error("read error.  fgets() failed, errno=%d (%s)",
+                     errno, strerror(errno));
         else
             pm_error("unexpected EOF");
     }
@@ -107,16 +109,16 @@ readXvHeader(FILE *         const ifP,
     
     getLine(ifP, buf, sizeof(buf));
 
-    if (!STRNEQ(buf, "P7 332", 6))
+    if (!strneq(buf, "P7 332", 6))
         pm_error("Input is not a XV thumbnail picture.  It does not "
                  "begin with the characters 'P7 332'.");
 
     endOfComments = FALSE;
     while (!endOfComments) {
         getLine(ifP, buf, sizeof(buf));
-        if (STRNEQ(buf, "#END_OF_COMMENTS", 16))
+        if (strneq(buf, "#END_OF_COMMENTS", 16))
             endOfComments = TRUE;
-        else if (STRNEQ(buf, "#BUILTIN", 8))
+        else if (strneq(buf, "#BUILTIN", 8))
             pm_error("This program does not know how to "
                      "convert builtin XV thumbnail pictures");
     }
diff --git a/converter/ppm/yuvsplittoppm.c b/converter/ppm/yuvsplittoppm.c
index 0f5e19a3..b3088812 100644
--- a/converter/ppm/yuvsplittoppm.c
+++ b/converter/ppm/yuvsplittoppm.c
@@ -20,6 +20,8 @@
 */
 
 #include <string.h>
+
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "nstring.h"
 #include "shhopt.h"