From ee915ec0d26c62f571aabce55b0ca878e98df489 Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Tue, 17 Feb 2015 12:52:16 -0500
Subject: [PATCH 1/6] Put a place holder for PLESC_IMPORT_BUFFER and revised
 some comments

This might not be an appropriate escape action to while working on a buffer.
However, until that gets determined in the mailing list, the placeholder
will make it clear that it is not missing due to an error.
---
 src/plbuf.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/plbuf.c b/src/plbuf.c
index b4214bb..e9858a3 100644
--- a/src/plbuf.c
+++ b/src/plbuf.c
@@ -702,7 +702,7 @@ rdbuf_state( PLStream *pls )
         if ( pls->ncol0 == 0 || pls->ncol0 != ncol )
         {
             // The current palatte is empty or the current palatte is not
-            // big enough, thus we need allocate a new one
+            // correctly sized, thus we need allocate a new one
 
             // If we have a colormap, discard it because we do not use
             // realloc().  We are going to read the colormap from the buffer
@@ -735,7 +735,7 @@ rdbuf_state( PLStream *pls )
         if ( pls->ncol1 == 0 || pls->ncol1 != ncol )
         {
             // The current palatte is empty or the current palatte is not
-            // big enough, thus we need allocate a new one
+            // correctly sized, thus we need allocate a new one
 
             // If we have a colormap, discard it because we do not use
             // realloc().  We are going to read the colormap from the buffer
@@ -824,6 +824,10 @@ rdbuf_esc( PLStream *pls )
     case PLESC_END_TEXT:
         rdbuf_text_unicode( op, pls );
         break;
+    case PLESC_IMPORT_BUFFER:
+        // Place holder until an appropriate action is determined.  
+        // Should this even be an ESC operation?
+        break;
     case PLESC_CLEAR:
         plP_esc( PLESC_CLEAR, NULL );
         break;
-- 
1.7.10.4


From fe86fe995294031b492b9cfe001cfc69c7eb4571 Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Tue, 17 Feb 2015 12:55:31 -0500
Subject: [PATCH 2/6] Added a placeholder for PLSTATE_CHR and PLSTATE_SYM

Those two state operations are not implemented in the 2005 metafile version.
When the new version is implemented, plrender will need to support those
two operations.
---
 utils/plrender.c |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/utils/plrender.c b/utils/plrender.c
index 4cef12a..8e30d91 100644
--- a/utils/plrender.c
+++ b/utils/plrender.c
@@ -1077,6 +1077,23 @@ plr_state( U_CHAR op )
 
         break;
     }
+
+    case PLSTATE_CHR: {
+        // Disabled for now because the 2005 version does not
+        // support this command
+        //plm_rd( pdf_rd_ieeef( pdfs, &plsc->chrdef ) );
+        //plm_rd( pdf_rd_ieeef( pdfs, &plsc->chrht ) );
+        break;
+    }
+
+    case PLSTATE_SYM: {
+        // Disabled for now because the 2005 version does not
+        // support this command
+        //plm_rd( pdf_rd_ieeef( pdfs, &plsc->symdef ) );
+        //plm_rd( pdf_rd_ieeef( pdfs, &plsc->symht ) );
+        break;
+    }
+
     }
 
     DEBUG_PRINT_LOCATION( "end of plr_state" );
-- 
1.7.10.4


From 16080226d9b85f8a58502bc5c9dfadcc5d1a04eb Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Tue, 17 Feb 2015 12:57:27 -0500
Subject: [PATCH 3/6] Cleanup and test casess implemented in test_plbuf.c

* Removed extraneous code that was not necessary for testing the plot buffer
* Added a test to generate and read plot metafiles
---
 examples/c/test_plbuf.c |  130 ++++++++++++++++++++++-------------------------
 1 file changed, 62 insertions(+), 68 deletions(-)

diff --git a/examples/c/test_plbuf.c b/examples/c/test_plbuf.c
index bc10976..bed0a8f 100644
--- a/examples/c/test_plbuf.c
+++ b/examples/c/test_plbuf.c
@@ -31,24 +31,21 @@
 #endif
 #include "plstrm.h"
 
+// Which test device to use.  The svg device is the best choice, however,
+// I (jrd) find it easier to debug with psc.  YMMV.
+#define TEST_DEVICE "psc"
+
 // Reach into the guts of PLPlot to get access to the current stream.
 // Not recommended behavior for user program.  Only needed for testing.
 extern PLDLLIMPEXP_DATA( PLStream * ) plsc;
 
 // Variables and data arrays used by plot generators
 
