Imported from libpng-0.97a.tar
diff --git a/TODO b/TODO
index 605e591..e8c95ea 100644
--- a/TODO
+++ b/TODO
@@ -3,8 +3,9 @@
 add "grayscale->palette" transformation and "palette->grayscale" detection
 improved dithering
 multi-lingual error and warning message support
+sPLT chunk handling
 cHRM transformation
-sRGB chunk handling
+complete sRGB transformation (presently it simply uses gamma=0.5)
 man pages for function calls
 high-level API for reading images
 final bug fixes
diff --git a/png.h b/png.h
index 3441beb..ae7ddf0 100644
--- a/png.h
+++ b/png.h
@@ -997,8 +997,10 @@
  * more information.
  */
 
+#if !defined(PNG_NO_STDIO)
 /* Initialize the input/output for the PNG file to the default functions. */
 extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, FILE *fp));
+#endif
 
 /* Replace the (error and abort), and warning functions with user
  * supplied functions.  If no messages are to be printed you must still
@@ -1066,10 +1068,18 @@
 extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr,
    png_const_charp error));
 
+/* The same, but the chunk name is prepended to the error string. */
+extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr,
+   png_const_charp error));
+
 /* Non-fatal error in libpng.  Can continue, but may have a problem. */
 extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr,
    png_const_charp message));
 
+/* Non-fatal error in libpng, chunk name is prepended to message. */
+extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr,
+   png_const_charp message));
+
 /* The png_set_<chunk> functions are for storing values in the png_info_struct.
  * Similarly, the png_get_<chunk> calls are used to read values from the
  * png_info_struct, either storing the parameters in the passed variables, or
@@ -1202,7 +1212,7 @@
 
 #if defined(PNG_READ_sRGB_SUPPORTED)
 extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_byte *srgb_intent));
+   png_infop info_ptr, png_bytep srgb_intent));
 #endif /* PNG_READ_sRGB_SUPPORTED */
 
 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
diff --git a/pngconf.h b/pngconf.h
index 70b77c1..81f21fc 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -21,7 +21,7 @@
  * an IDAT chunk.  Make this whatever size you feel is best for your
  * machine.  One of these will be allocated per png_struct.  When this
  * is full, it writes the data to the disk, and does some other
- * calculations.  Making this an extreamly small size will slow
+ * calculations.  Making this an extremely small size will slow
  * the library down, but you may want to experiment to determine
  * where it becomes significant, if you are concerned with memory
  * usage.  Note that zlib allocates at least 32Kb also.  For readers,
@@ -30,7 +30,9 @@
  * it should not make much difference how big this is.
  */
 
+#ifndef PNG_ZBUF_SIZE
 #define PNG_ZBUF_SIZE 8192
+#endif
 
 /* If you are running on a machine where you cannot allocate more
  * than 64K of memory at once, uncomment this.  While libpng will not
@@ -54,8 +56,9 @@
 
 /* We still need stdio.h for FILE even when PNG_NO_STDIO is defined.
  */
-
+#ifndef PNG_NO_STDIO 
 #include <stdio.h>
+#endif
 
 /* This macro protects us against machines that don't have function
  * prototypes (ie K&R style headers).  If your compiler does not handle
@@ -170,9 +173,15 @@
  * a largish chunk of memory (32K), those who are not as concerned
  * with dithering quality can decrease some or all of these.
  */
+#ifndef PNG_DITHER_RED_BITS
 #define PNG_DITHER_RED_BITS 5
+#endif
+#ifndef PNG_DITHER_GREEN_BITS
 #define PNG_DITHER_GREEN_BITS 5
+#endif
+#ifndef PNG_DITHER_BLUE_BITS
 #define PNG_DITHER_BLUE_BITS 5
+#endif
 
 /* This controls how fine the gamma correction becomes when you
  * are only interested in 8 bits anyway.  Increasing this value
@@ -235,7 +244,6 @@
 #ifdef PNG_READ_FULLY_SUPPORTED
 #define PNG_PROGRESSIVE_READ_SUPPORTED
 #define PNG_READ_OPT_PLTE_SUPPORTED
-#define PNG_READ_INTERLACING_SUPPORTED
 #define PNG_READ_EXPAND_SUPPORTED
 #define PNG_READ_SHIFT_SUPPORTED
 #define PNG_READ_PACK_SUPPORTED
@@ -252,6 +260,7 @@
 #define PNG_READ_SWAP_ALPHA_SUPPORTED
 #define PNG_READ_STRIP_ALPHA_SUPPORTED
 #endif /* PNG_READ_FULLY_SUPPORTED */
