Fix bug in copy-directory copying into an existing directory.
[bpt/emacs.git] / src / image.c
index 1312d13..cc8589f 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions for image support on window system.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -27,6 +27,16 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <unistd.h>
 #endif
 
+#ifdef HAVE_PNG
+#if defined HAVE_LIBPNG_PNG_H
+# include <libpng/png.h>
+#else
+# include <png.h>
+#endif
+#endif
+
+#include <setjmp.h>
+
 /* This makes the fields of a Display accessible, in Xlib header files.  */
 
 #define XLIB_ILLEGAL_ACCESS
@@ -79,6 +89,16 @@ typedef struct w32_bitmap_record Bitmap_Record;
 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
 #define x_defined_color w32_defined_color
 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
+
+/* Functions from w32term.c that depend on XColor (so can't go in w32term.h
+   without modifying lots of files).  */
+extern void x_query_colors (struct frame *f, XColor *colors, int ncolors);
+extern void x_query_color (struct frame *f, XColor *color);
+
+/* Version of libpng that we were compiled with, or -1 if no PNG
+   support was compiled in.  This is tested by w32-win.el to correctly
+   set up the alist used to search for PNG libraries.  */
+Lisp_Object Qlibpng_version;
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
@@ -135,248 +155,6 @@ static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
    the bitmaps yourself.  That is, creating a bitmap from the same
    data more than once will not be caught.  */
 