-static PLFLT        x[101], y[101];
-static PLFLT        xscale, yscale, xoff, yoff, xs[6], ys[6];
 static PLGraphicsIn gin;
 
-static int          locate_mode;
-static int          test_xor;
-static int          fontset = 1;
-static char         *f_name = NULL;
-
 // Function prototypes
 
-void plot1( int );
+void plot1( PLFLT xscale, PLFLT yscale, PLFLT xoff, PLFLT yoff );
 void plot2( void );
 void plot3( void );
 
@@ -67,66 +64,85 @@ void plot3( void );
 int
 main( int argc, const char *argv[] )
 {
-    PLINT digmax, cur_strm, new_strm;
+    PLINT cur_strm, new_strm;
     char  ver[80];
 
     // plplot initialization
 
+    // Set the output filename
+    plsfnam( "test_plbuf_0.out" );
+
     // Parse and process command line arguments
 
     plparseopts( &argc, argv, PL_PARSE_FULL );
 
-    // For the plot buffer on.  Typically the plot buffer is only used
-    // by interactive drivers and the plmeta driver
+    // Force the plot buffer on.  Typically the plot buffer is only used
+    // by interactive drivers and the plmeta driver.  Must do this before
+    // plot initialization occurs otherwise commands will be missed
+    // by the interactive drivers and the plmeta driver
     plsc->plbuf_write = 1;
 
-    plinit();
-    plreadmetafile( NULL );
-    plreplot();
-
-    exit( 0 );
     // Initialize plplot
     // Divide page into 2x2 plots
-    // Note: calling plstar replaces separate calls to plssub and plinit
-    plstar( 2, 2 );
-
-    // Set up the data
-    // Original case
-    xscale = 6.;
-    yscale = 1.;
-    xoff   = 0.;
-    yoff   = 0.;
+    // Note: calling plstart replaces separate calls to plssub and plinit
+    plstart( TEST_DEVICE, 2, 2 );
 
-    // Do a plot
-    plot1( 0 );
+    // Generate the plot for the first subwindow
+    plot1( 6.0, 1.0, 0.0, 0.0 );
 
-    // Set up the data
-    xscale = 1.;
-    yscale = 0.0014;
-    yoff   = 0.0185;
-
-    // Do a plot
-    digmax = 5;
-    plsyax( digmax, 0 );
-
-    plot1( 1 );
+    // Set the y-axis to 5 digits maximum and generate the plot for
+    // the second subwindow
+    plsyax( 5, 0 );
+    plot1( 1.0, 0.0014, 0.0, 0.0185 );
 
+    // Generate a plot for the third subwindow
     plot2();
 
+    // Generate a plot for the fourth subwindow
     plot3();
 
     // Replay the plot buffer
     plgstrm( &cur_strm );    // get current stream
     plmkstrm( &new_strm );   // create a new one
 
-    plsfnam( "foo1.ps" );    // file name
-    plsdev( "svg" );         // device type
+    plsfnam( "test_plbuf_1.out" );    // file name
+    plsdev( TEST_DEVICE );            // device type
 
     plcpstrm( cur_strm, 0 ); // copy old stream parameters to new stream
     plreplot();              // do the save by replaying the plot buffer
     plend1();                // finish the device
 
     plsstrm( cur_strm );     // return to previous stream
+    plend1();                // and end the first plot stream
+
+    // Start fresh and use the plmeta driver
+    plsfnam( "test_plbuf_0.plm" );
+    plstart( "plmeta", 2, 2 );
+
+    // Generate the same plots as before
+
+    // Generate the plot for the first subwindow
+    plot1( 6.0, 1.0, 0.0, 0.0 );
+
+    // Set the y-axis to 5 digits maximum and generate the plot for 
+    // the second subwindow
+    plsyax( 5, 0 );
+    plot1( 1.0, 0.0014, 0.0, 0.0185 );
+
+    // Generate the plot for the third subwindow
+    plot2();
+
+    // Generate the plot for the fourth subwindow
+    plot3();
+
+    // Finish this stream
+    plend1();
+
+    // Test reading of PLplot metafiles
+    plsfnam( "test_plbuf_2.out" );
+    plsdev( TEST_DEVICE );
+    //plstart( TEST_DEVICE, 2, 2 );
+    plreadmetafile( "test_plbuf_0.plm" );
 
     // Don't forget to call plend() to finish off!
     plend();
@@ -136,8 +152,10 @@ main( int argc, const char *argv[] )
 //--------------------------------------------------------------------------
 
 void
-plot1( int do_test )
+plot1( PLFLT xscale, PLFLT yscale, PLFLT xoff, PLFLT yoff )
 {
+    static PLFLT x[101], y[101];
+    static PLFLT xs[6], ys[6];
     int   i;
     PLFLT xmin, xmax, ymin, ymax;
 
@@ -177,34 +195,6 @@ plot1( int do_test )
 
     plcol0( 3 );
     plline( 60, x, y );
-
-// xor mode enable erasing a line/point/text by replotting it again
-// it does not work in double buffering mode, however
-
-    if ( do_test && test_xor )
-    {
-#ifdef PL_HAVE_NANOSLEEP
-        PLINT           st;
-        struct timespec ts;
-        ts.tv_sec  = 0;
-        ts.tv_nsec = 50000000;
-        plxormod( 1, &st ); // enter xor mode
-        if ( st )
-        {
-            for ( i = 0; i < 60; i++ )
-            {
-                plpoin( 1, x + i, y + i, 9 );   // draw a point
-                nanosleep( &ts, NULL );         // wait a little
-                plflush();                      // force an update of the tk driver
-                plpoin( 1, x + i, y + i, 9 );   // erase point
-            }
-            plxormod( 0, &st );                 // leave xor mode
-        }
-#else
-        printf( "The -xor command line option can only be exercised if your "
-            "system\nhas nanosleep(), which does not seem to happen.\n" );
-#endif
-    }
 }
 
 //--------------------------------------------------------------------------
@@ -212,6 +202,8 @@ plot1( int do_test )
 void
 plot2( void )
 {
+    static PLFLT x[101], y[101];
+    static PLFLT xs[6], ys[6];
     int i;
 
 // Set up the viewport and window using PLENV. The range in X is -2.0 to
@@ -246,6 +238,8 @@ plot2( void )
 void
 plot3( void )
 {
+    static PLFLT x[101], y[101];
+    static PLFLT xs[6], ys[6];
     PLINT space0 = 0, mark0 = 0, space1 = 1500, mark1 = 1500;
     int   i;
 
-- 
1.7.10.4


From 72b52d3e7e176a93e0205028578c10907a1ba318 Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Tue, 17 Feb 2015 12:59:04 -0500
Subject: [PATCH 4/6] Added free() for the metafile variables in the plot
 stream

---
 src/plcore.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/plcore.c b/src/plcore.c
index 74a0442..49337f2 100644
--- a/src/plcore.c
+++ b/src/plcore.c
@@ -2491,6 +2491,12 @@ c_plend1( void )
 
     closeqsas( &( plsc->qsasconfig ) );
 
+    // Free memory used by the plot metafiles
+    if ( plsc->mf_infile )
+        free_mem( plsc->mf_infile );
+    if ( plsc->mf_outfile )
+        free_mem( plsc->mf_outfile );
+
 // Free malloc'ed stream if not in initial stream, else clear it out
 
     if ( ipls > 0 )
-- 
1.7.10.4


From 5a7a38ac911e3f4e2c7d52f67405f621380768ab Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Tue, 17 Feb 2015 13:00:13 -0500
Subject: [PATCH 5/6] Added a placeholder for the PLSTATE_CHR and PLSTATE_SYM
 operations

The 2005 metafile version does not support these two operations.  The new
version will.
---
 drivers/plmeta.c |   18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/plmeta.c b/drivers/plmeta.c
index 321aeba..dbf3937 100644
--- a/drivers/plmeta.c
+++ b/drivers/plmeta.c
@@ -386,7 +386,25 @@ plD_state_plm( PLStream *pls, PLINT op )
             plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap1[i].b ) );
         }
         break;