+#define PNG_READ_INTERLACING_SUPPORTED
 
 #ifdef PNG_WRITE_FULLY_SUPPORTED
 #define PNG_WRITE_INTERLACING_SUPPORTED
@@ -267,7 +276,9 @@
 #define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
 #endif /*PNG_WRITE_FULLY_SUPPORTED */
 
+#if !defined(PNG_NO_STDIO)
 #define PNG_TIME_RFC1152_SUPPORTED
+#endif
 
 /* These are currently experimental features */
 #undef PNG_READ_16_TO_8_ACCURATE_SHIFT_SUPPORTED /* very little testing */
diff --git a/pngerror.c b/pngerror.c
index a800884..77232d7 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -51,6 +51,60 @@
       png_default_warning(png_ptr, message);
 }
 
+/* These utilities are used internally to build an error message which relates
+ * to the current chunk.  The chunk name comes from png_ptr->chunk_name,
+ * this is used to prefix the message.  The message is limited in length
+ * to 63 bytes, the name characters are output as hex digits wrapped in []
+ * if the character is invalid.
+ */
+#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
+static const char png_digit[16] = {
+   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+static void
+png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp message)
+{
+   int iout = 0, iin = 0;
+
+   while (iin < 4) {
+      int c = png_ptr->chunk_name[iin++];
+      if (isnonalpha(c)) {
+         buffer[iout++] = '[';
+         buffer[iout++] = png_digit[(c & 0xf0) >> 4];
+         buffer[iout++] = png_digit[c & 0xf];
+         buffer[iout++] = ']';
+      } else {
+         buffer[iout++] = c;
+      }
+   }
+
+   if (message == NULL)
+      buffer[iout++] = 0;
+   else {
+      buffer[iout++] = ':';
+      buffer[iout++] = ' ';
+      strncpy(buffer+iout, message, 64);
+      buffer[iout+63] = 0;
+   }
+}
+
+void
+png_chunk_error(png_structp png_ptr, png_const_charp message)
+{
+   char msg[16+64];
+   png_format_buffer(png_ptr, msg, message);
+   png_error(png_ptr, msg);
+}
+
+void
+png_chunk_warning(png_structp png_ptr, png_const_charp message)
+{
+   char msg[16+64];
+   png_format_buffer(png_ptr, msg, message);
+   png_warning(png_ptr, msg);
+}
+
 /* This is the default error handling function.  Note that replacements for
  * this function MUST NOT RETURN, or the program will likely crash.  This
  * function is used by default, or if the program supplies NULL for the
diff --git a/pngget.c b/pngget.c
index 549c17a..f06dde0 100644
--- a/pngget.c
+++ b/pngget.c
@@ -111,13 +111,14 @@
 
 #if defined(PNG_READ_sRGB_SUPPORTED)
 png_uint_32
-png_get_sRGB(png_structp png_ptr, png_infop info_ptr, png_byte *file_srgb_intent)
+png_get_sRGB(png_structp png_ptr, png_infop info_ptr, png_bytep
+    file_srgb_intent)
 {
    if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sRGB &&
-      *file_srgb_intent != NULL)
+      file_srgb_intent != NULL)
    {
       png_debug1(1, "in %s retrieval function\n", "sRGB");
-      *file_srgb_intent = (png_byte)info_ptr->srgb_intent;
+      *file_srgb_intent = info_ptr->srgb_intent;
       return (PNG_INFO_sRGB);
    }
    return (0);
diff --git a/pngpread.c b/pngpread.c
index a333513..e892a62 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -1056,10 +1056,7 @@
 
    if (!(png_ptr->chunk_name[0] & 0x20))
    {
-      char msg[40];
-
-      sprintf(msg, "Unknown critical chunk %s", png_ptr->chunk_name);
-      png_error(png_ptr, msg);
+      png_chunk_error(png_ptr, "unknown critical chunk");
    }
 
    png_push_crc_skip(png_ptr, length);
diff --git a/pngrio.c b/pngrio.c
index 119f582..1f4865a 100644
--- a/pngrio.c
+++ b/pngrio.c
@@ -33,6 +33,7 @@
       png_error(png_ptr, "Call to NULL read function");
 }
 
+#if !defined(PNG_NO_STDIO)
 /* This is the function which does the actual reading of data.  If you are
    not reading from a standard C stream, you should create a replacement
    read_data function and use it at run time with png_set_read_fn(), rather
@@ -103,6 +104,7 @@
    }
 }
 #endif
+#endif
 
 /* This function allows the application to supply a new input function
    for libpng if standard C streams aren't being used.
@@ -123,10 +125,14 @@
 {
    png_ptr->io_ptr = io_ptr;
 
+#if !defined(PNG_NO_STDIO)
    if (read_data_fn != NULL)
       png_ptr->read_data_fn = read_data_fn;
    else
       png_ptr->read_data_fn = png_default_read_data;
+#else
+   png_ptr->read_data_fn = read_data_fn;
+#endif
 
    /* It is an error to write to a read device */
    png_ptr->write_data_fn = NULL;