-#ifdef MAC_OS
-
-static XImagePtr
-XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
-     Display *display;         /* not used */
-     Pixmap pixmap;
-     int x, y;                 /* not used */
-     unsigned int width, height; /* not used */
-     unsigned long plane_mask;         /* not used */
-     int format;               /* not used */
-{
-#if !USE_MAC_IMAGE_IO
-#if GLYPH_DEBUG
-  xassert (x == 0 && y == 0);
-  {
-    Rect ri, rp;
-    SetRect (&ri, 0, 0, width, height);
-    xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
-  }
-  xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
-#endif
-
-  LockPixels (GetGWorldPixMap (pixmap));
-#endif
-
-  return pixmap;
-}
-
-static void
-XPutPixel (ximage, x, y, pixel)
-     XImagePtr ximage;
-     int x, y;
-     unsigned long pixel;
-{
-#if USE_MAC_IMAGE_IO
-  if (ximage->bits_per_pixel == 32)
-    ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
-  else
-    ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
-#else
-  PixMapHandle pixmap = GetGWorldPixMap (ximage);
-  short depth = GetPixDepth (pixmap);
-
-#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
-  if (depth == 32)
-    {
-      char *base_addr = GetPixBaseAddr (pixmap);
-      short row_bytes = GetPixRowBytes (pixmap);
-
-      ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
-    }
-  else
-#endif
-  if (depth == 1)
-    {
-      char *base_addr = GetPixBaseAddr (pixmap);
-      short row_bytes = GetPixRowBytes (pixmap);
-
-      if (pixel == PIX_MASK_DRAW)
-       base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7);
-      else
-       base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7));
-    }
-  else
-    {
-      CGrafPtr old_port;
-      GDHandle old_gdh;
-      RGBColor color;
-
-      GetGWorld (&old_port, &old_gdh);
-      SetGWorld (ximage, NULL);
-
-      color.red = RED16_FROM_ULONG (pixel);
-      color.green = GREEN16_FROM_ULONG (pixel);
-      color.blue = BLUE16_FROM_ULONG (pixel);
-
-      SetCPixel (x, y, &color);
-
-      SetGWorld (old_port, old_gdh);
-    }
-#endif
-}
-
-static unsigned long
-XGetPixel (ximage, x, y)
-     XImagePtr ximage;
-     int x, y;
-{
-#if USE_MAC_IMAGE_IO
-  if (ximage->bits_per_pixel == 32)
-    return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x];
-  else
-    return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x];
-#else
-  PixMapHandle pixmap = GetGWorldPixMap (ximage);
-  short depth = GetPixDepth (pixmap);
-
-#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
-  if (depth == 32)
-    {
-      char *base_addr = GetPixBaseAddr (pixmap);
-      short row_bytes = GetPixRowBytes (pixmap);
-
-      return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
-    }
-  else
-#endif
-  if (depth == 1)
-    {
-      char *base_addr = GetPixBaseAddr (pixmap);
-      short row_bytes = GetPixRowBytes (pixmap);
-
-      if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7)))
-       return PIX_MASK_DRAW;
-      else
-       return PIX_MASK_RETAIN;
-    }
-  else
-    {
-      CGrafPtr old_port;
-      GDHandle old_gdh;
-      RGBColor color;
-
-      GetGWorld (&old_port, &old_gdh);
-      SetGWorld (ximage, NULL);
-
-      GetCPixel (x, y, &color);
-
-      SetGWorld (old_port, old_gdh);
-      return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
-    }
-#endif
-}
-
-static void
-XDestroyImage (ximg)
-     XImagePtr ximg;
-{
-#if !USE_MAC_IMAGE_IO
-  UnlockPixels (GetGWorldPixMap (ximg));
-#endif
-}
-
-#if USE_CG_DRAWING
-#if USE_MAC_IMAGE_IO
-void
-mac_data_provider_release_data (info, data, size)
-     void *info;
-     const void *data;
-     size_t size;
-{
-  xfree ((void *)data);
-}
-#endif
-
-static CGImageRef
-mac_create_cg_image_from_image (f, img)
-     struct frame *f;
-     struct image *img;
-{
-#if USE_MAC_IMAGE_IO
-  XImagePtr ximg = img->pixmap;
-  CGDataProviderRef provider;
-  CGImageRef result;
-
-  if (img->mask)
-    {
-      int x, y;
-      unsigned long color, alpha;
-
-      for (y = 0; y < ximg->height; y++)
-       for (x = 0; x < ximg->width; x++)
-         {
-           color = XGetPixel (ximg, x, y);
-           alpha = XGetPixel (img->mask, x, y);
-           XPutPixel (ximg, x, y,
-                      ARGB_TO_ULONG (alpha,
-                                     RED_FROM_ULONG (color)
-                                     * alpha / PIX_MASK_DRAW,
-                                     GREEN_FROM_ULONG (color)
-                                     * alpha / PIX_MASK_DRAW,
-                                     BLUE_FROM_ULONG (color)
-                                     * alpha / PIX_MASK_DRAW));
-         }
-      xfree (img->mask->data);
-      img->mask->data = NULL;
-    }
-  BLOCK_INPUT;
-  provider = CGDataProviderCreateWithData (NULL, ximg->data,
-                                          ximg->bytes_per_line * ximg->height,
-                                          mac_data_provider_release_data);
-  ximg->data = NULL;
-  result = CGImageCreate (ximg->width, ximg->height, 8, 32,
-                         ximg->bytes_per_line, mac_cg_color_space_rgb,
-                         ((img->mask ? kCGImageAlphaPremultipliedFirst
-                           : kCGImageAlphaNoneSkipFirst)
-                          | kCGBitmapByteOrder32Host),
-                         provider, NULL, 0, kCGRenderingIntentDefault);
-  CGDataProviderRelease (provider);
-  UNBLOCK_INPUT;
-
-  return result;
-#else
-  Pixmap mask;
-  CGImageRef result = NULL;
-
-  BLOCK_INPUT;
-  if (img->mask)
-    mask = img->mask;
-  else
-    {
-      mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                           img->width, img->height, 1);
-      if (mask)
-       {
-         CGrafPtr old_port;
-         GDHandle old_gdh;
-         Rect r;
-
-         GetGWorld (&old_port, &old_gdh);
-         SetGWorld (mask, NULL);
-         BackColor (blackColor); /* Don't mask.  */
-         SetRect (&r, 0, 0, img->width, img->height);
-         EraseRect (&r);
-         SetGWorld (old_port, old_gdh);
-       }
-    }
-  if (mask)
-    {
-      CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
-                               GetGWorldPixMap (mask), &result);
-      if (mask != img->mask)
-       XFreePixmap (FRAME_X_DISPLAY (f), mask);
-    }
-  UNBLOCK_INPUT;
-
-  return result;
-#endif
-}
-#endif /* USE_CG_DRAWING */
-#endif /* MAC_OS */
-
 #ifdef HAVE_NS
 XImagePtr
 XGetImage (Display *display, Pixmap pixmap, int x, int y,
@@ -1622,10 +1400,7 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
     {
       Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
       img->pixmap = NO_PIXMAP;
-#ifdef HAVE_NS
-      if (img->background_valid)
-        ns_free_indexed_color(img->background);
-#endif
+      /* NOTE (HAVE_NS): background color is NOT an indexed color! */
       img->background_valid = 0;
     }
 
@@ -1770,7 +1545,12 @@ uncache_image (f, spec)
 {
   struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
   if (img)
-    free_image (f, img);
+    {
+      free_image (f, img);
+      /* As display glyphs may still be referring to the image ID, we
+        must garbage the frame (Bug#6426).  */
+      SET_FRAME_GARBAGED (f);
+    }
 }
 
 
@@ -2541,7 +2321,7 @@ static int xbm_load_image P_ ((struct frame *f, struct image *img,
 static int xbm_image_p P_ ((Lisp_Object object));
 static int xbm_read_bitmap_data P_ ((struct frame *f,
                                     unsigned char *, unsigned char *,
-                                    int *, int *, unsigned char **));
+                                    int *, int *, unsigned char **, int));
 static int xbm_file_p P_ ((Lisp_Object));
 
 
@@ -2568,7 +2348,7 @@ enum xbm_keyword_index
 /* Vector of image_keyword structures describing the format
    of valid XBM image specifications.  */
 
-static struct image_keyword xbm_format[XBM_LAST] =
+static const struct image_keyword xbm_format[XBM_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
@@ -2932,14 +2712,17 @@ Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
    buffer's end.  Set *WIDTH and *HEIGHT to the width and height of
    the image.  Return in *DATA the bitmap data allocated with xmalloc.
    Value is non-zero if successful.  DATA null means just test if
-   CONTENTS looks like an in-memory XBM file.  */
+   CONTENTS looks like an in-memory XBM file.  If INHIBIT_IMAGE_ERROR
+   is non-zero, inhibit the call to image_error when the image size is
+   invalid (the bitmap remains unread).  */
 
 static int
-xbm_read_bitmap_data (f, contents, end, width, height, data)
+xbm_read_bitmap_data (f, contents, end, width, height, data, inhibit_image_error)
      struct frame *f;
      unsigned char *contents, *end;
      int *width, *height;
      unsigned char **data;
+     int inhibit_image_error;
 {
   unsigned char *s = contents;
   char buffer[BUFSIZ];
@@ -2990,7 +2773,11 @@ xbm_read_bitmap_data (f, contents, end, width, height, data)
     }
 
   if (!check_image_size (f, *width, *height))
-    goto failure;
+    {
+      if (!inhibit_image_error)
+       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      goto failure;
+    }
   else if (data == NULL)
     goto success;
 
@@ -3093,7 +2880,8 @@ xbm_load_image (f, img, contents, end)
   unsigned char *data;
   int success_p = 0;
 
-  rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
+  rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
+                            &data, 0);
   if (rc)
     {
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
@@ -3148,9 +2936,8 @@ xbm_file_p (data)
   int w, h;
   return (STRINGP (data)
          && xbm_read_bitmap_data (NULL, SDATA (data),
-                                  (SDATA (data)
-                                   + SBYTES (data)),
-                                  &w, &h, NULL));
+                                  (SDATA (data) + SBYTES (data)),
+                                  &w, &h, NULL, 1));
 }
 
 