+
+    case PLSTATE_CHR:
+        // Disabled for now because the 2005 version does not
+        // support this command
+        //save the chrdef and chrht parameters
+        //plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->chrdef ) );
+        //plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->chrht ) );
+        break;
+
+    case PLSTATE_SYM:
+        // Disabled for now because the 2005 version does not
+        // support this command
+        //save the symdef and symht parameters
+        //plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->symdef ) );
+        //plm_wr( pdf_wr_ieeef( pls->pdfs, (float) pls->symht ) );
+        break;
+
     }
+
 }
 
 //--------------------------------------------------------------------------
-- 
1.7.10.4


From 50b350298708937fe26357f0d6a6c71ecf1d0397 Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Tue, 17 Feb 2015 13:01:18 -0500
Subject: [PATCH 6/6] Fixes to reading plot metafiles

The original plan to utilize the plot buffer did not work because the
coordinate system used in the plot metafile is not compatible with
the device level coordinate system that is in the plot buffer.

In order to keep redraws (one of the key uses of the plot buffer) fast,
the same strategy used by plrender was adopted.  The metafile coordinate
system is used to setup a coordinate system via plvpor() and plwind().

This will need to be revisited for the next revision to the plot buffers
that will support switching of devices to handle saving/printing.
---
 include/metadefs.h |    5 +-
 src/plmetafile.c   |  411 ++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 321 insertions(+), 95 deletions(-)