diff --git a/pngrtran.c b/pngrtran.c
index 28b0415..b72f0af 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -986,11 +986,15 @@
 #if !defined(PNG_USELESS_TESTS_SUPPORTED)
    if (png_ptr->row_buf == NULL)
    {
+#if !defined(PNG_NO_STDIO)
       char msg[50];
 
       sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
          png_ptr->pass);
       png_error(png_ptr, msg);
+#else
+      png_error(png_ptr, "NULL row buffer");
+#endif
    }
 #endif
 
diff --git a/pngrutil.c b/pngrutil.c
index bd225b6..4fe7a4d 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -88,20 +88,16 @@
 
    if (png_crc_error(png_ptr))
    {
-      char msg[80];
-
-      sprintf(msg,"CRC error in %s", png_ptr->chunk_name);
-
       if ((png_ptr->chunk_name[0] & 0x20 &&                /* Ancillary */
            !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
           (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
            png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))
       {
-         png_warning(png_ptr, msg);
+         png_chunk_warning(png_ptr, "CRC error");
       }
       else
       {
-         png_error(png_ptr, msg);
+         png_chunk_error(png_ptr, "CRC error");
       }
       return 1;
    }
@@ -307,10 +303,6 @@
    }
    else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
    {
-      char msg[80];
-
-      sprintf(msg,"CRC error in %s", png_ptr->chunk_name);
-
       /* If we don't want to use the data from an ancillary chunk,
          we have two options: an error abort, or a warning and we
          ignore the data in this chunk (which should be OK, since
@@ -319,11 +311,11 @@
       {
          if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
          {
-            png_error(png_ptr, msg);
+            png_chunk_error(png_ptr, "CRC error");
          }
          else
          {
-            png_warning(png_ptr, msg);
+            png_chunk_warning(png_ptr, "CRC error");
             png_ptr->flags &= ~PNG_FLAG_FREE_PALETTE;
             png_free(png_ptr, palette);
             return;
@@ -332,7 +324,7 @@
       /* Otherwise, we (optionally) emit a warning and use the chunk. */
       else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
       {
-         png_warning(png_ptr, msg);
+         png_chunk_warning(png_ptr, "CRC error");
       }
    }
 
@@ -406,7 +398,7 @@
 
 #if defined(PNG_READ_sRGB_SUPPORTED)
    if ((png_ptr->mode & PNG_HAVE_sRGB))