@@ -3274,7 +3061,7 @@ xbm_load (f, img)
             int nbytes, i;
             /* Windows mono bitmaps are reversed compared with X.  */
             invertedBits = bits;
-            nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR 
+            nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
               * img->height;
             bits = (char *) alloca(nbytes);
             for (i = 0; i < nbytes; i++)
@@ -3361,7 +3148,7 @@ enum xpm_keyword_index
 /* Vector of image_keyword structures describing the format
    of valid XPM image specifications.  */
 
-static struct image_keyword xpm_format[XPM_LAST] =
+static const struct image_keyword xpm_format[XPM_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
@@ -4200,7 +3987,7 @@ xpm_load_image (f, img, contents, end)
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size", Qnil, Qnil);
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       goto failure;
     }
 
@@ -4786,9 +4573,9 @@ x_to_xcolors (f, img, rgb_p)
     {
       XColor *row = p;
 
-#ifdef HAVE_X_WINDOWS
+#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
       for (x = 0; x < img->width; ++x, ++p)
-       p->pixel = XGetPixel (ximg, x, y);
+       p->pixel = GET_PIXEL (ximg, x, y);
       if (rgb_p)
        x_query_colors (f, row, img->width);
 
@@ -4800,16 +4587,9 @@ x_to_xcolors (f, img, rgb_p)
          p->pixel = GET_PIXEL (ximg, x, y);
          if (rgb_p)
            {
-#if defined (HAVE_NS)
              p->red = RED16_FROM_ULONG (p->pixel);
              p->green = GREEN16_FROM_ULONG (p->pixel);
              p->blue = BLUE16_FROM_ULONG (p->pixel);
-#endif  /* HAVE_NS */
-#ifdef HAVE_NTGUI
-             p->red = 256 * GetRValue (p->pixel);
-             p->green = 256 * GetGValue (p->pixel);
-             p->blue = 256 * GetBValue (p->pixel);
-#endif /* HAVE_NTGUI */
            }
        }
 #endif /* HAVE_X_WINDOWS */
@@ -5095,7 +4875,7 @@ x_disable_image (f, img)
       Display *dpy = FRAME_X_DISPLAY (f);
       GC gc;
 
-#ifndef HAVE_NS  //TODO: NS support, however this not needed for toolbars
+#ifndef HAVE_NS  /* TODO: NS support, however this not needed for toolbars */
 
 #define MaskForeground(f)  WHITE_PIX_DEFAULT (f)
 
@@ -5317,7 +5097,7 @@ enum pbm_keyword_index
 /* Vector of image_keyword structures describing the format
    of valid user-defined image specifications.  */
 
-static struct image_keyword pbm_format[PBM_LAST] =
+static const struct image_keyword pbm_format[PBM_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
@@ -5548,7 +5328,7 @@ pbm_load (f, img)
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size", Qnil, Qnil);
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       goto error;
     }
 
@@ -5739,7 +5519,7 @@ enum png_keyword_index
 /* Vector of image_keyword structures describing the format
    of valid user-defined image specifications.  */
 