diff --git a/include/metadefs.h b/include/metadefs.h
index 56f9174..9c90512 100644
--- a/include/metadefs.h
+++ b/include/metadefs.h
@@ -90,9 +90,12 @@ typedef struct
     FPOS_T  index_offset; // Position of the metafile index
     FPOS_T  lp_offset;    // Position of the previous page
 
-
     int     notfirst;
 
     PLINT   version;    // Metafile version number
     U_SHORT page;       // Current page
+
+    // Viewport configuration. Used to render a metafile
+    PLFLT vpxmin, vpymin;
+    PLFLT vpxmax, vpymax;
 } PLmDev;
diff --git a/src/plmetafile.c b/src/plmetafile.c
index c526b33..a1ac9e0 100644
--- a/src/plmetafile.c
+++ b/src/plmetafile.c
@@ -32,8 +32,6 @@
 
 #define MAX_BUFFER    256 // Character buffer size for reading records
 
-void plbuf_write( PLStream *pls, void *data, size_t bytes );
-
 // Status codes
 enum _plm_status
 {
@@ -409,29 +407,30 @@ enum _plm_status read_header( PDFstrm *plm,
 static
 enum _plm_status read_line( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 {
-    short            xy_list[4];
+    PLFLT            x_list[2], y_list[2];
     enum _plm_status rc;
 
     // Read the start and end points
     // The metafile stores the points as x,y pairs
-    rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy_list[0] );  // x1
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x_list[0] );  // x1
     if ( rc != PLM_SUCCESS )
         return rc;
-    rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy_list[2] );  // y1
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y_list[0] );  // y1
     if ( rc != PLM_SUCCESS )
         return rc;
-    rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy_list[1] );  // x2
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x_list[1] );  // x2
     if ( rc != PLM_SUCCESS )
         return rc;
-    rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy_list[3] );  // y2
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y_list[1] );  // y2
     if ( rc != PLM_SUCCESS )
         return rc;
 
-    plbuf_write( pls, xy_list, sizeof ( xy_list ) );
+    // Draw the line
+    plline( 2, x_list, y_list );
 
     // Preserve the last XY coords for the LINETO command
-    dev->xold = xy_list[1];
-    dev->yold = xy_list[3];
+    dev->xold = (short) x_list[1];
+    dev->yold = (short) y_list[1];
 
     return PLM_SUCCESS;
 }
@@ -444,27 +443,28 @@ enum _plm_status read_line( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 static
 enum _plm_status read_lineto( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 {
-    short            xy_list[4];
+    PLFLT            x_list[2], y_list[2];
     int              i;
     enum _plm_status rc;
 
     // Set the start to the last known position
-    xy_list[0] = dev->xold;
-    xy_list[2] = dev->yold;
+    x_list[0] = (PLFLT) dev->xold;
+    y_list[0] = (PLFLT) dev->yold;
 
     // Read the end point
-    rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy_list[1] );
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x_list[1] );
     if ( rc != PLM_SUCCESS )
         return rc;
-    rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy_list[3] );
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y_list[1] );
     if ( rc != PLM_SUCCESS )
         return rc;
 
-    plbuf_write( pls, xy_list, sizeof ( xy_list ) );
+    // Draw the line
+    plline( 2, x_list, y_list );
 
     // Preserve the last XY coords for the LINETO command
-    dev->xold = xy_list[1];
-    dev->yold = xy_list[3];
+    dev->xold = (short) x_list[1];
+    dev->yold = (short) y_list[1];
 
     return PLM_SUCCESS;
 }