-      if(igamma != 50000)
+      if(igamma != (png_uint_32)50000L)
       {
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
@@ -416,7 +408,7 @@
 
 #if defined(PNG_READ_sRGB_SUPPORTED)
    if (png_ptr->mode & PNG_HAVE_sRGB)
-      if(igamma != 50000)
+      if(igamma != (png_uint_32)50000L)
       {
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
@@ -585,8 +577,8 @@
    val = png_get_uint_32(buf);
    blue_y = (float)val / (float)100000.0;
 
-   if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
-       blue_x + blue_y > 1.0)
+   if (blue_x < (float)0 || blue_x > (float)0.8 || blue_y < (float)0 ||
+       blue_y > (float)0.8 || blue_x + blue_y > (float)1.0)
    {
       png_warning(png_ptr, "Invalid cHRM blue point");
       png_crc_finish(png_ptr, 0);
@@ -597,12 +589,20 @@
       return;
 
 #if defined(PNG_READ_sRGB_SUPPORTED)
-   if ((png_ptr->mode & PNG_HAVE_sRGB))
-      if(white_x != .3127 || white_y != .329 || red_x != .64 || red_y != .33 ||
-         green_x != .3 || green_y != .6 || blue_x != .15 || blue_y != .06)
+   if (png_ptr->mode & PNG_HAVE_sRGB)
       {
-         png_warning(png_ptr,
-           "Ignoring incorrect cHRM value when sRGB is also present");
+      if (fabs(white_x - (float).3127) > (float).001 ||
+          fabs(white_y - (float).3290) > (float).001 ||
+          fabs(  red_x - (float).6400) > (float).001 ||
+          fabs(  red_y - (float).3300) > (float).001 ||
+          fabs(green_x - (float).3000) > (float).001 ||
+          fabs(green_y - (float).6000) > (float).001 ||
+          fabs( blue_x - (float).1500) > (float).001 ||
+          fabs( blue_y - (float).6000) > (float).001)
+         {
+            png_warning(png_ptr,
+              "Ignoring incorrect cHRM value when sRGB is also present");
+         }
          return;
       }
 #endif /* PNG_READ_sRGB_SUPPORTED */
@@ -664,17 +664,17 @@
       already defined gamma and chrm with values that are
       inconsistent with sRGB -- for now, just ignore them */
 
-   file_gamma = 0.45;
+   file_gamma = (float)45000./(float)100000.;
    png_set_gAMA(png_ptr, info_ptr, file_gamma);
 
-   white_x = 0.3127;
-   white_y = 0.3290;
-   red_x   = 0.6400;
-   red_y   = 0.3300;
-   green_x = 0.3000;
-   green_y = 0.6000;
-   blue_x  = 0.1500;
-   blue_y  = 0.0600;
+   white_x = (float)31270./(float)100000.;
+   white_y = (float)32900./(float)100000.;
+   red_x   = (float)64000./(float)100000.;
+   red_y   = (float)33000./(float)100000.;
+   green_x = (float)30000./(float)100000.;
+   green_y = (float)60000./(float)100000.;
+   blue_x  = (float)15000./(float)100000.;
+   blue_y  = (float) 6000./(float)100000.;
 
    png_set_cHRM(png_ptr, info_ptr,
       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
@@ -1342,10 +1342,14 @@
    else /* if (comp_type >= PNG_TEXT_COMPRESSION_LAST) */
    {
       png_size_t text_size;
+#if !defined(PNG_NO_STDIO)
       char umsg[50];
 
       sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
       png_warning(png_ptr, umsg);
+#else
+      png_warning(png_ptr, "Unknown zTXt compression type");
+#endif
 
       /* Copy what we can of the error message into the text chunk */
       text_size = (png_size_t)length - (text - key) - 1;
@@ -1380,10 +1384,7 @@
 
    if (!(png_ptr->chunk_name[0] & 0x20))
    {
-      char msg[40];
-
-      sprintf(msg, "Unknown critical chunk %s", png_ptr->chunk_name);
-      png_error(png_ptr, msg);
+      png_chunk_error(png_ptr, "unknown critical chunk");
    }
 
    if (png_ptr->mode & PNG_HAVE_IDAT)
@@ -1407,11 +1408,7 @@
    if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
        isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
    {
-      char msg[45];
-
-      sprintf(msg, "Invalid chunk type 0x%02X 0x%02X 0x%02X 0x%02X",
-         chunk_name[0], chunk_name[1], chunk_name[2], chunk_name[3]);
-      png_error(png_ptr, msg);
+      png_chunk_error(png_ptr, "invalid chunk type");
    }
 }
 
diff --git a/pngset.c b/pngset.c
index 2855207..2652b76 100644
--- a/pngset.c
+++ b/pngset.c
@@ -238,19 +238,19 @@
    png_set_sRGB(png_ptr, info_ptr, intent);
 
 #if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_WRITE_gAMA_SUPPORTED)
-   file_gamma = 0.45;
+   file_gamma = (float).45;
    png_set_gAMA(png_ptr, info_ptr, file_gamma);
 #endif
 
 #if defined(PNG_READ_cHRM_SUPPORTED) || defined(PNG_WRITE_cHRM_SUPPORTED)
-   white_x = 0.3127;
-   white_y = 0.3290;
-   red_x   = 0.6400;
-   red_y   = 0.3300;
-   green_x = 0.3000;
-   green_y = 0.6000;
-   blue_x  = 0.1500;
-   blue_y  = 0.0600;
+   white_x = (float).3127;
+   white_y = (float).3290;
+   red_x   = (float).64;
+   red_y   = (float).33;
+   green_x = (float).30;
+   green_y = (float).60;
+   blue_x  = (float).15;
+   blue_y  = (float).06;
 
    png_set_cHRM(png_ptr, info_ptr,
       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
diff --git a/pngtest.c b/pngtest.c
index 1348f2d..cea4c8e 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -44,19 +44,190 @@
 /*  #define STDERR stderr  */
 #define STDERR stdout   /* for DOS */
 
-/* input and output filenames */
-#ifdef RISCOS
-PNG_CONST char *inname = "pngtest_png";
-PNG_CONST char *outname = "pngout_png";
+/* START of code to validate stdio-free compilation */
+/* These copies of the default read/write functions come from pngrio.c and */
+/* pngwio.c.  They allow "don't include stdio" testing of the library. */
+#if defined(PNG_NO_STDIO)
+/* This is the function which does the actual reading of data.  If you are
+   not reading from a standard C stream, you should create a replacement
+   read_data function and use it at run time with png_set_read_fn(), rather
+   than changing the library. */
+#ifndef USE_FAR_KEYWORD
+static void
+png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_size_t check;
+
+   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
+    * instead of an int, which is what fread() actually returns.
+    */
+   check = (png_size_t)fread(data, (png_size_t)1, length,
+      (FILE *)png_ptr->io_ptr);
+
+   if (check != length)
+   {
+      png_error(png_ptr, "Read Error");
+   }
+}
 #else
-PNG_CONST char *inname = "pngtest.png";
-PNG_CONST char *outname = "pngout.png";
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+ 
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+ 
+static void
+png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   int check;
+   png_byte *n_data;
+   FILE *io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   n_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (FILE *)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)n_data == data)
+   {
+      check = fread(n_data, 1, length, io_ptr);
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t read, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         read = MIN(NEAR_BUF_SIZE, remaining);
+         err = fread(buf, (png_size_t)1, read, io_ptr);
+         png_memcpy(data, buf, read); /* copy far buffer to near buffer */
+         if(err != read)
+            break;
+         else
+            check += err;
+         data += read;
+         remaining -= read;
+      }
+      while (remaining != 0);
+   }
+   if (check != length)
+   {
+      png_error(png_ptr, "read Error");
+   }
+}
 #endif
 