-static struct image_keyword png_format[PNG_LAST] =
+static const struct image_keyword png_format[PNG_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
@@ -5785,17 +5565,11 @@ png_image_p (object)
 
 #ifdef HAVE_PNG
 
-#if defined HAVE_LIBPNG_PNG_H
-# include <libpng/png.h>
-#else
-# include <png.h>
-#endif
-
 #ifdef HAVE_NTGUI
 /* PNG library details.  */
 
 DEF_IMGLIB_FN (png_get_io_ptr);
-DEF_IMGLIB_FN (png_check_sig);
+DEF_IMGLIB_FN (png_sig_cmp);
 DEF_IMGLIB_FN (png_create_read_struct);
 DEF_IMGLIB_FN (png_create_info_struct);
 DEF_IMGLIB_FN (png_destroy_read_struct);
@@ -5816,6 +5590,11 @@ DEF_IMGLIB_FN (png_read_image);
 DEF_IMGLIB_FN (png_read_end);
 DEF_IMGLIB_FN (png_error);
 
+#if (PNG_LIBPNG_VER >= 10500)
+DEF_IMGLIB_FN (png_longjmp);
+DEF_IMGLIB_FN (png_set_longjmp_fn);
+#endif /* libpng version >= 1.5 */
+
 static int
 init_png_functions (Lisp_Object libraries)
 {
@@ -5826,7 +5605,7 @@ init_png_functions (Lisp_Object libraries)
     return 0;
 
   LOAD_IMGLIB_FN (library, png_get_io_ptr);
-  LOAD_IMGLIB_FN (library, png_check_sig);
+  LOAD_IMGLIB_FN (library, png_sig_cmp);
   LOAD_IMGLIB_FN (library, png_create_read_struct);
   LOAD_IMGLIB_FN (library, png_create_info_struct);
   LOAD_IMGLIB_FN (library, png_destroy_read_struct);
@@ -5846,12 +5625,18 @@ init_png_functions (Lisp_Object libraries)
   LOAD_IMGLIB_FN (library, png_read_image);
   LOAD_IMGLIB_FN (library, png_read_end);
   LOAD_IMGLIB_FN (library, png_error);
+
+#if (PNG_LIBPNG_VER >= 10500)
+  LOAD_IMGLIB_FN (library, png_longjmp);
+  LOAD_IMGLIB_FN (library, png_set_longjmp_fn);
+#endif /* libpng version >= 1.5 */
+
   return 1;
 }
 #else
 
 #define fn_png_get_io_ptr              png_get_io_ptr
-#define fn_png_check_sig               png_check_sig
+#define fn_png_sig_cmp                 png_sig_cmp
 #define fn_png_create_read_struct      png_create_read_struct
 #define fn_png_create_info_struct      png_create_info_struct
 #define fn_png_destroy_read_struct     png_destroy_read_struct
@@ -5872,8 +5657,27 @@ init_png_functions (Lisp_Object libraries)
 #define fn_png_read_end                        png_read_end
 #define fn_png_error                   png_error
 
+#if (PNG_LIBPNG_VER >= 10500)
+#define fn_png_longjmp                 png_longjmp
+#define fn_png_set_longjmp_fn          png_set_longjmp_fn
+#endif /* libpng version >= 1.5 */
+
 #endif /* HAVE_NTGUI */
 
+
+#if (PNG_LIBPNG_VER < 10500)
+#define PNG_LONGJMP(ptr) (longjmp (ptr->jmpbuf, 1))
+#define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
+#else
+/* In libpng version 1.5, the jmpbuf member is hidden.
+   We need the extra cast for PNG_JMPBUF because, for Windows,
+   DEF_IMGLIB_FN defines the return value of fn_png_set_longjmp_fn to
+   be int (Bug#7908).  */
+#define PNG_LONGJMP(ptr) (fn_png_longjmp (png_ptr, 1))
+#define PNG_JMPBUF(ptr) \
+  (*(jmp_buf *)(fn_png_set_longjmp_fn((ptr), longjmp, sizeof (jmp_buf))))
+#endif
+
 /* Error and warning handlers installed when the PNG library
    is initialized.  */
 
@@ -5883,8 +5687,10 @@ my_png_error (png_ptr, msg)
      char *msg;
 {
   xassert (png_ptr != NULL);
+  /* Avoid compiler warning about deprecated direct access to
+     png_ptr's fields in libpng versions 1.4.x.  */
   image_error ("PNG error: %s", build_string (msg), Qnil);
-  longjmp (png_ptr->jmpbuf, 1);
+  PNG_LONGJMP (png_ptr);
 }
 
 
@@ -5998,7 +5804,7 @@ png_load (f, img)
 
       /* Check PNG signature.  */
       if (fread (sig, 1, sizeof sig, fp) != sizeof sig
-         || !fn_png_check_sig (sig, sizeof sig))
+         || fn_png_sig_cmp (sig, 0, sizeof sig))
        {
          image_error ("Not a PNG file: `%s'", file, Qnil);
          UNGCPRO;
@@ -6015,7 +5821,7 @@ png_load (f, img)
 
       /* Check PNG signature.  */
       if (tbr.len < sizeof sig
-         || !fn_png_check_sig (tbr.bytes, sizeof sig))
+         || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
        {
          image_error ("Not a PNG image: `%s'", img->spec, Qnil);
          UNGCPRO;
@@ -6060,7 +5866,7 @@ png_load (f, img)
 
   /* Set error jump-back.  We come back here when the PNG library
      detects an error.  */
-  if (setjmp (png_ptr->jmpbuf))
+  if (setjmp (PNG_JMPBUF (png_ptr)))
     {
     error:
       if (png_ptr)
@@ -6084,8 +5890,10 @@ png_load (f, img)
                   &interlace_type, NULL, NULL);
 
   if (!check_image_size (f, width, height))
-    goto error;
-
+    {
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      goto error;
+    }
   /* If image contains simply transparency data, we prefer to
      construct a clipping mask.  */
   if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
@@ -6123,7 +5931,6 @@ png_load (f, img)
       if (STRINGP (specified_bg))
        /* The user specified `:background', use that.  */
        {
-         /* W32 version incorrectly used COLORREF here!!  ++kfs */
          XColor color;
          if (x_defined_color (f, SDATA (specified_bg), &color, 0))
            {
@@ -6142,7 +5949,7 @@ png_load (f, img)
        {
          /* We use the current frame background, ignoring any default
             background color set by the image.  */
-#ifdef HAVE_X_WINDOWS
+#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
          XColor color;
          png_color_16 frame_background;
 
@@ -6155,19 +5962,6 @@ png_load (f, img)
          frame_background.blue = color.blue >> shift;
 #endif /* HAVE_X_WINDOWS */
 
-#ifdef HAVE_NTGUI
-         COLORREF color;
-         png_color_16 frame_background;
-         color = FRAME_BACKGROUND_PIXEL (f);
-#if 0 /* W32 TODO : Colormap support.  */
-         x_query_color (f, &color);
-#endif
-         bzero (&frame_background, sizeof frame_background);
-         frame_background.red = GetRValue (color);
-         frame_background.green = GetGValue (color);
-         frame_background.blue = GetBValue (color);
-#endif /* HAVE_NTGUI */
-
          fn_png_set_background (png_ptr, &frame_background,
                                 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
        }
@@ -6359,7 +6153,7 @@ enum jpeg_keyword_index
 /* Vector of image_keyword structures describing the format
    of valid user-defined image specifications.  */
 
-static struct image_keyword jpeg_format[JPEG_LAST] =
+static const struct image_keyword jpeg_format[JPEG_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
@@ -6420,7 +6214,6 @@ jpeg_image_p (object)
 
 #include <jpeglib.h>
 #include <jerror.h>
-#include <setjmp.h>
 
 #ifdef HAVE_STLIB_H_1
 #define HAVE_STDLIB_H 1
@@ -6806,7 +6599,7 @@ jpeg_load (f, img)
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size", Qnil, Qnil);
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       longjmp (mgr.setjmp_buffer, 2);
     }
 
@@ -6926,13 +6719,14 @@ enum tiff_keyword_index
   TIFF_HEURISTIC_MASK,
   TIFF_MASK,
   TIFF_BACKGROUND,
+  TIFF_INDEX,
   TIFF_LAST
 };
 
 /* Vector of image_keyword structures describing the format
    of valid user-defined image specifications.  */
 
-static struct image_keyword tiff_format[TIFF_LAST] =
+static const struct image_keyword tiff_format[TIFF_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
@@ -6943,7 +6737,8 @@ static struct image_keyword tiff_format[TIFF_LAST] =
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0},
+  {":index",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0}
 };
 
 /* Structure describing the image type `tiff'.  */
@@ -6989,6 +6784,7 @@ DEF_IMGLIB_FN (TIFFClientOpen);
 DEF_IMGLIB_FN (TIFFGetField);
 DEF_IMGLIB_FN (TIFFReadRGBAImage);
 DEF_IMGLIB_FN (TIFFClose);
+DEF_IMGLIB_FN (TIFFSetDirectory);
 
 static int
 init_tiff_functions (Lisp_Object libraries)
@@ -7005,6 +6801,7 @@ init_tiff_functions (Lisp_Object libraries)
   LOAD_IMGLIB_FN (library, TIFFGetField);
   LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
   LOAD_IMGLIB_FN (library, TIFFClose);
+  LOAD_IMGLIB_FN (library, TIFFSetDirectory);
   return 1;
 }
 
@@ -7017,7 +6814,7 @@ init_tiff_functions (Lisp_Object libraries)
 #define fn_TIFFGetField                        TIFFGetField
 #define fn_TIFFReadRGBAImage           TIFFReadRGBAImage
 #define fn_TIFFClose                   TIFFClose
-
+#define fn_TIFFSetDirectory            TIFFSetDirectory
 #endif /* HAVE_NTGUI */
 
 
@@ -7170,12 +6967,13 @@ tiff_load (f, img)
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
   TIFF *tiff;
-  int width, height, x, y;
+  int width, height, x, y, count;
   uint32 *buf;
-  int rc;
+  int rc, rc2;
   XImagePtr ximg;
   struct gcpro gcpro1;
   tiff_memory_source memsrc;
+  Lisp_Object image;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
@@ -7231,6 +7029,20 @@ tiff_load (f, img)
        }
     }
 
