From 8726f767fe87ea7551d26f6915255ec67096fc52 Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Sat, 24 Jan 2015 19:07:45 -0500
Subject: [PATCH 1/7] Changed the if logic for PLSTATE_CMAP0 and PLSTATE_CMAP1
 that puts both the empty colormap and too small
 colormap cases into one block. This eliminates
 duplicative code.

Reformatted some long line wraps and fixed some odd indenting.
---
 src/plbuf.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/plbuf.c b/src/plbuf.c
index cf830cd..bf8f9e1 100644
--- a/src/plbuf.c
+++ b/src/plbuf.c
@@ -751,7 +751,7 @@ rdbuf_state( PLStream *pls )
                 plexit( "Insufficient memory for colormap 1" );
             }
         }
-
+        
         // Now read the colormap from the buffer
         rd_data( pls, &(pls->cmap1[0]), size );
         pls->ncol1 = ncol;
-- 
1.7.10.4


From d6a6e3cfc5010d67b12a340ecc14d17015fa512f Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Wed, 28 Jan 2015 21:40:54 -0500
Subject: [PATCH 2/7] Added obsolete commands to plbuf_control to attempt some
 backwards compatabilty with old plot metafiles.

Removed unneeded malloc() and memcpy for LINE, POLYINE, and FILL when
remaking the plot.  Temporary storage was used because of the old
file-based buffer approach.  With the removal of file-based buffer
code, a different apporach that uses pointers into the plot buffer could
be used.

Fixed the bug that caused random segfaults.  This could be manifested
in several ways, one of them being a POLYLINE with over a billion nodes.
The root cause was a mismatch in the data sizes between the buffer writer
and the buffer reader (a wrong sizeof() was used).  Changed the code
to use sizeof(variable) instead of sizeof(data type).

Changed the buffer writer to maintain two-byte alignment.  This should
avoid the performance penalty associated with misaligned arrays.
---
 src/plbuf.c |   28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/src/plbuf.c b/src/plbuf.c
index bf8f9e1..099349b 100644
--- a/src/plbuf.c
+++ b/src/plbuf.c
@@ -49,6 +49,7 @@ static void     wr_data( PLStream *pls, void *buf, size_t buf_size );
 static void     plbuf_control( PLStream *pls, U_CHAR c );
 static void     plbuf_fill( PLStream *pls );
 static void     plbuf_swin( PLStream *pls, PLWindow *plwin );
+static void     check_buffer_size( PLStream *pls, size_t data_size );
 
 static void     rdbuf_init( PLStream *pls );
 static void     rdbuf_line( PLStream *pls );
@@ -613,6 +614,33 @@ rdbuf_polyline( PLStream *pls )
 }
 
 //--------------------------------------------------------------------------
+// rdbuf_eop()
+//
+// End of page.
+//--------------------------------------------------------------------------
+
+static void
+rdbuf_eop( PLStream * PL_UNUSED( pls ) )
+{
+    dbug_enter( "rdbuf_eop" );
+}
+
+//--------------------------------------------------------------------------
+// rdbuf_bop()
+//
+// Set up for the next page.
+//--------------------------------------------------------------------------
+
+static void
+rdbuf_bop( PLStream *pls )
+{
+    dbug_enter( "rdbuf_bop" );
+
+    pls->nplwin = 0;
+>>>>>>> Added obsolete commands to plbuf_control to attempt some backwards
+}
+
+//--------------------------------------------------------------------------
 // rdbuf_state()
 //
 // Handle change in PLStream state (color, pen width, fill attribute, etc).
-- 
1.7.10.4


From 1ebafec74faff708c9ff1b3dadf7dcd7be8c1043 Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Thu, 12 Feb 2015 23:03:13 -0500
Subject: [PATCH 3/7] Fixes to preserving state information in the plot buffer

---
 src/plbuf.c      |   30 ++----------------------------
 src/plmetafile.c |    1 +
 2 files changed, 3 insertions(+), 28 deletions(-)

diff --git a/src/plbuf.c b/src/plbuf.c
index 099349b..c1f2a0b 100644
--- a/src/plbuf.c
+++ b/src/plbuf.c
@@ -151,7 +151,7 @@ plbuf_bop( PLStream *pls )
     // Save the colormaps
     plbuf_state(pls, PLSTATE_CMAP0);
     plbuf_state(pls, PLSTATE_CMAP1);