-char inbuf[256], outbuf[256];
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+static void
+png_default_flush(png_structp png_ptr)
+{
+   FILE *io_ptr;
+   io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr));
+   if (io_ptr != NULL)
+      fflush(io_ptr);
+}
+#endif
 
-int
-main(int argc, char *argv[])
+/* This is the function which does the actual writing of data.  If you are
+   not writing to a standard C stream, you should create a replacement
+   write_data function and use it at run time with png_set_write_fn(), rather
+   than changing the library. */
+#ifndef USE_FAR_KEYWORD
+static void
+png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+
+   check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
+   if (check != length)
+   {
+      png_error(png_ptr, "Write Error");
+   }
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void
+png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+   png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
+   FILE *io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   near_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (FILE *)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)near_data == data)
+   {
+      check = fwrite(near_data, 1, length, io_ptr);
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t written, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         written = MIN(NEAR_BUF_SIZE, remaining);
+         png_memcpy(buf, data, written); /* copy far buffer to near buffer */
+         err = fwrite(buf, 1, written, io_ptr);
+         if (err != written)
+            break;
+         else
+            check += err;
+         data += written;
+         remaining -= written;
+      }
+      while (remaining != 0);
+   }
+   if (check != length)
+   {
+      png_error(png_ptr, "Write Error");
+   }
+}
+
+#endif
+
+/* This function is called when there is a warning, but the library thinks
+ * it can continue anyway.  Replacement functions don't have to do anything
+ * here if you don't want to.  In the default configuration, png_ptr is
+ * not used, but it is passed in case it may be useful.
+ */
+static void
+png_default_warning(png_structp png_ptr, png_const_charp message)
+{
+   PNG_CONST char *name = "UNKNOWN (ERROR!)";
+   if (png_ptr != NULL && png_ptr->error_ptr != NULL)
+      name = png_ptr->error_ptr;
+   fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
+}
+
+/* This is the default error handling function.  Note that replacements for
+ * this function MUST NOT RETURN, or the program will likely crash.  This
+ * function is used by default, or if the program supplies NULL for the
+ * error function pointer in png_set_error_fn().
+ */
+static void
+png_default_error(png_structp png_ptr, png_const_charp message)
+{
+   png_default_warning(png_ptr, message);
+   /* We can return because png_error calls the default handler which is
+    * actually ok in this case. */
+}
+#endif
+/* END of code to validate stdio-free compilation */
+
+/* Test one file */
+int test(PNG_CONST char *inname, PNG_CONST char *outname)
 {
    FILE *fpin, *fpout;
    png_structp read_ptr, write_ptr;
@@ -69,30 +240,11 @@
 #ifdef USE_FAR_KEYWORD
    jmp_buf jmpbuf;
 #endif   
+   
+   char inbuf[256], outbuf[256];
+
    row_buf = (png_bytep)NULL;
 
-   fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
-
-   if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
-   {
-      fprintf(STDERR,
-         "Warning: versions are different between png.h and png.c\n");
-      fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
-      fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
-   }
-
-   if (argc > 1)
-     inname = argv[1];
-
-   if (argc > 2)
-     outname = argv[2];
-
-   if (argc > 3)
-   {
-     fprintf(stderr, "usage: %s [infile.png] [outfile.png]\n", argv[0]);
-     exit(1);
-   }
-
    if ((fpin = fopen(inname, "rb")) == NULL)
    {
       fprintf(STDERR, "Could not find input file %s\n", inname);
@@ -109,8 +261,14 @@
    png_debug(0, "Allocating read and write structures\n");
    read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
       (png_error_ptr)NULL, (png_error_ptr)NULL);
+#if defined(PNG_NO_STDIO)
+   png_set_error_fn(read_ptr, (png_voidp)inname, png_default_error, png_default_warning);
+#endif
    write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
       (png_error_ptr)NULL, (png_error_ptr)NULL);