@@ -478,39 +478,47 @@ static
 enum _plm_status read_polyline( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 {
     PLINT            i, npts;
-    short            j, xy;
+    PLFLT            *x_list, *y_list;
     enum _plm_status rc;
 
     // Read the number of control points
     rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &npts );
     if ( rc != PLM_SUCCESS )
         return rc;
-    plbuf_write( pls, &npts, sizeof ( npts ) );
+
+    // Not optimal to alloc/dealloc memory, but it works for now
+    if( ( x_list = malloc( npts * sizeof(PLFLT) ) ) == NULL ) {
+        plexit("read_polyline: Unable to allocate memory\n");
+    }
+    if( ( y_list = malloc( npts * sizeof(PLFLT) ) ) == NULL ) {
+        plexit("read_polyline: Unable to allocate memory\n");
+    }
 
     // Read the points and insert into the plot buffer
     // The x values
     for ( i = 0; i < npts; i++ )
     {
-        rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy );
+        rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, x_list + i );
         if ( rc != PLM_SUCCESS )
             return rc;
-
-        plbuf_write( pls, &xy, sizeof ( xy ) );
     }
-    // Preserve the last XY coords for the LINETO command
-    dev->xold = xy;
-
     // The y values
     for ( i = 0; i < npts; i++ )
     {
-        rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy );
+        rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, y_list + i );
         if ( rc != PLM_SUCCESS )
             return rc;
-
-        plbuf_write( pls, &xy, sizeof ( xy ) );
     }
-    // Preserve the last XY coords for the LINETO command
-    dev->yold = xy;
+
+    // Draw the line
+    plline( npts, x_list, y_list );
+
+    // Preserve the last X coord for the LINETO command
+    dev->xold = (short) x_list[npts - 1];
+    dev->yold = (short) y_list[npts - 1];
+
+    free(x_list);
+    free(y_list);
 
     return PLM_SUCCESS;
 }
@@ -530,35 +538,42 @@ enum _plm_status read_escape( PDFstrm *plm, PLmDev *dev, PLStream *pls )
     if ( pdf_rd_1byte( plm, &op ) != 0 )
         return PLM_FORMAT_ERROR;
 
-    // Put the command into the plot buffer
-    plbuf_write( pls, &op, sizeof ( op ) );
-
     switch ( op )
     {
     case PLESC_FILL:
     {
         PLINT i, npts;
-        short xy[2];
+	PLFLT *x_list, *y_list;
 
         // Get the number of control points for the fill
         rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &npts );
         if ( rc != PLM_SUCCESS )
             return rc;
 
-        plbuf_write( pls, &npts, sizeof ( npts ) );
+	// Not optimal to alloc/dealloc memory, but it works for now
+	if( ( x_list = malloc( npts * sizeof(PLFLT) ) ) == NULL ) {
+	    plexit("read_escape: Unable to allocate memory\n");
+	}
+	if( ( y_list = malloc( npts * sizeof(PLFLT) ) ) == NULL ) {
+	    plexit("read_escape: Unable to allocate memory\n");
+	}
 
         for ( i = 0; i < npts; i++ )
         {
-            rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy[0] );
+            rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, x_list + i );
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            rc = read_entry( plm, PDF_USHORT, PLP_SHORT, &xy[1] );
+            rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, y_list + i );
             if ( rc != PLM_SUCCESS )
                 return rc;
-
-            plbuf_write( pls, xy, sizeof ( xy ) );
         }
+
+	plfill( npts, x_list, y_list );
+	
+	free(x_list);
+	free(y_list);
+
     }
     break;
 
@@ -588,9 +603,6 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
     if ( pdf_rd_1byte( plm, &op ) != 0 )
         return PLM_FORMAT_ERROR;
 
-    // Put the command into the plot buffer
-    plbuf_write( pls, &op, sizeof ( op ) );
-
     switch ( op )
     {
     case PLSTATE_WIDTH:
@@ -603,25 +615,24 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            plbuf_write( pls, &width, sizeof ( width ) );
+	    plwidth ( width );
         }
         break;
 
     case PLSTATE_COLOR0:
-    case PLSTATE_COLOR1:
-        pldebug( "state: COLOR0/COLOR1" );
+        pldebug( "state: COLOR0" );
+
         {
             PLINT icol;
 
-            // Read the color index number and place into the buffer
+            // Read the color index number
             rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &icol );
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            plbuf_write( pls, &icol, sizeof ( icol ) );
-
-            if ( op == PLSTATE_COLOR0 && icol == PL_RGB_COLOR )
+            if ( icol == PL_RGB_COLOR )
             {
+ 	        // Set pen 0 to the specified RGB value
                 PLColor color;
 
                 rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.r );
@@ -639,30 +650,62 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
                 color.a    = 1.0;
                 color.name = NULL;
 