-
+    
     // Initialize to a known state
     //plbuf_state( pls, PLSTATE_COLOR0 );
     //plbuf_state( pls, PLSTATE_WIDTH );
@@ -614,33 +614,6 @@ rdbuf_polyline( PLStream *pls )
 }
 
 //--------------------------------------------------------------------------
-// rdbuf_eop()
-//
-// End of page.
-//--------------------------------------------------------------------------
-
-static void
-rdbuf_eop( PLStream * PL_UNUSED( pls ) )
-{
-    dbug_enter( "rdbuf_eop" );
-}
-
-//--------------------------------------------------------------------------
-// rdbuf_bop()
-//
-// Set up for the next page.
-//--------------------------------------------------------------------------
-
-static void
-rdbuf_bop( PLStream *pls )
-{
-    dbug_enter( "rdbuf_bop" );
-
-    pls->nplwin = 0;
->>>>>>> Added obsolete commands to plbuf_control to attempt some backwards
-}
-
-//--------------------------------------------------------------------------
 // rdbuf_state()
 //
 // Handle change in PLStream state (color, pen width, fill attribute, etc).
@@ -1345,6 +1318,7 @@ static void
 wr_data( PLStream *pls, void *buf, size_t buf_size )
 {
     check_buffer_size(pls, buf_size);
+
     memcpy( (uint8_t *) pls->plbuf_buffer + pls->plbuf_top, buf, buf_size );
 
     // Advance position but maintain alignment
diff --git a/src/plmetafile.c b/src/plmetafile.c
index 52c9dc4..f8c4e73 100644
--- a/src/plmetafile.c
+++ b/src/plmetafile.c
@@ -203,6 +203,7 @@ enum _plm_status set_ulong_plp_value(unsigned long x,
     enum _plm_status rc = PLM_SUCCESS;
 
     switch(type)
+    switch(type) 
     {
         case PLP_NULL:
 	    break;
-- 
1.7.10.4


From b56c0ef984d3da58e130e172b0c3bd62f2d5510e Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Thu, 12 Feb 2015 23:09:36 -0500
Subject: [PATCH 4/7] New plmeta implementation

* Cleanup on drivers/plmeta.c to aid transition to new implementation
* Created src/plmetafile.c to read plot metafiles
* Moved PLmDev data structure from plmeta.c to metadefs.h
* Created test routine for the plot buffer
* Updates to CMake files
---
 drivers/plmeta.c |  172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 172 insertions(+)

diff --git a/drivers/plmeta.c b/drivers/plmeta.c
index 2246980..bee07dd 100644
--- a/drivers/plmeta.c
+++ b/drivers/plmeta.c
@@ -557,6 +557,178 @@ WriteFileHeader( PLStream *pls )
 
     plm_wr( pdf_wr_header( pls->pdfs, "" ) );
 }
+    
+//--------------------------------------------------------------------------
+// WritePageInfo()
+//
+// Update table of contents info & write new page header.
+//--------------------------------------------------------------------------
+
+static void
+WritePageInfo( PLStream *pls, FPOS_T pp_offset )
+{
+    PLmDev *dev   = (PLmDev *) pls->dev;
+    FILE   *file  = pls->OutFile;
+    int    isfile = ( pls->output_type == 0 );
+    U_CHAR c;
+    FPOS_T cp_offset = 0;
+
+    // Update table of contents.
+
+    if ( isfile )
+    {
+        // Get the position of this page in order to update the index
+        if ( pl_fgetpos( file, &cp_offset ) )
+            plexit( "WritePageInfo (plmeta.c): fgetpos call failed" );
+
+        UpdateIndex( pls, cp_offset );
+    }
+
+    // Write new page header
+
+    if ( dev->notfirst )
+        c = BOP;
+    else
+    {
+        c             = BOP0;
+        dev->notfirst = 1;
+    }
+    plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
+    plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->page ) );
+    plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) pp_offset ) );
+    plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) 0 ) );
+
+    // Update last page offset with current page value
+
+    dev->lp_offset = cp_offset;
+
+    // Write some page state information just to make things nice later on
+    // Eventually there will be more
+
+    plD_state_plm( pls, PLSTATE_COLOR0 );
+}
+
+//--------------------------------------------------------------------------
+// UpdatePrevPagehdr()
+//
+// Update previous page header.
+//--------------------------------------------------------------------------
+
+static void
+UpdatePrevPagehdr( PLStream *pls )
+{
+    PLmDev *dev      = (PLmDev *) pls->dev;
+    FILE   *file     = pls->OutFile;
+    FPOS_T cp_offset = 0;
+
+    fflush( file );
+
+    // Determine where we are
+
+    if ( pl_fgetpos( file, &cp_offset ) )
+        plexit( "plD_bop_plm: fgetpos call failed" );
+
+    // Seek back to previous page header.
+
+    if ( dev->lp_offset > 0 )
+    {
+        FPOS_T fwbyte_offset = 0;
+
+        pldebug( "UpdatePrevPagehdr 1 (plmeta.c)",
+            "Location: %d, seeking to: %d\n",
+            (int) cp_offset, (int) dev->lp_offset );
+
+        // The forward byte offset is located exactly 7 bytes after the BOP
+        fwbyte_offset = dev->lp_offset + 7;
+        if ( pl_fsetpos( file, &fwbyte_offset ) )
+        {
+	    handle_fsetpos_failed("UpdatePrevPagehdr", 
+				  "fwbyte_offset", fwbyte_offset);
+        }
+
+        // DEBUG: verify current location
+
+#ifdef DEBUG
+        if ( pl_fgetpos( file, &fwbyte_offset ) )
+            plexit( "UpdatePrevPagehdr (plmeta.c): fgetpos call failed" );
+
+        pldebug( "UpdatePrevPagehdr 2 (plmeta.c)",
+            "Now at: %d, to write: %d\n",
+            (int) fwbyte_offset, (int) cp_offset );
+#endif
+
+        // Write forward byte offset into previous page header.
+
+        plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) cp_offset ) );
+        fflush( file );
+
+        // DEBUG: move back to before the write & read it to verify
+
+#ifdef DEBUG
+        if ( pl_fsetpos( file, &fwbyte_offset ) )
+        {
+  	    handle_fsetpos_failed("UpdatePrevPagehdr",
+				  "fwbyte_offset", fwbyte_offset);
+        }
+        {
+            U_LONG read_offset;
+            plm_rd( pdf_rd_4bytes( pls->pdfs, &read_offset ) );
+            pldebug( "UpdatePrevPagehdr 3 (plmeta.c)",
+                "Value read as: %d\n", read_offset );
+        }
+#endif
+
+        // Return to current page offset
+
+        if ( pl_fsetpos( file, &cp_offset ) )
+        {
+	    handle_fsetpos_failed("UpdatePrevPagehdr",
+				  "cp_offset", cp_offset);
+        }
+    }
+}
+
+//--------------------------------------------------------------------------
+// UpdateIndex()
+//
+// Update file index.
+//--------------------------------------------------------------------------
+
+static void
+UpdateIndex( PLStream *pls, FPOS_T cp_offset )
+{
+    PLmDev *dev  = (PLmDev *) pls->dev;
+    FILE   *file = pls->OutFile;
+
+    // Update file index.  Right now only number of pages.
+    // The ordering here is critical
+
+    if ( dev->index_offset > 0 )
+    {
+        pldebug( "UpdateIndex (plmeta.c)",
+            "Location: %d, seeking to: %d\n",
+            (int) cp_offset, (int) dev->lp_offset );
+
+        if ( pl_fsetpos( file, &dev->index_offset ) )
+        {
+	    handle_fsetpos_failed("UpdateIndex",
+				  "index_offset", dev->index_offset);
+        }
+        plm_wr( pdf_wr_header( pls->pdfs, "pages" ) );
+        plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->page ) );
+
+        pldebug( "UpdateIndex (plmeta.c)",
+            "Location: %d, seeking to: %d\n",
+            (int) dev->lp_offset, (int) cp_offset );
+
+        if ( pl_fsetpos( file, &cp_offset ) )
+        {
+	    handle_fsetpos_failed("UpdateIndex",
+				  "cp_offset", cp_offset);
+
+        }
+    }
+}
 
 //--------------------------------------------------------------------------
 // WritePageInfo()