+#if defined(PNG_NO_STDIO)
+   png_set_error_fn(write_ptr, (png_voidp)inname, png_default_error, png_default_warning);
+#endif
    png_debug(0, "Allocating read_info, write_info and end_info structures\n");
    read_info_ptr = png_create_info_struct(read_ptr);
    write_info_ptr = png_create_info_struct(read_ptr);
@@ -123,7 +281,7 @@
    if (setjmp(read_ptr->jmpbuf))
 #endif
    {
-      fprintf(STDERR, "libpng read error\n");
+      fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
       png_destroy_write_struct(&write_ptr, &write_info_ptr);
       fclose(fpin);
@@ -139,7 +297,7 @@
    if (setjmp(write_ptr->jmpbuf))
 #endif
    {
-      fprintf(STDERR, "libpng write error\n");
+      fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
       png_destroy_write_struct(&write_ptr, &write_info_ptr);
       fclose(fpin);
@@ -151,8 +309,18 @@
    png_memcpy(write_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
 #endif
    png_debug(0, "Initializing input and output streams\n");
+#if !defined(PNG_NO_STDIO)
    png_init_io(read_ptr, fpin);
    png_init_io(write_ptr, fpout);
+#else
+   png_set_read_fn(read_ptr, (png_voidp)fpin, png_default_read_data);
+   png_set_write_fn(write_ptr, (png_voidp)fpout,  png_default_write_data,
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+      png_default_flush);
+#else
+      NULL);
+#endif
+#endif
 
    png_debug(0, "Reading info struct\n");
    png_read_info(read_ptr, read_info_ptr);
@@ -398,8 +566,70 @@
 
    fclose(fpin);
    fclose(fpout);
-   fprintf(STDERR, "libpng passes test\n");
 
    return 0;
 }
 
+/* input and output filenames */
+#ifdef RISCOS
+PNG_CONST char *inname = "pngtest_png";
+PNG_CONST char *outname = "pngout_png";
+#else
+PNG_CONST char *inname = "pngtest.png";
+PNG_CONST char *outname = "pngout.png";
+#endif
+
+int
+main(int argc, char *argv[])
+{
+   int multiple = 0;
+   int ierror = 0;
+
+   fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
+
+   if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
+   {
+      fprintf(STDERR,
+         "Warning: versions are different between png.h and png.c\n");
+      fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
+      fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
+      ++ierror;
+   }
+
+   if (argc > 1)
+   {
+   if (strcmp(argv[1], "-m") == 0)
+      multiple = 1;
+   else
+      inname = argv[1];
+   }
+
+   if (!multiple && argc == 3)
+     outname = argv[2];
+
+   if (!multiple && argc > 3 || multiple && argc < 2)
+   {
+     fprintf(STDERR, "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
+        argv[0], argv[0]);
+     fprintf(STDERR, "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
+     fprintf(STDERR, "  with -m %s is used as a temporary file\n", outname);
+     exit(1);
+   }
+
+   if (multiple)
+   {
+      int i;
+      for (i=2; i<argc; ++i)
+         ierror += test(argv[i], outname);
+   }
+   else
+   {
+      ierror += test(inname, outname);
+   }
+
+   if (ierror == 0)
+      fprintf(STDERR, "libpng passes test\n");
+   else
+      fprintf(STDERR, "libpng FAILS test\n");
+   return ierror != 0;
+}
diff --git a/pngwio.c b/pngwio.c
index 0fa2a94..497c5ca 100644
--- a/pngwio.c
+++ b/pngwio.c
@@ -33,6 +33,7 @@
       png_error(png_ptr, "Call to NULL write function");
 }
 
+#if !defined(PNG_NO_STDIO)
 /* This is the function which does the actual writing of data.  If you are
    not writing to a standard C stream, you should create a replacement
    write_data function and use it at run time with png_set_write_fn(), rather
@@ -99,6 +100,7 @@
 }
 
 #endif
+#endif
 
 /* This function is called to output any data pending writing (normally
    to disk).  After png_flush is called, there should be no data pending
@@ -111,6 +113,7 @@
       (*(png_ptr->output_flush_fn))(png_ptr);
 }
 
+#if !defined(PNG_NO_STDIO)
 static void
 png_default_flush(png_structp png_ptr)
 {
@@ -120,6 +123,7 @@
       fflush(io_ptr);
 }
 #endif
+#endif
 
 /* This function allows the application to supply new output functions for
    libpng if standard C streams aren't being used.
@@ -149,16 +153,24 @@
 {
    png_ptr->io_ptr = io_ptr;
 
+#if !defined(PNG_NO_STDIO)
    if (write_data_fn != NULL)
       png_ptr->write_data_fn = write_data_fn;
    else
       png_ptr->write_data_fn = png_default_write_data;
+#else
+   png_ptr->write_data_fn = write_data_fn;
+#endif
 
 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
+#if !defined(PNG_NO_STDIO)
    if (output_flush_fn != NULL)
       png_ptr->output_flush_fn = output_flush_fn;
    else
       png_ptr->output_flush_fn = png_default_flush;
+#else
+   png_ptr->output_flush_fn = output_flush_fn;
+#endif
 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
 
    /* It is an error to read while writing a png file */
diff --git a/pngwrite.c b/pngwrite.c
index 584254d..6a7b060 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -24,7 +24,9 @@
 void
 png_write_info(png_structp png_ptr, png_infop info_ptr)
 {
+#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
    int i;
+#endif
 
    png_debug(1, "in png_write_info\n");
    png_write_sig(png_ptr); /* write PNG signature */
@@ -146,7 +148,9 @@
    /* see if user wants us to write information chunks */
    if (info_ptr != NULL)
    {
+#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
       int i; /* local index variable */
+#endif
 #if defined(PNG_WRITE_tIME_SUPPORTED)
       /* check to see if user has supplied a time chunk */
       if (info_ptr->valid & PNG_INFO_tIME &&
@@ -210,9 +214,22 @@
       png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, 29*sizeof(char));
    }
 
+#ifdef USE_FAR_KEYWORD
+   {
+      char near_time_buf[29];
+      sprintf(near_time_buf, "%d %s %d %02d:%02d:%02d +0000",
+               ptime->day % 31, short_months[ptime->month],
+               ptime->year, ptime->hour % 24, ptime->minute % 60,
+               ptime->second % 61);
+      png_memcpy(png_ptr->time_buffer, near_time_buf,
+      29*sizeof(char));
+   }
+#else
    sprintf(png_ptr->time_buffer, "%d %s %d %02d:%02d:%02d +0000",
-               ptime->day % 31, short_months[ptime->month], ptime->year,
-               ptime->hour % 24, ptime->minute % 60, ptime->second % 61);
+               ptime->day % 31, short_months[ptime->month],
+               ptime->year, ptime->hour % 24, ptime->minute % 60,
+               ptime->second % 61);
+#endif
    return png_ptr->time_buffer;
 }
 #endif /* PNG_TIME_RFC1152_SUPPORTED */