-                plbuf_write( pls, &color, sizeof ( color ) );
-            }
+		plscol0( icol, color.r, color.g, color.b );
+            } 
+	    else 
+	    {
+  	        // Set color for pen 0
+  	        plcol0( icol );
+	    }
+	}
+	break;
+
+    case PLSTATE_COLOR1:
+        pldebug( "state: COLOR1" );
+
+	{
+            PLINT icol;
+
+            // Read the color index number
+            rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &icol );
+            if ( rc != PLM_SUCCESS )
+                return rc;
+
+	    plcol1( icol );
         }
         break;
 
     case PLSTATE_FILL:
         pldebug( "state: FILL" );
+
+	{
+	    U_CHAR pattern;
+
+            // Read the color index number
+            rc = read_entry( plm, PDF_USHORT, PLP_UCHAR, &pattern );
+            if ( rc != PLM_SUCCESS )
+                return rc;
+	    
+	    plpsty( pattern );
+	}
         break;
 
     case PLSTATE_CMAP0:
-    case PLSTATE_CMAP1:
-        pldebug( "state: CMAP0/CMAP1" );
+        pldebug( "state: CMAP0" );
+
         {
             PLINT   i, ncol;
             PLColor color;
 
-            // Read the number of colors and place into the buffer
+            // Read the number of colors
             rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &ncol );
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            plbuf_write( pls, &ncol, sizeof ( ncol ) );
+	    // Set the number of colors in the colormap
+	    plscmap0n( ncol );
 
-            // Read the colormap and place into the buffer
+            // Read the colormap
             for ( i = 0; i < ncol; i++ )
             {
                 rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.r );
@@ -679,18 +722,113 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 
                 color.a    = 1.0;
                 color.name = NULL;
+		
+		// Save the color for this entry
+		plsc->cmap0[i].r = color.r;
+		plsc->cmap0[i].g = color.g;
+		plsc->cmap0[i].b = color.b;
+		plsc->cmap0[i].a = color.a;
+		plsc->cmap0[i].name = color.name;
+            }
+
+	    if( plsc->level > 0 )
+	      plP_state( PLSTATE_CMAP0 );
+        }
+        break;
+
+    case PLSTATE_CMAP1:
+        pldebug( "state: CMAP0" );
+
+        {
+            PLINT   i, ncol;
+            PLColor color;
+
+            // Read the number of colors
+            rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &ncol );
+            if ( rc != PLM_SUCCESS )
+                return rc;
+
+	    // Set the number of colors in the colormap
+	    plscmap1n( ncol );
+
+            // Read the colormap
+            for ( i = 0; i < ncol; i++ )
+            {
+                rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.r );
+                if ( rc != PLM_SUCCESS )
+                    return rc;
+
+                rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.g );
+                if ( rc != PLM_SUCCESS )
+                    return rc;
+
+                rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.b );
+                if ( rc != PLM_SUCCESS )
+                    return rc;
 
-                plbuf_write( pls, &color, sizeof ( color ) );
+                color.a    = 1.0;
+                color.name = NULL;
+		
+		// Save the color for this entry
+		plsc->cmap1[i].r = color.r;
+		plsc->cmap1[i].g = color.g;
+		plsc->cmap1[i].b = color.b;
+		plsc->cmap1[i].a = color.a;
+		plsc->cmap1[i].name = color.name;
             }
+
+	    if( plsc->level > 0 )
+	      plP_state( PLSTATE_CMAP1 );
         }
         break;
 
     case PLSTATE_CHR:
         pldebug( "state: CHR" );
+
+	// Note: The operation is not put into the buffer because
+	// this operation is not supported in the 2005 format.
+	// This code is a placeholder until a new version is made
+	// Put the command into the plot buffer
+
+	if(0) 
+	{
+  	    PLFLT chrdef;
+  	    PLFLT chrht;
+
+	    rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &chrdef );
+	    if(rc != PLM_SUCCESS) 
+	        return rc;
+
+	    rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &chrht );
+	    if(rc != PLM_SUCCESS) 
+	        return rc;
+	    
+	}
         break;
 
     case PLSTATE_SYM:
         pldebug( "state: SYM" );
+
+	// Note: The operation is not put into the buffer because
+	// this operation is not supported in the 2005 format.
+	// This code is a placeholder until a new version is made
+	// Put the command into the plot buffer
+
+	if(0) 
+	{
+  	    PLFLT symdef;
+  	    PLFLT symht;
+
+	    rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &symdef );
+	    if(rc != PLM_SUCCESS) 
+	        return rc;
+
+	    rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &symht );
+	    if(rc != PLM_SUCCESS) 
+	        return rc;
+	    
+
+	}
         break;
 
     default:
@@ -723,9 +861,7 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
         {
         case INITIALIZE:
             pldebug( "cmd: INITIALIZE" );
-
-            // Put the command into the plot buffer
-            plbuf_write( pls, &cmd, sizeof ( cmd ) );
+	    // No action needed
             break;
 
         case CLOSE:
@@ -735,19 +871,13 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 
         case EOP:
             pldebug( "cmd: EOP" );
-
-            // Put the command into the plot buffer
-            plbuf_write( pls, &cmd, sizeof ( cmd ) );
+            // No action needed
             break;
 
         case BOP:
         case BOP0:                   // First BOP in a file
             pldebug( "cmd: BOP/BOP0" );
 
-            // Put the command into the plot buffer
-            cmd = BOP;
-            plbuf_write( pls, &cmd, sizeof ( cmd ) );
-
             // Read the metadata for this page
             rc = read_entry( plm,
                 page_2005_header[0].pdf_type,
@@ -770,62 +900,54 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
             if ( rc != PLM_SUCCESS )
                 break;
 
-            // Push state information into the plot buffer
-            plbuf_write( pls, &( pls->icol0 ), sizeof ( pls->icol0 ) );
-            plbuf_write( pls, &( pls->icol1 ), sizeof ( pls->icol1 ) );
-            plbuf_write( pls, &( pls->curcolor ), sizeof ( pls->curcolor ) );
+
+	    // Setup the subwindows
+	    //plP_ssub( pls->nsubx, pls->nsuby, pls->cursub );
+	    plP_setsub();
+	    
+	    plvpor( 
+	        dev->vpxmin, dev->vpxmax, 
+		dev->vpymin, dev->vpymax );
+	    plwind( 
+	        ( PLFLT) dev->xmin, (PLFLT) dev->xmax, 
+		( PLFLT) dev->ymin, (PLFLT) dev->ymax );
 
             break;
 
         case LINE:
             pldebug( "cmd: LINE" );
 
-            // Put the command into the plot buffer
-            plbuf_write( pls, &cmd, sizeof ( cmd ) );
-
             rc = read_line( plm, dev, pls );
             break;
 
         case LINETO:
             pldebug( "cmd: LINETO" );
 
-            // Put the command into the plot buffer
-            cmd = LINE;
-            plbuf_write( pls, &cmd, sizeof ( cmd ) );
-
             rc = read_lineto( plm, dev, pls );
             break;
 
         case ESCAPE:
             pldebug( "cmd: ESCAPE" );
 
-            // Put the command into the plot buffer
-            plbuf_write( pls, &cmd, sizeof ( cmd ) );
-
             rc = read_escape( plm, dev, pls );
             break;
 
         case POLYLINE:
             pldebug( "cmd: POLYLINE" );
 
-            // Put the command into the plot buffer
-            plbuf_write( pls, &cmd, sizeof ( cmd ) );
-
             rc = read_polyline( plm, dev, pls );
             break;
 
         case CHANGE_STATE:
             pldebug( "cmd: CHANGE_STATE" );
 
-            // Put the command into the plot buffer
-            plbuf_write( pls, &cmd, sizeof ( cmd ) );
-
             rc = read_state( plm, dev, pls );
             break;
 
         case END_OF_FIELD:
             pldebug( "cmd: EOF" );
-            plabort( "EOF" );
+	    
+	    // No action needed
 
             break;
 
@@ -851,11 +973,96 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
     return PLM_SUCCESS;
 }
 
+static
+void setup_page( PLmDev *dev )
+{
+    PLFLT aspect;
+    PLINT dev_xmin, dev_ymin;
+    PLINT dev_xmax, dev_ymax;
+    PLINT dev_xlen, dev_ylen;
+    PLFLT dev_xpmm, dev_ypmm;
+    PLFLT dev_aspect;
+    PLFLT ratio;
+    PLFLT vpxlen, vpylen;
+    PLINT nsubx, nsuby, cursub;
+    
+    // Determine the current subpage
+    plP_gsub( &nsubx, &nsuby, &cursub );
+
+    // Are we on a valid subpage?
+    if( cursub == 0 || cursub > nsubx * nsuby ) {
+        // No, it appears that the current subpage is unintialized or the
+        // subpage is not valid for the current supbage configuration
+        cursub = 1;
+
+	// Set the subpage information
+	plP_ssub( nsubx, nsuby, cursub );
+	plP_setsub();
+    }
+
+    // Set aspect ratio to the natural ratio of the metafile coordinate system.
+    
+    // For older versions of plplot, the length is not set.  Do it here
+    // just in case.
+    dev->xlen = dev->xmax - dev->xmin;
+    dev->ylen = dev->ymax - dev->ymin;
+
+    // Aspect ration of the plot metafile
+    aspect = ( ( ( PLFLT ) dev->ylen) / dev->pxly ) 
+        / ( ( ( PLFLT ) dev->xlen ) / dev->pxlx );
+
+    // Aspect ratio of the current output device
+    plP_gphy( &dev_xmin, &dev_xmax, &dev_ymin, &dev_ymax );
+    plP_gpixmm( &dev_xpmm, &dev_ypmm );
+
+    dev_xlen = dev_xmax - dev_xmin;
+    dev_ylen = dev_ymax - dev_ymin;
+
+    dev_aspect = ( ( ( PLFLT ) dev_ylen ) / dev_ypmm ) 
+        / ( ( ( PLFLT ) dev_xlen ) / dev_xpmm );
+
+    if ( dev_aspect <= 0. )
+        fprintf( stderr, "Aspect ratio error: dev_aspect = %f\n", dev_aspect );
+
+    ratio = aspect / dev_aspect;
+
+    // Default relative coordinate space
+    vpxlen = 1.0;
+    vpylen = 1.0;
+    dev->vpxmin = 0.5 - vpxlen / 2.;
+    dev->vpymin = 0.5 - vpylen / 2.;
+    dev->vpxmax = dev->vpxmin + vpxlen;
+    dev->vpymax = dev->vpymin + vpylen;
+
+    //
+    // Construct viewport that preserves the aspect ratio of the original 
+    // device (plmeta output file).  Thus you automatically get all physical 
+    // coordinate plots to come out correctly.  Note: this could also be done 
+    // using the driver interface function plsdimap.
+    //
+
+    if ( ratio <= 0 )
+        fprintf( stderr, "Aspect ratio error: ratio = %f\n", ratio );
+    else if ( ratio < 1 )
+        vpylen = ratio;
+    else
+        vpxlen = 1. / ratio;
+
+    dev->vpxmin = ( 1. - vpxlen ) / 2.;
+    dev->vpxmax = dev->vpxmin + vpxlen;
+
+    dev->vpymin = ( 1. - vpylen ) / 2.;
+    dev->vpymax = dev->vpymin + vpylen;
+}
+
 //--------------------------------------------------------------------------
 // plreadmetafile()
 //
 //! Reads a PLplot metafile and uses the current plot stream to display
-//! the contents.
+//! the contents.  If the plot stream has not been initialized, this
+//! routine will attempt to intialize the plot stream via a plinit() 
+//! call.  For an initialized plot stream, the metafile will start at the 
+//! current page/subpage.  
 //!
 //! @param infile  Input PLplot metafile name.
 //!
@@ -867,6 +1074,7 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 void plreadmetafile( char *infile )
 {
     PDFstrm          *plm;
+    PLStream         mf_pls;
     PLmDev           dev;
     PLmIndex         index;
     enum _plm_status rc;
@@ -918,10 +1126,14 @@ void plreadmetafile( char *infile )
         return;
     }
 
-    // Read the plot header
+    // Read the plot header into a local version of a plot stream.
+    // We do this because some of the parameters from the metafile may
+    // be invalid or inappropriate for the current plot device 
+    // (e.g. xlength = 0).  The plspage() call should be smart enough
+    // to setup the page correctly.
     rc = read_header( plm,
         metafile_format[dev.version].plot_header,
-        (U_CHAR *) plsc );
+        (U_CHAR *) &mf_pls );
     if ( rc != PLM_SUCCESS )
     {
         pdf_close( plm );
@@ -929,8 +1141,19 @@ void plreadmetafile( char *infile )
         return;
     }
 
-    // Attempt to (re-)initialize the plot buffer
-    plbuf_init( plsc );
+    // Set the physical characterisics of the output device if the current
+    // stream has not been initialized
+    if( plsc->level == 0 ) {
+        plspage( mf_pls.xdpi, mf_pls.ydpi,
+	    mf_pls.xlength, mf_pls.ylength,
+	    mf_pls.xoffset, mf_pls.yoffset );
+
+	plinit();
+    }
+
+    // Configure the plot match the configuration used when the plot
+    // was created
+    setup_page( &dev );
 
     // At this point we should be in the plot commands
     rc = read_plot_commands( plm, &dev, plsc );
-- 
1.7.10.4