-- 
1.7.10.4


From f731c43334db41fe5daab0f7de8dd9689d712e7f Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Sat, 14 Feb 2015 13:13:08 -0500
Subject: [PATCH 5/7] Revisions to plot metafiles * Added free() of memory
 allocated to metafile names * Update to test_plbuf

---
 examples/c/test_plbuf.c |  108 ++++++++++++++++++-----------------------------
 src/plcore.c            |    6 +++
 2 files changed, 47 insertions(+), 67 deletions(-)

diff --git a/examples/c/test_plbuf.c b/examples/c/test_plbuf.c
index 5205439..017b111 100644
--- a/examples/c/test_plbuf.c
+++ b/examples/c/test_plbuf.c
@@ -31,14 +31,16 @@
 #endif
 #include "plstrm.h"
 
+// Which test device to use.  svg 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;
@@ -48,7 +50,7 @@ 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 +69,60 @@ 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
-
-    // Parse and process command line arguments
-
-    plparseopts( &argc, argv, PL_PARSE_FULL );
+    // plplot initialization.
+    // Set the output filename
+    plsfnam( "test_plbuf_0.out" );
 
     // For the plot buffer on.  Typically the plot buffer is only used
-    // by interactive drivers and the plmeta driver
+    // by interactive drivers and the plmeta driver.  Must do this before
+    // plot initialization occurs otherwise commands will be missed
     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.;