@@ -732,7 +749,9 @@
    int num_weights, png_doublep filter_weights,
    png_doublep filter_costs)
 {
+#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
    int i;
+#endif
 
    png_debug(1, "in png_set_filter_heuristics\n");
    if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
diff --git a/pngwutil.c b/pngwutil.c
index bad95a9..b4575e4 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -593,10 +593,7 @@
 
    if (key == NULL || (key_len = png_strlen(key)) == 0)
    {
-      char msg[40];
-
-      sprintf(msg, "Zero length %s keyword", png_ptr->chunk_name);
-      png_warning(png_ptr, msg);
+      png_chunk_warning(png_ptr, "zero length keyword");
       return 0;
    }
 
@@ -607,13 +604,16 @@
    /* Replace non-printing characters with a blank and print a warning */
    for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
    {
-      if (*kp < 0x20 || (*kp > 0x7E && *kp < 0xA1))
+      if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1))
       {
+#if !defined(PNG_NO_STDIO)
          char msg[40];
 
-         sprintf(msg, "Invalid %s keyword character 0x%02X",
-            png_ptr->chunk_name, *kp);
-         png_warning(png_ptr, msg);
+         sprintf(msg, "invalid keyword character 0x%02X", *kp);
+         png_chunk_warning(png_ptr, msg);
+#else
+         png_chunk_warning(png_ptr, "invalid character in keyword");
+#endif
          *dp = ' ';
       }
       else