+  image = image_spec_value (img->spec, QCindex, NULL);
+  if (INTEGERP (image))
+    {
+      int ino = XFASTINT (image);
+      if (!fn_TIFFSetDirectory (tiff, ino))
+       {
+         image_error ("Invalid image number `%s' in image `%s'",
+                      image, img->spec);
+         fn_TIFFClose (tiff);
+         UNGCPRO;
+         return 0;
+       }
+    }
+
   /* Get width and height of the image, and allocate a raster buffer
      of width x height 32-bit values.  */
   fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
@@ -7238,7 +7050,8 @@ tiff_load (f, img)
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size", Qnil, Qnil);
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      fn_TIFFClose (tiff);
       UNGCPRO;
       return 0;
     }
@@ -7246,6 +7059,16 @@ tiff_load (f, img)
   buf = (uint32 *) xmalloc (width * height * sizeof *buf);
 
   rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
+
+  /* Count the number of images in the file.  */
+  for (count = 1, rc2 = 1; rc2; count++)
+    rc2 = fn_TIFFSetDirectory (tiff, count);
+
+  if (count > 1)
+    img->data.lisp_val = Fcons (Qcount,
+                               Fcons (make_number (count),
+                                      img->data.lisp_val));
+
   fn_TIFFClose (tiff);
   if (!rc)
     {
@@ -7355,7 +7178,7 @@ enum gif_keyword_index
 /* Vector of image_keyword structures describing the format
    of valid user-defined image specifications.  */
 
-static struct image_keyword gif_format[GIF_LAST] =
+static const struct image_keyword gif_format[GIF_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
@@ -7366,7 +7189,7 @@ static struct image_keyword gif_format[GIF_LAST] =
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":image",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":index",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
@@ -7499,8 +7322,8 @@ gif_read_from_memory (file, buf, len)
 /* Load GIF image IMG for use on frame F.  Value is non-zero if
    successful.  */
 
-static int interlace_start[] = {0, 4, 2, 1};
-static int interlace_increment[] = {8, 8, 4, 2};
+static const int interlace_start[] = {0, 4, 2, 1};
+static const int interlace_increment[] = {8, 8, 4, 2};
 
 static int
 gif_load (f, img)
@@ -7566,7 +7389,7 @@ gif_load (f, img)
   /* Before reading entire contents, check the declared image size. */
   if (!check_image_size (f, gif->SWidth, gif->SHeight))
     {
-      image_error ("Invalid image size", Qnil, Qnil);
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       fn_DGifCloseFile (gif);
       UNGCPRO;
       return 0;
@@ -7609,7 +7432,7 @@ gif_load (f, img)
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size", Qnil, Qnil);
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       fn_DGifCloseFile (gif);
       UNGCPRO;
       return 0;
@@ -7794,7 +7617,7 @@ enum svg_keyword_index
 /* Vector of image_keyword structures describing the format
    of valid user-defined image specifications.  */
 
-static struct image_keyword svg_format[SVG_LAST] =
+static const struct image_keyword svg_format[SVG_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
@@ -7871,14 +7694,15 @@ DEF_IMGLIB_FN (g_type_init);
 DEF_IMGLIB_FN (g_object_unref);
 DEF_IMGLIB_FN (g_error_free);
 
-Lisp_Object Qgdk_pixbuf, Qglib;
+Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
 
 static int
 init_svg_functions (Lisp_Object libraries)
 {
-  HMODULE library, gdklib, glib;
+  HMODULE library, gdklib, glib, gobject;
 
   if (!(glib = w32_delayed_load (libraries, Qglib))
+      || !(gobject = w32_delayed_load (libraries, Qgobject))
       || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
       || !(library = w32_delayed_load (libraries, Qsvg)))
     return 0;
@@ -7899,9 +7723,10 @@ init_svg_functions (Lisp_Object libraries)
   LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
   LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
 
-  LOAD_IMGLIB_FN (glib, g_type_init);
-  LOAD_IMGLIB_FN (glib, g_object_unref);
+  LOAD_IMGLIB_FN (gobject, g_type_init);
+  LOAD_IMGLIB_FN (gobject, g_object_unref);
   LOAD_IMGLIB_FN (glib, g_error_free);
+
   return 1;
 }
 
@@ -8021,7 +7846,7 @@ svg_load_image (f, img, contents, size)
      gnome type library functions.  */
   fn_g_type_init ();
   /* Make a handle to a new rsvg object.  */
-  rsvg_handle = fn_rsvg_handle_new ();
+  rsvg_handle = (RsvgHandle *) fn_rsvg_handle_new ();
 
   /* Parse the contents argument and fill in the rsvg_handle.  */
   fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
@@ -8034,18 +7859,21 @@ svg_load_image (f, img, contents, size)
 
   fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
   if (! check_image_size (f, dimension_data.width, dimension_data.height))
-    goto rsvg_error;
+    {
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      goto rsvg_error;
+    }
 
   /* We can now get a valid pixel buffer from the svg file, if all
      went ok.  */
-  pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
+  pixbuf = (GdkPixbuf *) fn_rsvg_handle_get_pixbuf (rsvg_handle);
   if (!pixbuf) goto rsvg_error;
   fn_g_object_unref (rsvg_handle);
 
   /* Extract some meta data from the svg handle.  */
   width     = fn_gdk_pixbuf_get_width (pixbuf);
   height    = fn_gdk_pixbuf_get_height (pixbuf);
-  pixels    = fn_gdk_pixbuf_get_pixels (pixbuf);
+  pixels    = (const guint8 *) fn_gdk_pixbuf_get_pixels (pixbuf);
   rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
 
   /* Validate the svg meta data.  */
@@ -8066,42 +7894,24 @@ svg_load_image (f, img, contents, size)
   /* Handle alpha channel by combining the image with a background
      color.  */
   specified_bg = image_spec_value (img->spec, QCbackground, NULL);
-  if (STRINGP (specified_bg)
-      && x_defined_color (f, SDATA (specified_bg), &background, 0))
-    {
-      background.red   >>= 8;
-      background.green >>= 8;
-      background.blue  >>= 8;
-    }
-  else
+  if (!STRINGP (specified_bg)
+      || !x_defined_color (f, SDATA (specified_bg), &background, 0))
     {
-#ifdef HAVE_X_WINDOWS
-      background.pixel = FRAME_BACKGROUND_PIXEL (f);
-      x_query_color (f, &background);
-
-      /* SVG pixmaps specify transparency in the last byte, so right
-        shift 8 bits to get rid of it, since emacs doesn't support
-        transparency.  */
-      background.red   >>= 8;
-      background.green >>= 8;
-      background.blue  >>= 8;
-#elif defined (HAVE_NTGUI)
+#ifndef HAVE_NS
       background.pixel = FRAME_BACKGROUND_PIXEL (f);
-#if 0 /* W32 TODO : Colormap support.  */
       x_query_color (f, &background);
-#endif
-
-      /* SVG pixmaps specify transparency in the last byte, so right
-        shift 8 bits to get rid of it, since emacs doesn't support
-        transparency.  */
-      background.red   >>= 8;
-      background.green >>= 8;
-      background.blue  >>= 8;
-#else /* not HAVE_X_WINDOWS*/
-#error FIXME
+#else
+      ns_query_color(FRAME_BACKGROUND_COLOR (f), &background, 1);
 #endif
     }
 
+  /* SVG pixmaps specify transparency in the last byte, so right
+     shift 8 bits to get rid of it, since emacs doesn't support
+     transparency.  */
+  background.red   >>= 8;
+  background.green >>= 8;
+  background.blue  >>= 8;
+
   /* This loop handles opacity values, since Emacs assumes
      non-transparent images.  Each pixel must be "flattened" by
      calculating the resulting color, given the transparency of the
@@ -8214,7 +8024,7 @@ enum gs_keyword_index
 /* Vector of image_keyword structures describing the format
    of valid user-defined image specifications.  */
 
-static struct image_keyword gs_format[GS_LAST] =
+static const struct image_keyword gs_format[GS_LAST] =
 {
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":pt-width",                IMAGE_POSITIVE_INTEGER_VALUE,           1},
@@ -8325,7 +8135,7 @@ gs_load (f, img)
 
   if (!check_image_size (f, img->width, img->height))
     {
-      image_error ("Invalid image size", Qnil, Qnil);
+      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       return 0;
     }
 
@@ -8605,7 +8415,7 @@ list; if none is loaded, the running session of Emacs won't
 support the image type.  Types 'pbm and 'xbm don't need to be
 listed; they are always supported.  */);
   Vimage_library_alist = Qnil;
-  Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
+  Fput (intern_c_string ("image-library-alist"), Qrisky_local_variable, Qt);
 
   DEFVAR_LISP ("max-image-size", &Vmax_image_size,
     doc: /* Maximum size of images.
@@ -8622,103 +8432,118 @@ non-numeric, there is no explicit limit on the size of images.  */);
   Vimage_type_cache = Qnil;
   staticpro (&Vimage_type_cache);
 
-  Qpbm = intern ("pbm");
+  Qpbm = intern_c_string ("pbm");
   staticpro (&Qpbm);
   ADD_IMAGE_TYPE (Qpbm);
 
-  Qxbm = intern ("xbm");
+  Qxbm = intern_c_string ("xbm");
   staticpro (&Qxbm);
   ADD_IMAGE_TYPE (Qxbm);
 
   define_image_type (&xbm_type, 1);
   define_image_type (&pbm_type, 1);
 
-  Qcount = intern ("count");
+  Qcount = intern_c_string ("count");
   staticpro (&Qcount);
 
-  QCascent = intern (":ascent");
+  QCascent = intern_c_string (":ascent");
   staticpro (&QCascent);
-  QCmargin = intern (":margin");
+  QCmargin = intern_c_string (":margin");
   staticpro (&QCmargin);
-  QCrelief = intern (":relief");
+  QCrelief = intern_c_string (":relief");
   staticpro (&QCrelief);
-  QCconversion = intern (":conversion");
+  QCconversion = intern_c_string (":conversion");
   staticpro (&QCconversion);
-  QCcolor_symbols = intern (":color-symbols");
+  QCcolor_symbols = intern_c_string (":color-symbols");
   staticpro (&QCcolor_symbols);
-  QCheuristic_mask = intern (":heuristic-mask");
+  QCheuristic_mask = intern_c_string (":heuristic-mask");
   staticpro (&QCheuristic_mask);
-  QCindex = intern (":index");
+  QCindex = intern_c_string (":index");
   staticpro (&QCindex);
-  QCmatrix = intern (":matrix");
+  QCmatrix = intern_c_string (":matrix");
   staticpro (&QCmatrix);
-  QCcolor_adjustment = intern (":color-adjustment");
+  QCcolor_adjustment = intern_c_string (":color-adjustment");
   staticpro (&QCcolor_adjustment);
-  QCmask = intern (":mask");
+  QCmask = intern_c_string (":mask");
   staticpro (&QCmask);
 
-  Qlaplace = intern ("laplace");
+  Qlaplace = intern_c_string ("laplace");
   staticpro (&Qlaplace);
-  Qemboss = intern ("emboss");
+  Qemboss = intern_c_string ("emboss");
   staticpro (&Qemboss);
-  Qedge_detection = intern ("edge-detection");
+  Qedge_detection = intern_c_string ("edge-detection");
   staticpro (&Qedge_detection);
-  Qheuristic = intern ("heuristic");
+  Qheuristic = intern_c_string ("heuristic");
   staticpro (&Qheuristic);
 
-  Qpostscript = intern ("postscript");
+  Qpostscript = intern_c_string ("postscript");
   staticpro (&Qpostscript);
 #ifdef HAVE_GHOSTSCRIPT
   ADD_IMAGE_TYPE (Qpostscript);
-  QCloader = intern (":loader");
+  QCloader = intern_c_string (":loader");
   staticpro (&QCloader);
-  QCbounding_box = intern (":bounding-box");
+  QCbounding_box = intern_c_string (":bounding-box");
   staticpro (&QCbounding_box);
-  QCpt_width = intern (":pt-width");
+  QCpt_width = intern_c_string (":pt-width");
   staticpro (&QCpt_width);
-  QCpt_height = intern (":pt-height");
+  QCpt_height = intern_c_string (":pt-height");
   staticpro (&QCpt_height);
 #endif /* HAVE_GHOSTSCRIPT */
 
+#ifdef HAVE_NTGUI
+  Qlibpng_version = intern_c_string ("libpng-version");
+  staticpro (&Qlibpng_version);
+  Fset (Qlibpng_version,
+#if HAVE_PNG
+       make_number (PNG_LIBPNG_VER)
+#else
+       make_number (-1)
+#endif
+       );
+#endif
+
 #if defined (HAVE_XPM) || defined (HAVE_NS)
-  Qxpm = intern ("xpm");
+  Qxpm = intern_c_string ("xpm");
   staticpro (&Qxpm);
   ADD_IMAGE_TYPE (Qxpm);
 #endif
 
 #if defined (HAVE_JPEG) || defined (HAVE_NS)
-  Qjpeg = intern ("jpeg");
+  Qjpeg = intern_c_string ("jpeg");
   staticpro (&Qjpeg);
   ADD_IMAGE_TYPE (Qjpeg);
 #endif
 
 #if defined (HAVE_TIFF) || defined (HAVE_NS)
-  Qtiff = intern ("tiff");
+  Qtiff = intern_c_string ("tiff");
   staticpro (&Qtiff);
   ADD_IMAGE_TYPE (Qtiff);
 #endif
 
 #if defined (HAVE_GIF) || defined (HAVE_NS)
-  Qgif = intern ("gif");
+  Qgif = intern_c_string ("gif");
   staticpro (&Qgif);
   ADD_IMAGE_TYPE (Qgif);
 #endif
 
 #if defined (HAVE_PNG) || defined (HAVE_NS)
-  Qpng = intern ("png");
+  Qpng = intern_c_string ("png");
   staticpro (&Qpng);
   ADD_IMAGE_TYPE (Qpng);
 #endif
 
 #if defined (HAVE_RSVG)
-  Qsvg = intern ("svg");
+  Qsvg = intern_c_string ("svg");
   staticpro (&Qsvg);
   ADD_IMAGE_TYPE (Qsvg);
 #ifdef HAVE_NTGUI
-  Qgdk_pixbuf = intern ("gdk-pixbuf");
+  /* Other libraries used directly by svg code.  */
+  Qgdk_pixbuf = intern_c_string ("gdk-pixbuf");
   staticpro (&Qgdk_pixbuf);
-  Qglib = intern ("glib");
+  Qglib = intern_c_string ("glib");
   staticpro (&Qglib);
+  Qgobject = intern_c_string ("gobject");
+  staticpro (&Qgobject);
 #endif /* HAVE_NTGUI  */
 #endif /* HAVE_RSVG  */