-
-    // Do a plot
-    plot1( 0 );
+    plstart( TEST_DEVICE, 2, 2 );
 
-    // Set up the data
-    xscale = 1.;
-    yscale = 0.0014;
-    yoff   = 0.0185;
+    // Generate the plot for the first subwindow
+    plot1( 6.0, 1.0, 0.0, 0.0 );
 
-    // 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 );
 
+    // Genertae the plot for the third subwindow
     plot2();
 
+    // Generate the 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();                // 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
+
+    // Test reading of PLplot metafiles
+    plinit();
+    plreadmetafile(NULL);
+    plreplot();
 
     // Don't forget to call plend() to finish off!
     plend();
@@ -136,8 +132,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 +175,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 +182,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 +218,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;
 
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 c1e314f4e3c133f6f57cbbd237749634125e06f9 Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Sat, 14 Feb 2015 22:16:35 -0500
Subject: [PATCH 6/7] Corrected some comments to better explain what the code
 was doing

---
 src/plbuf.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/plbuf.c b/src/plbuf.c
index c1f2a0b..5f012c8 100644
--- a/src/plbuf.c
+++ b/src/plbuf.c
@@ -706,9 +706,8 @@ 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
-
+            // The current palatte is empty or the current palatte is not 
+            // sized correctly, 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
             if(pls->cmap0 != NULL)
@@ -739,9 +738,8 @@ 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
-
+            // The current palatte is empty or the current palatte is not 
+            // sized correctly, 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
             if(pls->cmap1 != NULL)
-- 
1.7.10.4


From 6db18bc3c10da2aa60e3886ed7a72c7db9e05fb8 Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Sun, 15 Feb 2015 00:44:17 -0500
Subject: [PATCH 7/7] More progress on implementing the new plmeta driver

* Started to put code to handle commands for the new file version
* The plmetafile import appears to work correctly, however, it does not generate identical output
* Finished the test_plbuf routine that also exercises plmetafiles
---
 drivers/plmeta.c        |  184 ++++-------------------------------------------
 examples/c/test_plbuf.c |   23 +++++-
 src/plmetafile.c        |   69 ++++++++++++++++--
 utils/plrender.c        |   13 ++++
 4 files changed, 107 insertions(+), 182 deletions(-)

diff --git a/drivers/plmeta.c b/drivers/plmeta.c
index bee07dd..5388dfa 100644
--- a/drivers/plmeta.c
+++ b/drivers/plmeta.c
@@ -386,6 +386,18 @@ plD_state_plm( PLStream *pls, PLINT op )
             plm_wr( pdf_wr_1byte( pls->pdfs, pls->cmap1[i].b ) );
         }
         break;
+
+    case PLSTATE_CHR:
+        //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:
+        //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;
     }
 }
 
@@ -730,178 +742,6 @@ UpdateIndex( PLStream *pls, FPOS_T cp_offset )
     }
 }
 