@@ -627,11 +627,7 @@
    kp = *new_key + key_len - 1;
    if (*kp == ' ')
    {
-      char msg[50];
-      sprintf(msg, "Trailing spaces removed from %s keyword",
-         png_ptr->chunk_name);
-
-      png_warning(png_ptr, msg);
+      png_chunk_warning(png_ptr, "trailing spaces removed from keyword");
 
       while (*kp == ' ')
       {
@@ -644,11 +640,7 @@
    kp = *new_key;
    if (*kp == ' ')
    {
-      char msg[50];
-      sprintf(msg, "Leading spaces removed from %s keyword",
-         png_ptr->chunk_name);
-
-      png_warning(png_ptr, msg);
+      png_chunk_warning(png_ptr, "leading spaces removed from keyword");
 
       while (*kp == ' ')
       {
@@ -681,19 +673,12 @@
 
    if (key_len == 0)
    {
-      char msg[40];
-
-      sprintf(msg, "Zero length %s keyword", png_ptr->chunk_name);
-      png_warning(png_ptr, msg);
+      png_chunk_warning(png_ptr, "zero length keyword");
    }
 
    if (key_len > 79)
    {
-      char msg[50];
-
-      sprintf(msg, "%s keyword length must be 1 - 79 characters",
-         png_ptr->chunk_name);
-      png_warning(png_ptr, msg);
+      png_chunk_warning(png_ptr, "keyword length must be 1 - 79 characters");
       new_key[79] = '\0';
       key_len = 79;
    }
@@ -714,10 +699,7 @@
    png_debug(1, "in png_write_tEXt\n");
    if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
    {
-      char msg[40];
-
-      sprintf(msg, "Empty keyword in %s chunk", "tEXt");
-      png_warning(png_ptr, msg);
+      png_warning(png_ptr, "Empty keyword in tEXt chunk");
       return;
    }
 
@@ -753,10 +735,7 @@
 
    if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
    {
-      char msg[40];
-
-      sprintf(msg, "Empty keyword in %s chunk", "zTXt");
-      png_warning(png_ptr, msg);
+      png_warning(png_ptr, "Empty keyword in zTXt chunk");
       return;
    }
 
@@ -771,9 +750,13 @@
 
    if (compression >= PNG_TEXT_COMPRESSION_LAST)
    {
+#if !defined(PNG_NO_STDIO)
       char msg[50];
       sprintf(msg, "Unknown zTXt compression type %d", compression);
       png_warning(png_ptr, msg);
+#else
+      png_warning(png_ptr, "Unknown zTXt compression type");
+#endif
       compression = PNG_TEXT_COMPRESSION_zTXt;
    }
 
@@ -1389,10 +1372,10 @@
  * been specified by the application, and then writes the row out with the
  * chosen filter.
  */
-#define PNG_MAXSUM (~0x0UL >> 1)
+#define PNG_MAXSUM (png_uint_32)(~0x0UL >> 1)
 #define PNG_HISHIFT 10
-#define PNG_LOMASK 0xffffL
-#define PNG_HIMASK (~PNG_LOMASK >> PNG_HISHIFT)
+#define PNG_LOMASK (png_uint_32)0xffffL
+#define PNG_HIMASK (png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)
 void
 png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 {