-//--------------------------------------------------------------------------
-// WritePageInfo()
-//
-// Update table of contents info & write new page header.
-//--------------------------------------------------------------------------
-
-static void
-WritePageInfo( PLStream *pls, FPOS_T pp_offset )
-{
-    PLmDev *dev   = (PLmDev *) pls->dev;
-    FILE   *file  = pls->OutFile;
-    int    isfile = ( pls->output_type == 0 );
-    U_CHAR c;
-    FPOS_T cp_offset = 0;
-
-    // Update table of contents.
-
-    if ( isfile )
-    {
-        // Get the position of this page in order to update the index
-        if ( pl_fgetpos( file, &cp_offset ) )
-            plexit( "WritePageInfo (plmeta.c): fgetpos call failed" );
-
-        UpdateIndex( pls, cp_offset );
-    }
-
-    // Write new page header
-
-    if ( dev->notfirst )
-        c = BOP;
-    else
-    {
-        c             = BOP0;
-        dev->notfirst = 1;
-    }
-    plm_wr( pdf_wr_1byte( pls->pdfs, c ) );
-    plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->page ) );
-    plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) pp_offset ) );
-    plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) 0 ) );
-
-    // Update last page offset with current page value
-
-    dev->lp_offset = cp_offset;
-
-    // Write some page state information just to make things nice later on
-    // Eventually there will be more
-
-    plD_state_plm( pls, PLSTATE_COLOR0 );
-}
-
-//--------------------------------------------------------------------------
-// UpdatePrevPagehdr()
-//
-// Update previous page header.
-//--------------------------------------------------------------------------
-
-static void
-UpdatePrevPagehdr( PLStream *pls )
-{
-    PLmDev *dev      = (PLmDev *) pls->dev;
-    FILE   *file     = pls->OutFile;
-    FPOS_T cp_offset = 0;
-
-    fflush( file );
-
-    // Determine where we are
-
-    if ( pl_fgetpos( file, &cp_offset ) )
-        plexit( "plD_bop_plm: fgetpos call failed" );
-
-    // Seek back to previous page header.
-
-    if ( dev->lp_offset > 0 )
-    {
-        FPOS_T fwbyte_offset = 0;
-
-        pldebug( "UpdatePrevPagehdr 1 (plmeta.c)",
-            "Location: %d, seeking to: %d\n",
-            (int) cp_offset, (int) dev->lp_offset );
-
-        // The forward byte offset is located exactly 7 bytes after the BOP
-        fwbyte_offset = dev->lp_offset + 7;
-        if ( pl_fsetpos( file, &fwbyte_offset ) )
-        {
-	    handle_fsetpos_failed("UpdatePrevPagehdr",
-				  "fwbyte_offset", fwbyte_offset);
-        }
-
-        // DEBUG: verify current location
-
-#ifdef DEBUG
-        if ( pl_fgetpos( file, &fwbyte_offset ) )
-            plexit( "UpdatePrevPagehdr (plmeta.c): fgetpos call failed" );
-
-        pldebug( "UpdatePrevPagehdr 2 (plmeta.c)",
-            "Now at: %d, to write: %d\n",
-            (int) fwbyte_offset, (int) cp_offset );
-#endif
-
-        // Write forward byte offset into previous page header.
-
-        plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) cp_offset ) );
-        fflush( file );
-
-        // DEBUG: move back to before the write & read it to verify
-
-#ifdef DEBUG
-        if ( pl_fsetpos( file, &fwbyte_offset ) )
-        {
-	    handle_fsetpos_failed("UpdatePrevPagehdr",
-				  "fwbyte_offset", fwbyte_offset);
-        }
-        {
-            U_LONG read_offset;
-            plm_rd( pdf_rd_4bytes( pls->pdfs, &read_offset ) );
-            pldebug( "UpdatePrevPagehdr 3 (plmeta.c)",
-                "Value read as: %d\n", read_offset );
-        }
-#endif
-
-        // Return to current page offset
-
-        if ( pl_fsetpos( file, &cp_offset ) )
-        {
-	    handle_fsetpos_failed("UpdatePrevPagehdr",
-				  "cp_offset", cp_offset);
-        }
-    }
-}
-
-//--------------------------------------------------------------------------
-// UpdateIndex()
-//
-// Update file index.
-//--------------------------------------------------------------------------
-
-static void
-UpdateIndex( PLStream *pls, FPOS_T cp_offset )
-{
-    PLmDev *dev  = (PLmDev *) pls->dev;
-    FILE   *file = pls->OutFile;
-
-    // Update file index.  Right now only number of pages.
-    // The ordering here is critical
-
-    if ( dev->index_offset > 0 )
-    {
-        pldebug( "UpdateIndex (plmeta.c)",
-            "Location: %d, seeking to: %d\n",
-            (int) cp_offset, (int) dev->lp_offset );
-
-        if ( pl_fsetpos( file, &dev->index_offset ) )
-        {
-	    handle_fsetpos_failed("UpdateIndex",
-				  "index_offset", dev->index_offset);
-        }
-        plm_wr( pdf_wr_header( pls->pdfs, "pages" ) );
-        plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) pls->page ) );
-
-        pldebug( "UpdateIndex (plmeta.c)",
-            "Location: %d, seeking to: %d\n",
-            (int) dev->lp_offset, (int) cp_offset );
-
-        if ( pl_fsetpos( file, &cp_offset ) )
-        {
-	    handle_fsetpos_failed("UpdateIndex",
-				  "cp_offset", cp_offset);
-
-        }
-    }
-}
-
 #else
 int
 pldummy_plmeta()
diff --git a/examples/c/test_plbuf.c b/examples/c/test_plbuf.c
index 017b111..302d261 100644
--- a/examples/c/test_plbuf.c
+++ b/examples/c/test_plbuf.c
@@ -117,11 +117,28 @@ main( int argc, const char *argv[] )
     plsfnam( "test_plbuf_0.plm" );
     plstart( "plmeta", 2, 2 );
 
-    // Generate the same plots
+    // 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
-    plinit();
-    plreadmetafile(NULL);
+    plsfnam ( "test_plbuf_2.out" );
+    plreadmetafile( "test_plbuf_0.plm" );
     plreplot();
 
     // Don't forget to call plend() to finish off!
diff --git a/src/plmetafile.c b/src/plmetafile.c
index f8c4e73..2ea84e8 100644
--- a/src/plmetafile.c
+++ b/src/plmetafile.c
@@ -565,14 +565,14 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
     // Read the state operation, return if an error
     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:
 	    pldebug("state: WIDTH");
 
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &op, sizeof(op));
+
 	    {
 	      PLFLT width;
 
@@ -586,6 +586,10 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
         case PLSTATE_COLOR0:
         case PLSTATE_COLOR1:
 	    pldebug("state: COLOR0/COLOR1");
+
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &op, sizeof(op));
+
 	    {
 	      PLINT icol;
 
@@ -618,11 +622,19 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 
         case PLSTATE_FILL:
 	    pldebug("state: FILL");
+
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &op, sizeof(op));
+
 	    break;
 
         case PLSTATE_CMAP0:
         case PLSTATE_CMAP1:
 	    pldebug("state: CMAP0/CMAP1");
+
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &op, sizeof(op));
+
 	    {
 	      PLINT i, ncol;
 	      PLColor color;
@@ -653,12 +665,40 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 	    }
 	    break;
 
-        case PLSTATE_CHR:
+        case PLSTATE_CHR: 
 	    pldebug("state: CHR");
+
+	    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;
+
+		plbuf_write( pls, &chrdef, sizeof(chrdef) );
+		plbuf_write( pls, &chrht, sizeof(chrht) );
+	    }
 	    break;
 
         case PLSTATE_SYM:
 	    pldebug("state: SYM");
+
+	    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;
+
+		plbuf_write( pls, &symdef, sizeof(symdef) );
+		plbuf_write( pls, &symht, sizeof(symht) );
+	    }
 	    break;
 
         default:
@@ -691,6 +731,9 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 	    case INITIALIZE:
 	        pldebug("cmd: INITIALIZE");
 
+		// Update the output device information that has not
+		plinit();
+
 		// Put the command into the plot buffer
 		plbuf_write( pls, &cmd, sizeof(cmd));
 		break;
@@ -831,6 +874,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;
@@ -876,10 +920,13 @@ 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 may be invalid 
+    // (e.g. xlength = 0).  The plspage() call should be smart enough
+    // to handle things 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);
@@ -887,7 +934,15 @@ void plreadmetafile( char *infile )
 	return;
     }
 
-    // Attempt to (re-)initialize the plot buffer
+    // 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 );
+    }
+
+    // Attempt to (re-)initialize the plot buffer for current plot stream
     plbuf_init( plsc );
 
     // At this point we should be in the plot commands
diff --git a/utils/plrender.c b/utils/plrender.c
index 4cef12a..0f4de54 100644
--- a/utils/plrender.c
+++ b/utils/plrender.c
@@ -1077,6 +1077,19 @@ plr_state( U_CHAR op )
 
         break;
     }
+
+    case PLSTATE_CHR: {
+        //plm_rd( pdf_rd_ieeef( pdfs, &plsc->chrdef ) );
+        //plm_rd( pdf_rd_ieeef( pdfs, &plsc->chrht ) );
+        break;
+    }
+
+    case PLSTATE_SYM: {
+        //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

