(enum fringe_bitmap_type): Define here.
[bpt/emacs.git] / src / w32fns.c
index 8698459..190ff15 100644 (file)
@@ -55,6 +55,10 @@ Boston, MA 02111-1307, USA.  */
 #include <dlgs.h>
 #define FILE_NAME_TEXT_FIELD edt1
 
+void syms_of_w32fns ();
+void globals_of_w32fns ();
+static void init_external_image_libraries ();
+
 extern void free_frame_menubar ();
 extern void x_compute_fringe_widths P_ ((struct frame *, int));
 extern double atof ();
@@ -152,12 +156,16 @@ int display_hourglass_p;
    over text or in the modeline.  */
 
 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
-Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape;
+Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape, Vx_hand_shape;
 
 /* The shape when over mouse-sensitive text.  */
 
 Lisp_Object Vx_sensitive_text_pointer_shape;
 
+#ifndef IDC_HAND
+#define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+
 /* Color of chars displayed in cursor box.  */
 
 Lisp_Object Vx_cursor_fore_pixel;
@@ -2193,6 +2201,7 @@ x_set_mouse_color (f, arg, oldval)
   else
     horizontal_drag_cursor
       = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
+  /* TODO: hand_cursor */
 
   /* Check and report errors with the above calls.  */
   x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
@@ -2221,6 +2230,7 @@ x_set_mouse_color (f, arg, oldval)
                     &fore_color, &back_color);
     XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
                     &fore_color, &back_color);
+    /* TODO: hand_cursor */
   }
 
   if (FRAME_W32_WINDOW (f) != 0)
@@ -2249,6 +2259,7 @@ x_set_mouse_color (f, arg, oldval)
       && f->output_data.w32->cross_cursor != 0)
     XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
   f->output_data.w32->cross_cursor = cross_cursor;
+    /* TODO: hand_cursor */
 
   XFlush (FRAME_W32_DISPLAY (f));
   UNBLOCK_INPUT;
@@ -2349,9 +2360,8 @@ x_set_cursor_type (f, arg, oldval)
 {
   set_frame_cursor_types (f, arg);
 
-  /* Make sure the cursor gets redrawn.  This is overkill, but how
-     often do people change cursor types?  */
-  update_mode_lines++;
+  /* Make sure the cursor gets redrawn.  */
+  cursor_type_changed = 1;
 }
 \f
 void
@@ -3063,7 +3073,7 @@ and the class is `Emacs.CLASS.SUBCLASS'.  */)
   strcat (name_key, ".");
   strcat (name_key, SDATA (attribute));
 
-  value = x_get_string_resource (Qnil,
+  value = x_get_string_resource (check_x_display_info (Qnil)->xrdb,
                                 name_key, class_key);
 
   if (value != (char *) 0)
@@ -3094,7 +3104,8 @@ x_get_resource_string (attribute, class)
           attribute);
   sprintf (class_key, "%s.%s", EMACS_CLASS, class);
 
-  return x_get_string_resource (sf, name_key, class_key);
+  return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
+                               name_key, class_key);
 }
 
 /* Types we might convert a resource string into.  */
@@ -3417,6 +3428,21 @@ x_figure_window_size (f, parms)
 }
 
 \f
+Cursor
+w32_load_cursor (LPCTSTR name)
+{
+  /* Try first to load cursor from application resource.  */
+  Cursor cursor = LoadImage ((HINSTANCE) GetModuleHandle(NULL),
+                            name, IMAGE_CURSOR, 0, 0,
+                            LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
+  if (!cursor)
+    {
+      /* Then try to load a shared predefined cursor.  */
+      cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0,
+                         LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
+    }
+  return cursor;
+}
 
 extern LRESULT CALLBACK w32_wnd_proc ();
 
@@ -3432,7 +3458,7 @@ w32_init_class (hinst)
   wc.cbWndExtra = WND_EXTRA_BYTES;
   wc.hInstance = hinst;
   wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
-  wc.hCursor = LoadCursor (NULL, IDC_ARROW);
+  wc.hCursor = w32_load_cursor (IDC_ARROW);
   wc.hbrBackground = NULL; /* GetStockObject (WHITE_BRUSH);  */
   wc.lpszMenuName = NULL;
   wc.lpszClassName = EMACS_CLASS;
@@ -4934,30 +4960,6 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       goto dflt;
 
     case WM_SETFOCUS:
-      /*
-        Reinitialize the function pointer track_mouse_event_fn here.
-        This is required even though it is initialized in syms_of_w32fns
-        which is called in main (emacs.c).
-        Reinitialize the function pointer track_mouse_event_fn here.
-        Even though this function pointer is initialized in
-        syms_of_w32fns which is called from main (emacs.c),
-        we need to initialize it again here in order to prevent
-        a crash that occurs in Windows 9x (possibly only when Emacs
-        was built on Windows NT / 2000 / XP?) when handling the
-        WM_MOUSEMOVE message.
-        The crash occurs when attempting to call the Win32 API
-        function TrackMouseEvent through the function pointer.
-        It appears as if the function pointer that is obtained when
-        syms_of_w32fns is called from main is no longer valid
-        (possibly due to DLL relocation?).
-        To resolve this issue, I have placed a call to reinitialize
-        this function pointer here because this message gets received
-        when the Emacs window gains focus.        
-       */
-      track_mouse_event_fn =
-        (TrackMouseEvent_Proc) GetProcAddress (
-            GetModuleHandle ("user32.dll"),
-            "TrackMouseEvent");
       dpyinfo->faked_key = 0;
       reset_modifiers ();
       register_hot_keys (hwnd);
@@ -5084,6 +5086,20 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       ((LPMINMAXINFO) lParam)->ptMaxTrackSize.y = 32767;
       return 0;
 
+    case WM_SETCURSOR:
+      if (LOWORD (lParam) == HTCLIENT)
+       return 0;
+
+      goto dflt;
+
+    case WM_EMACS_SETCURSOR:
+      {
+       Cursor cursor = (Cursor) wParam;
+       if (cursor)
+         SetCursor (cursor);
+       return 0;
+      }
+
     case WM_EMACS_CREATESCROLLBAR:
       return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
                                            (struct scroll_bar *) lParam);
@@ -5674,6 +5690,14 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
   f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
 
+  f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
+  f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
+  f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW);
+  f->output_data.w32->cross_cursor = w32_load_cursor (IDC_CROSS);
+  f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT);
+  f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE);
+  f->output_data.w32->hand_cursor = w32_load_cursor (IDC_HAND);
+
   /* Add the tool-bar height to the initial frame height so that the
      user gets a text display area of the size he specified with -g or
      via .Xdefaults.  Later changes of the tool-bar height don't
@@ -7317,7 +7341,7 @@ static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names)
         {
           newlist = Fcons (XCAR (tem), newlist);
           n_fonts++;
-          if (n_fonts >= max_names)
+          if (max_names >= 0 && n_fonts >= max_names)
             break;
         }
     }
@@ -7331,7 +7355,8 @@ static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names)
    to be listed.  Frame F NULL means we have not yet created any
    frame, which means we can't get proper size info, as we don't have
    a device context to use for GetTextMetrics.
-   MAXNAMES sets a limit on how many fonts to match.  */
+   MAXNAMES sets a limit on how many fonts to match.  If MAXNAMES is
+   negative, then all matching fonts are returned.  */
 
 Lisp_Object
 w32_list_fonts (f, pattern, size, maxnames)
@@ -7444,7 +7469,7 @@ w32_list_fonts (f, pattern, size, maxnames)
             {
               newlist = Fcons (XCAR (tem), newlist);
               n_fonts++;
-              if (n_fonts >= maxnames)
+              if (maxnames >= 0 && n_fonts >= maxnames)
                 break;
               else
                 continue;
@@ -7483,7 +7508,7 @@ w32_list_fonts (f, pattern, size, maxnames)
             {
               newlist = Fcons (XCAR (tem), newlist);
               n_fonts++;
-              if (n_fonts >= maxnames)
+              if (maxnames >= 0 && n_fonts >= maxnames)
                 break;
             }
           /* keep track of the closest matching size in case
@@ -7519,7 +7544,7 @@ w32_list_fonts (f, pattern, size, maxnames)
     }
 
   /* Include any bdf fonts.  */
-  if (n_fonts < maxnames)
+  if (n_fonts < maxnames || maxnames < 0)
   {
     Lisp_Object combined[2];
     combined[0] = w32_list_bdf_fonts (pattern, maxnames - n_fonts);
@@ -8766,7 +8791,7 @@ image_background_transparent (img, f, mask)
              mask = CreateCompatibleDC (frame_dc);
              release_frame_dc (f, frame_dc);
 
-             prev = SelectObject (mask, img->mask);          
+             prev = SelectObject (mask, img->mask);
            }
 
          img->background_transparent
@@ -9314,6 +9339,15 @@ forall_images_in_image_cache (f, fn)
                            W32 support code
  ***********************************************************************/
 
+/* Macro for defining functions that will be loaded from image DLLs.  */
+#define DEF_IMGLIB_FN(func) FARPROC fn_##func
+
+/* Macro for loading those image functions from the library.  */
+#define LOAD_IMGLIB_FN(lib,func) {                                     \
+    fn_##func = (void *) GetProcAddress (lib, #func);                  \
+    if (!fn_##func) return 0;                                          \
+  }
+
 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
                                             XImage **, Pixmap *));
 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
@@ -9441,6 +9475,7 @@ x_put_x_image (f, ximg, pixmap, width, height)
      struct frame *f;
      XImage *ximg;
      Pixmap pixmap;
+     int width, height;
 {
 #if 0  /* I don't think this is necessary looking at where it is used.  */
   HDC hdc = get_frame_dc (f);
@@ -9834,7 +9869,7 @@ w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
 
   w1 = (width + 7) / 8;         /* nb of 8bits elt in X bitmap */
   w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
-  bits = (char *) xmalloc (height * w2);
+  bits = (char *) alloca (height * w2);
   bzero (bits, height * w2);
   for (i = 0; i < height; i++)
     {
@@ -9843,7 +9878,6 @@ w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
         *p++ = reflect_byte(*data++);
     }
   bmp = CreateBitmap (width, height, 1, 1, bits);
-  xfree (bits);
 
   return bmp;
 }
@@ -10022,7 +10056,7 @@ static void convert_mono_to_color_image (f, img, foreground, background)
          0, 0, SRCCOPY);
 
   SelectObject (old_img_dc, old_prev);
-  SelectObject (new_img_dc, new_prev);   
+  SelectObject (new_img_dc, new_prev);
   DeleteDC (old_img_dc);
   DeleteDC (new_img_dc);
   DeleteObject (img->pixmap);
@@ -10259,7 +10293,17 @@ static int xpm_image_p P_ ((Lisp_Object object));
 static int xpm_load P_ ((struct frame *f, struct image *img));
 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
 
+/* Indicate to xpm.h that we don't have Xlib.  */
+#define FOR_MSW
+/* simx.h in xpm defines XColor and XImage differently than Emacs.  */
+#define XColor xpm_XColor
+#define XImage xpm_XImage
+#define PIXEL_ALREADY_TYPEDEFED
 #include "X11/xpm.h"
+#undef FOR_MSW
+#undef XColor
+#undef XImage
+#undef PIXEL_ALREADY_TYPEDEFED
 
 /* The symbol `xpm' identifying XPM-format images.  */
 
@@ -10313,6 +10357,26 @@ static struct image_type xpm_type =
 };
 
 
+/* XPM library details.  */
+
+DEF_IMGLIB_FN (XpmFreeAttributes);
+DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
+DEF_IMGLIB_FN (XpmReadFileToImage);
+DEF_IMGLIB_FN (XImageFree);
+
+
+static int
+init_xpm_functions (library)
+     HMODULE library;
+{
+  LOAD_IMGLIB_FN (library, XpmFreeAttributes);
+  LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
+  LOAD_IMGLIB_FN (library, XpmReadFileToImage);
+  LOAD_IMGLIB_FN (library, XImageFree);
+
+  return 1;
+}
+
 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
    for XPM images.  Such a list must consist of conses whose car and
    cdr are strings.  */
@@ -10361,17 +10425,23 @@ xpm_load (f, img)
      struct frame *f;
      struct image *img;
 {
-  int rc, i;
+  HDC hdc;
+  int rc;
   XpmAttributes attrs;
   Lisp_Object specified_file, color_symbols;
+  xpm_XImage * xpm_image, * xpm_mask;
 
   /* Configure the XPM lib.  Use the visual of frame F.  Allocate
      close colors.  Return colors allocated.  */
   bzero (&attrs, sizeof attrs);
+  xpm_image = xpm_mask = NULL;
+
+#if 0
   attrs.visual = FRAME_X_VISUAL (f);
   attrs.colormap = FRAME_X_COLORMAP (f);
   attrs.valuemask |= XpmVisual;
   attrs.valuemask |= XpmColormap;
+#endif
   attrs.valuemask |= XpmReturnAllocPixels;
 #ifdef XpmAllocCloseColors
   attrs.alloc_close_colors = 1;
@@ -10419,34 +10489,71 @@ xpm_load (f, img)
 
   /* Create a pixmap for the image, either from a file, or from a
      string buffer containing data in the same format as an XPM file.  */
-  BLOCK_INPUT;
+
   specified_file = image_spec_value (img->spec, QCfile, NULL);
+
+  {
+    HDC frame_dc = get_frame_dc (f);
+    hdc = CreateCompatibleDC (frame_dc);
+    release_frame_dc (f, frame_dc);
+  }
+
   if (STRINGP (specified_file))
     {
       Lisp_Object file = x_find_image_file (specified_file);
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNBLOCK_INPUT;
          return 0;
        }
 
-      rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
-                               SDATA (file), &img->pixmap, &img->mask,
-                               &attrs);
+      /* XpmReadFileToPixmap is not available in the Windows port of
+        libxpm.  But XpmReadFileToImage almost does what we want.  */
+      rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
+                                 &xpm_image, &xpm_mask,
+                                 &attrs);
     }
   else
     {
       Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
-      rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
-                                     SDATA (buffer),
-                                     &img->pixmap, &img->mask,
-                                     &attrs);
+      /* XpmCreatePixmapFromBuffer is not available in the Windows port
+        of libxpm.  But XpmCreateImageFromBuffer almost does what we want.  */
+      rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
+                                       &xpm_image, &xpm_mask,
+                                       &attrs);
     }
-  UNBLOCK_INPUT;
 
   if (rc == XpmSuccess)
     {
+      int i;
+
+      /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
+        plus some duplicate attributes.  */
+      if (xpm_image && xpm_image->bitmap)
+       {
+         img->pixmap = xpm_image->bitmap;
+         /* XImageFree in libXpm frees XImage struct without destroying
+            the bitmap, which is what we want.  */
+         fn_XImageFree (xpm_image);
+       }
+      if (xpm_mask && xpm_mask->bitmap)
+       {
+         /* The mask appears to be inverted compared with what we expect.
+            TODO: invert our expectations.  See other places where we
+            have to invert bits because our idea of masks is backwards.  */
+         HGDIOBJ old_obj;
+         old_obj = SelectObject (hdc, xpm_mask->bitmap);
+
+         PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
+         SelectObject (hdc, old_obj);
+
+         img->mask = xpm_mask->bitmap;
+         fn_XImageFree (xpm_mask);
+         DeleteDC (hdc);
+       }
+
+      DeleteDC (hdc);
+
       /* Remember allocated colors.  */
       img->ncolors = attrs.nalloc_pixels;
       img->colors = (unsigned long *) xmalloc (img->ncolors
@@ -10459,12 +10566,12 @@ xpm_load (f, img)
       xassert (img->width > 0 && img->height > 0);
 
       /* The call to XpmFreeAttributes below frees attrs.alloc_pixels.  */
-      BLOCK_INPUT;
-      XpmFreeAttributes (&attrs);
-      UNBLOCK_INPUT;
+      fn_XpmFreeAttributes (&attrs);
     }
   else
     {
+      DeleteDC (hdc);
+
       switch (rc)
        {
        case XpmOpenFailed:
@@ -10789,24 +10896,40 @@ static void XPutPixel (ximg, x, y, color)
 {
   int width = ximg->info.bmiHeader.biWidth;
   int height = ximg->info.bmiHeader.biHeight;
-  int rowbytes = width * 3;
   unsigned char * pixel;
 
-  /* Don't support putting pixels in images with palettes.  */
-  xassert (ximg->info.bmiHeader.biBitCount == 24);
-
-  /* Ensure scanlines are aligned on 4 byte boundaries.  */
-  if (rowbytes % 4)
-    rowbytes += 4 - (rowbytes % 4);
-
-  pixel = ximg->data + y * rowbytes + x * 3;
-  /* Windows bitmaps are in BGR order.  */
-  *pixel = GetBValue (color);
-  *(pixel + 1) = GetGValue (color);
-  *(pixel + 2) = GetRValue (color);
+  /* True color images.  */
+  if (ximg->info.bmiHeader.biBitCount == 24)
+    {
+      int rowbytes = width * 3;
+      /* Ensure scanlines are aligned on 4 byte boundaries.  */
+      if (rowbytes % 4)
+       rowbytes += 4 - (rowbytes % 4);
+
+      pixel = ximg->data + y * rowbytes + x * 3;
+      /* Windows bitmaps are in BGR order.  */
+      *pixel = GetBValue (color);
+      *(pixel + 1) = GetGValue (color);
+      *(pixel + 2) = GetRValue (color);
+    }
+  /* Monochrome images.  */
+  else if (ximg->info.bmiHeader.biBitCount == 1)
+    {
+      int rowbytes = width / 8;
+      /* Ensure scanlines are aligned on 4 byte boundaries.  */
+      if (rowbytes % 4)
+       rowbytes += 4 - (rowbytes % 4);
+      pixel = ximg->data + y * rowbytes + x / 8;
+      /* Filter out palette info.  */
+      if (color & 0x00ffffff)
+       *pixel = *pixel | (1 << x % 8);
+      else
+       *pixel = *pixel & ~(1 << x % 8);
+    }
+  else
+    image_error ("XPutPixel: palette image not supported.", Qnil, Qnil);
 }
 
-
 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
    RGB members are set.  F is the frame on which this all happens.
    COLORS will be freed; an existing IMG->pixmap will be freed, too.  */
@@ -11142,7 +11265,7 @@ x_build_heuristic_mask (f, img, how)
   image_background_transparent (img, f, img_dc);
 
   /* Put mask_img into img->mask.  */
-  x_destroy_x_image (mask_img);
+  x_destroy_x_image ((XImage *)mask_img);
   SelectObject (img_dc, prev);
   DeleteDC (img_dc);
 
@@ -11586,6 +11709,59 @@ static struct image_type png_type =
   NULL
 };
 
+/* PNG library details.  */
+
+DEF_IMGLIB_FN (png_get_io_ptr);
+DEF_IMGLIB_FN (png_check_sig);
+DEF_IMGLIB_FN (png_create_read_struct);
+DEF_IMGLIB_FN (png_create_info_struct);
+DEF_IMGLIB_FN (png_destroy_read_struct);
+DEF_IMGLIB_FN (png_set_read_fn);
+DEF_IMGLIB_FN (png_init_io);
+DEF_IMGLIB_FN (png_set_sig_bytes);
+DEF_IMGLIB_FN (png_read_info);
+DEF_IMGLIB_FN (png_get_IHDR);
+DEF_IMGLIB_FN (png_get_valid);
+DEF_IMGLIB_FN (png_set_strip_16);
+DEF_IMGLIB_FN (png_set_expand);
+DEF_IMGLIB_FN (png_set_gray_to_rgb);
+DEF_IMGLIB_FN (png_set_background);
+DEF_IMGLIB_FN (png_get_bKGD);
+DEF_IMGLIB_FN (png_read_update_info);
+DEF_IMGLIB_FN (png_get_channels);
+DEF_IMGLIB_FN (png_get_rowbytes);
+DEF_IMGLIB_FN (png_read_image);
+DEF_IMGLIB_FN (png_read_end);
+DEF_IMGLIB_FN (png_error);
+
+static int
+init_png_functions (library)
+     HMODULE library;
+{
+  LOAD_IMGLIB_FN (library, png_get_io_ptr);
+  LOAD_IMGLIB_FN (library, png_check_sig);
+  LOAD_IMGLIB_FN (library, png_create_read_struct);
+  LOAD_IMGLIB_FN (library, png_create_info_struct);
+  LOAD_IMGLIB_FN (library, png_destroy_read_struct);
+  LOAD_IMGLIB_FN (library, png_set_read_fn);
+  LOAD_IMGLIB_FN (library, png_init_io);
+  LOAD_IMGLIB_FN (library, png_set_sig_bytes);
+  LOAD_IMGLIB_FN (library, png_read_info);
+  LOAD_IMGLIB_FN (library, png_get_IHDR);
+  LOAD_IMGLIB_FN (library, png_get_valid);
+  LOAD_IMGLIB_FN (library, png_set_strip_16);
+  LOAD_IMGLIB_FN (library, png_set_expand);
+  LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
+  LOAD_IMGLIB_FN (library, png_set_background);
+  LOAD_IMGLIB_FN (library, png_get_bKGD);
+  LOAD_IMGLIB_FN (library, png_read_update_info);
+  LOAD_IMGLIB_FN (library, png_get_channels);
+  LOAD_IMGLIB_FN (library, png_get_rowbytes);
+  LOAD_IMGLIB_FN (library, png_read_image);
+  LOAD_IMGLIB_FN (library, png_read_end);
+  LOAD_IMGLIB_FN (library, png_error);
+  return 1;
+}
 
 /* Return non-zero if OBJECT is a valid PNG image specification.  */
 
@@ -11648,10 +11824,10 @@ png_read_from_memory (png_ptr, data, length)
      png_size_t length;
 {
   struct png_memory_storage *tbr
-    = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
+    = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
 
   if (length > tbr->len - tbr->index)
-    png_error (png_ptr, "Read error");
+    fn_png_error (png_ptr, "Read error");
 
   bcopy (tbr->bytes + tbr->index, data, length);
   tbr->index = tbr->index + length;
@@ -11674,14 +11850,13 @@ png_load (f, img)
   png_info *info_ptr = NULL, *end_info = NULL;
   FILE *volatile fp = NULL;
   png_byte sig[8];
-  png_byte *volatile pixels = NULL;
-  png_byte **volatile rows = NULL;
+  png_byte * volatile pixels = NULL;
+  png_byte ** volatile rows = NULL;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   png_byte channels;
   png_uint_32 row_bytes;
   int transparent_p;
-  char *gamma_str;
   double screen_gamma, image_gamma;
   int intent;
   struct png_memory_storage tbr;  /* Data to be read */
@@ -11696,31 +11871,31 @@ png_load (f, img)
     {
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
 
       /* Open the image file.  */
       fp = fopen (SDATA (file), "rb");
       if (!fp)
-        {
-          image_error ("Cannot open image file `%s'", file, Qnil);
-          UNGCPRO;
-          fclose (fp);
-          return 0;
-        }
+       {
+         image_error ("Cannot open image file `%s'", file, Qnil);
+         UNGCPRO;
+         fclose (fp);
+         return 0;
+       }
 
       /* Check PNG signature.  */
       if (fread (sig, 1, sizeof sig, fp) != sizeof sig
-          || !png_check_sig (sig, sizeof sig))
-        {
-          image_error ("Not a PNG file:` %s'", file, Qnil);
-          UNGCPRO;
-          fclose (fp);
-          return 0;
-        }
+         || !fn_png_check_sig (sig, sizeof sig))
+       {
+         image_error ("Not a PNG file: `%s'", file, Qnil);
+         UNGCPRO;
+         fclose (fp);
+         return 0;
+       }
     }
   else
     {
@@ -11731,7 +11906,7 @@ png_load (f, img)
 
       /* Check PNG signature.  */
       if (tbr.len < sizeof sig
-         || !png_check_sig (tbr.bytes, sizeof sig))
+         || !fn_png_check_sig (tbr.bytes, sizeof sig))
        {
          image_error ("Not a PNG image: `%s'", img->spec, Qnil);
          UNGCPRO;
@@ -11743,8 +11918,8 @@ png_load (f, img)
     }
 
   /* Initialize read and info structs for PNG lib.  */
-  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
-                                   my_png_error, my_png_warning);
+  png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
+                                      my_png_error, my_png_warning);
   if (!png_ptr)
     {
       if (fp) fclose (fp);
@@ -11752,19 +11927,19 @@ png_load (f, img)
       return 0;
     }
 
-  info_ptr = png_create_info_struct (png_ptr);
+  info_ptr = fn_png_create_info_struct (png_ptr);
   if (!info_ptr)
     {
-      png_destroy_read_struct (&png_ptr, NULL, NULL);
+      fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
       if (fp) fclose (fp);
       UNGCPRO;
       return 0;
     }
 
-  end_info = png_create_info_struct (png_ptr);
+  end_info = fn_png_create_info_struct (png_ptr);
   if (!end_info)
     {
-      png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+      fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
       if (fp) fclose (fp);
       UNGCPRO;
       return 0;
@@ -11776,7 +11951,7 @@ png_load (f, img)
     {
     error:
       if (png_ptr)
-        png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+        fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
       xfree (pixels);
       xfree (rows);
       if (fp) fclose (fp);
@@ -11786,18 +11961,18 @@ png_load (f, img)
 
   /* Read image info.  */
   if (!NILP (specified_data))
-    png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
+    fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
   else
-    png_init_io (png_ptr, fp);
+    fn_png_init_io (png_ptr, fp);
 
-  png_set_sig_bytes (png_ptr, sizeof sig);
-  png_read_info (png_ptr, info_ptr);
-  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
-               &interlace_type, NULL, NULL);
+  fn_png_set_sig_bytes (png_ptr, sizeof sig);
+  fn_png_read_info (png_ptr, info_ptr);
+  fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+                  &interlace_type, NULL, NULL);
 
   /* If image contains simply transparency data, we prefer to
      construct a clipping mask.  */
-  if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
+  if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
     transparent_p = 1;
   else
     transparent_p = 0;
@@ -11808,46 +11983,44 @@ png_load (f, img)
 
   /* Strip more than 8 bits per channel.  */
   if (bit_depth == 16)
-    png_set_strip_16 (png_ptr);
+    fn_png_set_strip_16 (png_ptr);
 
   /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
      if available.  */
-  png_set_expand (png_ptr);
+  fn_png_set_expand (png_ptr);
 
   /* Convert grayscale images to RGB.  */
   if (color_type == PNG_COLOR_TYPE_GRAY
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-    png_set_gray_to_rgb (png_ptr);
+    fn_png_set_gray_to_rgb (png_ptr);
 
-  /* The value 2.2 is a guess for PC monitors from PNG example.c.  */
-  gamma_str = getenv ("SCREEN_GAMMA");
-  screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
+  screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
 
+#if 0 /* Avoid double gamma correction for PNG images. */
   /* Tell the PNG lib to handle gamma correction for us.  */
-
 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
   if (png_get_sRGB (png_ptr, info_ptr, &intent))
-    /* There is a special chunk in the image specifying the gamma.  */
-    png_set_sRGB (png_ptr, info_ptr, intent);
+    /* The libpng documentation says this is right in this case.  */
+    png_set_gamma (png_ptr, screen_gamma, 0.45455);
   else
 #endif
   if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
     /* Image contains gamma information.  */
     png_set_gamma (png_ptr, screen_gamma, image_gamma);
   else
-    /* Use a default of 0.5 for the image gamma.  */
-    png_set_gamma (png_ptr, screen_gamma, 0.5);
+    /* Use the standard default for the image gamma.  */
+    png_set_gamma (png_ptr, screen_gamma, 0.45455);
+#endif /* if 0 */
 
   /* Handle alpha channel by combining the image with a background
      color.  Do this only if a real alpha channel is supplied.  For
      simple transparency, we prefer a clipping mask.  */
   if (!transparent_p)
     {
-      png_color_16 *image_background;
+      png_color_16 *image_bg;
       Lisp_Object specified_bg
        = image_spec_value (img->spec, QCbackground, NULL);
 
-
       if (STRINGP (specified_bg))
        /* The user specified `:background', use that.  */
        {
@@ -11857,55 +12030,57 @@ png_load (f, img)
              png_color_16 user_bg;
 
              bzero (&user_bg, sizeof user_bg);
-             user_bg.red = color.red;
-             user_bg.green = color.green;
-             user_bg.blue = color.blue;
+             user_bg.red = 256 * GetRValue (color);
+             user_bg.green = 256 * GetGValue (color);
+             user_bg.blue = 256 * GetBValue (color);
 
-             png_set_background (png_ptr, &user_bg,
-                                 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+             fn_png_set_background (png_ptr, &user_bg,
+                                    PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
            }
        }
-      else if (png_get_bKGD (png_ptr, info_ptr, &image_background))
+      else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
        /* Image contains a background color with which to
           combine the image.  */
-       png_set_background (png_ptr, image_background,
-                           PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+       fn_png_set_background (png_ptr, image_bg,
+                              PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
       else
        {
          /* Image does not contain a background color with which
             to combine the image data via an alpha channel.  Use
             the frame's background instead.  */
-         XColor color;
-         Colormap cmap;
+         COLORREF color;
          png_color_16 frame_background;
+         color = FRAME_BACKGROUND_PIXEL (f);
+#if 0 /* TODO : Colormap support.  */
+         Colormap cmap;
 
          cmap = FRAME_X_COLORMAP (f);
-         color.pixel = FRAME_BACKGROUND_PIXEL (f);
          x_query_color (f, &color);
+#endif
 
          bzero (&frame_background, sizeof frame_background);
-         frame_background.red = color.red;
-         frame_background.green = color.green;
-         frame_background.blue = color.blue;
+         frame_background.red = 256 * GetRValue (color);
+         frame_background.green = 256 * GetGValue (color);
+         frame_background.blue = 256 * GetBValue (color);
 
-         png_set_background (png_ptr, &frame_background,
-                             PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+         fn_png_set_background (png_ptr, &frame_background,
+                                PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
        }
     }
 
   /* Update info structure.  */
-  png_read_update_info (png_ptr, info_ptr);
+  fn_png_read_update_info (png_ptr, info_ptr);
 
   /* Get number of channels.  Valid values are 1 for grayscale images
      and images with a palette, 2 for grayscale images with transparency
      information (alpha channel), 3 for RGB images, and 4 for RGB
      images with alpha channel, i.e. RGBA.  If conversions above were
      sufficient we should only have 3 or 4 channels here.  */
-  channels = png_get_channels (png_ptr, info_ptr);
+  channels = fn_png_get_channels (png_ptr, info_ptr);
   xassert (channels == 3 || channels == 4);
 
   /* Number of bytes needed for one row of the image.  */
-  row_bytes = png_get_rowbytes (png_ptr, info_ptr);
+  row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
 
   /* Allocate memory for the image.  */
   pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
@@ -11914,8 +12089,8 @@ png_load (f, img)
     rows[i] = pixels + i * row_bytes;
 
   /* Read the entire image.  */
-  png_read_image (png_ptr, rows);
-  png_read_end (png_ptr, info_ptr);
+  fn_png_read_image (png_ptr, rows);
+  fn_png_read_end (png_ptr, info_ptr);
   if (fp)
     {
       fclose (fp);
@@ -11935,13 +12110,14 @@ png_load (f, img)
                                       &mask_img, &img->mask))
     {
       x_destroy_x_image (ximg);
-      XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
+      DeleteObject (img->pixmap);
       img->pixmap = 0;
       goto error;
     }
-
   /* Fill the X image and mask from PNG data.  */
+#if 0 /* TODO: Color tables.  */
   init_color_table ();
+#endif
 
   for (y = 0; y < height; ++y)
     {
@@ -11951,11 +12127,14 @@ png_load (f, img)
        {
          unsigned r, g, b;
 
-         r = *p++ << 8;
-         g = *p++ << 8;
-         b = *p++ << 8;
+         r = *p++;
+         g = *p++;
+         b = *p++;
+#if 0 /* TODO: Color tables.  */
          XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
-
+#else
+         XPutPixel (ximg, x, y, PALETTERGB (r, g, b));
+#endif
          /* An alpha channel, aka mask channel, associates variable
             transparency with an image.  Where other image formats
             support binary transparency---fully transparent or fully
@@ -11986,19 +12165,26 @@ png_load (f, img)
        overrode it.  */
     {
       png_color_16 *bg;
-      if (png_get_bKGD (png_ptr, info_ptr, &bg))
+      if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
        {
+#if 0 /* TODO: Color tables.  */
          img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
+#else
+         img->background = PALETTERGB (bg->red / 256, bg->green / 256,
+                                       bg->blue / 256);
+#endif
          img->background_valid = 1;
        }
     }
 
+#if 0 /* TODO: Color tables.  */
   /* Remember colors allocated for this image.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
 
   /* Clean up.  */
-  png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+  fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
   xfree (rows);
   xfree (pixels);
 
@@ -12105,6 +12291,44 @@ static struct image_type jpeg_type =
 };
 
 
+/* JPEG library details.  */
+DEF_IMGLIB_FN (jpeg_CreateDecompress);
+DEF_IMGLIB_FN (jpeg_start_decompress);
+DEF_IMGLIB_FN (jpeg_finish_decompress);
+DEF_IMGLIB_FN (jpeg_destroy_decompress);
+DEF_IMGLIB_FN (jpeg_read_header);
+DEF_IMGLIB_FN (jpeg_read_scanlines);
+DEF_IMGLIB_FN (jpeg_stdio_src);
+DEF_IMGLIB_FN (jpeg_std_error);
+DEF_IMGLIB_FN (jpeg_resync_to_restart);
+
+static int
+init_jpeg_functions (library)
+     HMODULE library;
+{
+  LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
+  LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
+  LOAD_IMGLIB_FN (library, jpeg_start_decompress);
+  LOAD_IMGLIB_FN (library, jpeg_read_header);
+  LOAD_IMGLIB_FN (library, jpeg_stdio_src);
+  LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
+  LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
+  LOAD_IMGLIB_FN (library, jpeg_std_error);
+  LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
+  return 1;
+}
+
+/* Wrapper since we can't directly assign the function pointer
+   to another function pointer that was declared more completely easily.  */
+static boolean
+jpeg_resync_to_restart_wrapper(cinfo, desired)
+     j_decompress_ptr cinfo;
+     int desired;
+{
+  return fn_jpeg_resync_to_restart (cinfo, desired);
+}
+
+
 /* Return non-zero if OBJECT is a valid JPEG image specification.  */
 
 static int
@@ -12129,6 +12353,7 @@ struct my_jpeg_error_mgr
   jmp_buf setjmp_buffer;
 };
 
+
 static void
 my_error_exit (cinfo)
      j_common_ptr cinfo;
@@ -12137,6 +12362,7 @@ my_error_exit (cinfo)
   longjmp (mgr->setjmp_buffer, 1);
 }
 
+
 /* Init source method for JPEG data source manager.  Called by
    jpeg_read_header() before any data is actually read.  See
    libjpeg.doc from the JPEG lib distribution.  */
@@ -12226,7 +12452,7 @@ jpeg_memory_src (cinfo, data, len)
   src->init_source = our_init_source;
   src->fill_input_buffer = our_fill_input_buffer;
   src->skip_input_data = our_skip_input_data;
-  src->resync_to_restart = jpeg_resync_to_restart; /* Use default method.  */
+  src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method.  */
   src->term_source = our_term_source;
   src->bytes_in_buffer = len;
   src->next_input_byte = data;
@@ -12264,24 +12490,24 @@ jpeg_load (f, img)
     {
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
 
       fp = fopen (SDATA (file), "r");
       if (fp == NULL)
-        {
-          image_error ("Cannot open `%s'", file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+       {
+         image_error ("Cannot open `%s'", file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
     }
 
   /* Customize libjpeg's error handling to call my_error_exit when an
-     error is detected. This function will perform a longjmp. */
-  cinfo.err = jpeg_std_error (&mgr.pub);
+     error is detected.  This function will perform a longjmp.  */
+  cinfo.err = fn_jpeg_std_error (&mgr.pub);
   mgr.pub.error_exit = my_error_exit;
 
   if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
@@ -12297,8 +12523,8 @@ jpeg_load (f, img)
 
       /* Close the input file and destroy the JPEG object.  */
       if (fp)
-        fclose (fp);
-      jpeg_destroy_decompress (&cinfo);
+       fclose ((FILE *) fp);
+      fn_jpeg_destroy_decompress (&cinfo);
 
       /* If we already have an XImage, free that.  */
       x_destroy_x_image (ximg);
@@ -12311,27 +12537,26 @@ jpeg_load (f, img)
     }
 
   /* Create the JPEG decompression object.  Let it read from fp.
-     Read the JPEG image header.  */
-  jpeg_create_decompress (&cinfo);
+        Read the JPEG image header.  */
+  fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
 
   if (NILP (specified_data))
-    jpeg_stdio_src (&cinfo, fp);
+    fn_jpeg_stdio_src (&cinfo, (FILE *) fp);
   else
     jpeg_memory_src (&cinfo, SDATA (specified_data),
                     SBYTES (specified_data));
 
-  jpeg_read_header (&cinfo, TRUE);
+  fn_jpeg_read_header (&cinfo, TRUE);
 
   /* Customize decompression so that color quantization will be used.
-     Start decompression.  */
+        Start decompression.  */
   cinfo.quantize_colors = TRUE;
-  jpeg_start_decompress (&cinfo);
+  fn_jpeg_start_decompress (&cinfo);
   width = img->width = cinfo.output_width;
   height = img->height = cinfo.output_height;
 
   /* Create X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
-                                   &img->pixmap))
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     longjmp (mgr.setjmp_buffer, 2);
 
   /* Allocate colors.  When color quantization is used,
@@ -12349,27 +12574,33 @@ jpeg_load (f, img)
     else
       ir = 0, ig = 0, ib = 0;
 
+#if 0 /* TODO: Color tables.  */
     /* Use the color table mechanism because it handles colors that
        cannot be allocated nicely.  Such colors will be replaced with
        a default color, and we don't have to care about which colors
        can be freed safely, and which can't.  */
     init_color_table ();
+#endif
     colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
                                       * sizeof *colors);
 
     for (i = 0; i < cinfo.actual_number_of_colors; ++i)
       {
-       /* Multiply RGB values with 255 because X expects RGB values
-          in the range 0..0xffff.  */
-       int r = cinfo.colormap[ir][i] << 8;
-       int g = cinfo.colormap[ig][i] << 8;
-       int b = cinfo.colormap[ib][i] << 8;
+       int r = cinfo.colormap[ir][i];
+       int g = cinfo.colormap[ig][i];
+       int b = cinfo.colormap[ib][i];
+#if 0 /* TODO: Color tables.  */
        colors[i] = lookup_rgb_color (f, r, g, b);
+#else
+       colors[i] = PALETTERGB (r, g, b);
+#endif
       }
 
+#if 0 /* TODO: Color tables.  */
     /* Remember those colors actually allocated.  */
     img->colors = colors_in_color_table (&img->ncolors);
     free_color_table ();
+#endif
   }
 
   /* Read pixels.  */
@@ -12378,16 +12609,16 @@ jpeg_load (f, img)
                                    row_stride, 1);
   for (y = 0; y < height; ++y)
     {
-      jpeg_read_scanlines (&cinfo, buffer, 1);
+      fn_jpeg_read_scanlines (&cinfo, buffer, 1);
       for (x = 0; x < cinfo.output_width; ++x)
        XPutPixel (ximg, x, y, colors[buffer[0][x]]);
     }
 
   /* Clean up.  */
-  jpeg_finish_decompress (&cinfo);
-  jpeg_destroy_decompress (&cinfo);
+  fn_jpeg_finish_decompress (&cinfo);
+  fn_jpeg_destroy_decompress (&cinfo);
   if (fp)
-    fclose (fp);
+    fclose ((FILE *) fp);
 
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
@@ -12396,7 +12627,6 @@ jpeg_load (f, img)
   /* Put the image into the pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-  UNBLOCK_INPUT;
   UNGCPRO;
   return 1;
 }
@@ -12465,6 +12695,28 @@ static struct image_type tiff_type =
   NULL
 };
 
+/* TIFF library details.  */
+DEF_IMGLIB_FN (TIFFSetErrorHandler);
+DEF_IMGLIB_FN (TIFFSetWarningHandler);
+DEF_IMGLIB_FN (TIFFOpen);
+DEF_IMGLIB_FN (TIFFClientOpen);
+DEF_IMGLIB_FN (TIFFGetField);
+DEF_IMGLIB_FN (TIFFReadRGBAImage);
+DEF_IMGLIB_FN (TIFFClose);
+
+static int
+init_tiff_functions (library)
+     HMODULE library;
+{
+  LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
+  LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
+  LOAD_IMGLIB_FN (library, TIFFOpen);
+  LOAD_IMGLIB_FN (library, TIFFClientOpen);
+  LOAD_IMGLIB_FN (library, TIFFGetField);
+  LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
+  LOAD_IMGLIB_FN (library, TIFFClose);
+  return 1;
+}
 
 /* Return non-zero if OBJECT is a valid TIFF image specification.  */
 
@@ -12644,8 +12896,8 @@ tiff_load (f, img)
   file = Qnil;
   GCPRO1 (file);
 
-  TIFFSetErrorHandler (tiff_error_handler);
-  TIFFSetWarningHandler (tiff_warning_handler);
+  fn_TIFFSetErrorHandler (tiff_error_handler);
+  fn_TIFFSetWarningHandler (tiff_warning_handler);
 
   if (NILP (specified_data))
     {
@@ -12659,7 +12911,7 @@ tiff_load (f, img)
        }
 
       /* Try to open the image file.  */
-      tiff = TIFFOpen (SDATA (file), "r");
+      tiff = fn_TIFFOpen (SDATA (file), "r");
       if (tiff == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
@@ -12674,14 +12926,14 @@ tiff_load (f, img)
       memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
-      tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
-                            (TIFFReadWriteProc) tiff_read_from_memory,
-                            (TIFFReadWriteProc) tiff_write_from_memory,
-                            tiff_seek_in_memory,
-                            tiff_close_memory,
-                            tiff_size_of_memory,
-                            tiff_mmap_memory,
-                            tiff_unmap_memory);
+      tiff = fn_TIFFClientOpen ("memory_source", "r", &memsrc,
+                                (TIFFReadWriteProc) tiff_read_from_memory,
+                                (TIFFReadWriteProc) tiff_write_from_memory,
+                                tiff_seek_in_memory,
+                                tiff_close_memory,
+                                tiff_size_of_memory,
+                                tiff_mmap_memory,
+                                tiff_unmap_memory);
 
       if (!tiff)
        {
@@ -12693,12 +12945,12 @@ tiff_load (f, img)
 
   /* Get width and height of the image, and allocate a raster buffer
      of width x height 32-bit values.  */
-  TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
-  TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
+  fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
+  fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
   buf = (uint32 *) xmalloc (width * height * sizeof *buf);
 
-  rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
-  TIFFClose (tiff);
+  rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
+  fn_TIFFClose (tiff);
   if (!rc)
     {
       image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
@@ -12715,8 +12967,10 @@ tiff_load (f, img)
       return 0;
     }
 
+#if 0 /* TODO: Color tables.  */
   /* Initialize the color table.  */
   init_color_table ();
+#endif
 
   /* Process the pixel raster.  Origin is in the lower-left corner.  */
   for (y = 0; y < height; ++y)
@@ -12726,16 +12980,22 @@ tiff_load (f, img)
       for (x = 0; x < width; ++x)
        {
          uint32 abgr = row[x];
-         int r = TIFFGetR (abgr) << 8;
-         int g = TIFFGetG (abgr) << 8;
-         int b = TIFFGetB (abgr) << 8;
+         int r = TIFFGetR (abgr);
+         int g = TIFFGetG (abgr);
+         int b = TIFFGetB (abgr);
+#if 0 /* TODO: Color tables.  */
          XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
+#else
+          XPutPixel (ximg, x, height - 1 - y, PALETTERGB (r, g, b));
+#endif
        }
     }
 
+#if 0 /* TODO: Color tables.  */
   /* Remember the colors allocated for the image.  Free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
 
   img->width = width;
   img->height = height;
@@ -12763,7 +13023,9 @@ tiff_load (f, img)
 
 #if HAVE_GIF
 
+#define DrawText gif_DrawText
 #include <gif_lib.h>
+#undef DrawText
 
 static int gif_image_p P_ ((Lisp_Object object));
 static int gif_load P_ ((struct frame *f, struct image *img));
@@ -12819,6 +13081,25 @@ static struct image_type gif_type =
   NULL
 };
 
+
+/* GIF library details.  */
+DEF_IMGLIB_FN (DGifCloseFile);
+DEF_IMGLIB_FN (DGifSlurp);
+DEF_IMGLIB_FN (DGifOpen);
+DEF_IMGLIB_FN (DGifOpenFileName);
+
+static int
+init_gif_functions (library)
+     HMODULE library;
+{
+  LOAD_IMGLIB_FN (library, DGifCloseFile);
+  LOAD_IMGLIB_FN (library, DGifSlurp);
+  LOAD_IMGLIB_FN (library, DGifOpen);
+  LOAD_IMGLIB_FN (library, DGifOpenFileName);
+  return 1;
+}
+
+
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
@@ -12905,7 +13186,7 @@ gif_load (f, img)
         }
 
       /* Open the GIF file.  */
-      gif = DGifOpenFileName (SDATA (file));
+      gif = fn_DGifOpenFileName (SDATA (file));
       if (gif == NULL)
         {
           image_error ("Cannot open `%s'", file, Qnil);
@@ -12921,7 +13202,7 @@ gif_load (f, img)
       memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
-      gif = DGifOpen(&memsrc, gif_read_from_memory);
+      gif = fn_DGifOpen(&memsrc, gif_read_from_memory);
       if (!gif)
        {
          image_error ("Cannot open memory source `%s'", img->spec, Qnil);
@@ -12931,11 +13212,11 @@ gif_load (f, img)
     }
 
   /* Read entire contents.  */
-  rc = DGifSlurp (gif);
+  rc = fn_DGifSlurp (gif);
   if (rc == GIF_ERROR)
     {
       image_error ("Error reading `%s'", img->spec, Qnil);
-      DGifCloseFile (gif);
+      fn_DGifCloseFile (gif);
       UNGCPRO;
       return 0;
     }
@@ -12946,18 +13227,18 @@ gif_load (f, img)
     {
       image_error ("Invalid image number `%s' in image `%s'",
                    image, img->spec);
-      DGifCloseFile (gif);
+      fn_DGifCloseFile (gif);
       UNGCPRO;
       return 0;
     }
 
-  width = img->width = gif->SWidth;
-  height = img->height = gif->SHeight;
+  width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
+  height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
 
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
-      DGifCloseFile (gif);
+      fn_DGifCloseFile (gif);
       UNGCPRO;
       return 0;
     }
@@ -12966,19 +13247,27 @@ gif_load (f, img)
   gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
   if (!gif_color_map)
     gif_color_map = gif->SColorMap;
+#if 0 /* TODO: Color tables */
   init_color_table ();
+#endif
   bzero (pixel_colors, sizeof pixel_colors);
 
   for (i = 0; i < gif_color_map->ColorCount; ++i)
     {
-      int r = gif_color_map->Colors[i].Red << 8;
-      int g = gif_color_map->Colors[i].Green << 8;
-      int b = gif_color_map->Colors[i].Blue << 8;
+      int r = gif_color_map->Colors[i].Red;
+      int g = gif_color_map->Colors[i].Green;
+      int b = gif_color_map->Colors[i].Blue;
+#if 0 /* TODO: Color tables */
       pixel_colors[i] = lookup_rgb_color (f, r, g, b);
+#else
+      pixel_colors[i] = PALETTERGB (r, g, b);
+#endif
     }
 
+#if 0 /* TODO: Color tables */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
 
   /* Clear the part of the screen image that are not covered by
      the image from the GIF file.  Full animated GIF support
@@ -13049,7 +13338,7 @@ gif_load (f, img)
          }
     }
 
-  DGifCloseFile (gif);
+  fn_DGifCloseFile (gif);
 
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
@@ -13073,6 +13362,10 @@ gif_load (f, img)
 
 Lisp_Object Qpostscript;
 
+/* Keyword symbols.  */
+
+Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
+
 #ifdef HAVE_GHOSTSCRIPT
 static int gs_image_p P_ ((Lisp_Object object));
 static int gs_load P_ ((struct frame *f, struct image *img));
@@ -14906,14 +15199,9 @@ If the underlying system call fails, value is nil.  */)
 void
 syms_of_w32fns ()
 {
-  HMODULE user32_lib = GetModuleHandle ("user32.dll");
-
+  globals_of_w32fns ();
   /* This is zero if not using MS-Windows.  */
   w32_in_use = 0;
-
-  /* TrackMouseEvent not available in all versions of Windows, so must load
-     it dynamically.  Do it once, here, instead of every time it is used.  */
-  track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
   track_mouse_window = NULL;
 
   w32_visible_system_caret_hwnd = NULL;
@@ -15161,7 +15449,7 @@ system to handle them.  */);
   init_x_parm_symbols ();
 
   DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
-              doc: /* List of directories to search for bitmap files for w32.  */);
+              doc: /* List of directories to search for window system bitmap files.  */);
   Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
 
   DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
@@ -15432,7 +15720,6 @@ versions of Windows) characters.  */);
   staticpro (&QCrelief);
   Qpostscript = intern ("postscript");
   staticpro (&Qpostscript);
-#if 0 /* TODO: These need entries at top of file.  */
   QCloader = intern (":loader");
   staticpro (&QCloader);
   QCbounding_box = intern (":bounding-box");
@@ -15441,7 +15728,6 @@ versions of Windows) characters.  */);
   staticpro (&QCpt_width);
   QCpt_height = intern (":pt-height");
   staticpro (&QCpt_height);
-#endif
   QCindex = intern (":index");
   staticpro (&QCindex);
   Qpbm = intern ("pbm");
@@ -15497,37 +15783,100 @@ versions of Windows) characters.  */);
 }
 
 
-void
-init_xfns ()
+/*
+       globals_of_w32fns is used to initialize those global variables that
+       must always be initialized on startup even when the global variable
+       initialized is non zero (see the function main in emacs.c).
+       globals_of_w32fns is called from syms_of_w32fns when the global
+       variable initialized is 0 and directly from main when initialized
+       is non zero.
+ */
+void globals_of_w32fns ()
 {
-  image_types = NULL;
-  Vimage_types = Qnil;
+  HMODULE user32_lib = GetModuleHandle ("user32.dll");
+       /*
+               TrackMouseEvent not available in all versions of Windows, so must load
+               it dynamically.  Do it once, here, instead of every time it is used.
+  */
+  track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
+}
 
-  define_image_type (&pbm_type);
-  define_image_type (&xbm_type);
-#if 0 /* TODO : Image support for W32 */
-  define_image_type (&gs_type);
-#endif
+/* Initialize image types. Based on which libraries are available.  */
+static void
+init_external_image_libraries ()
+{
+  HINSTANCE library;
 
 #if HAVE_XPM
-  define_image_type (&xpm_type);
+  if ((library = LoadLibrary ("libXpm.dll")))
+    {
+      if (init_xpm_functions (library))
+       define_image_type (&xpm_type);
+    }
+
 #endif
 
 #if HAVE_JPEG
-  define_image_type (&jpeg_type);
+  /* Try loading jpeg library under probable names.  */
+  if ((library = LoadLibrary ("libjpeg.dll"))
+      || (library = LoadLibrary ("jpeg-62.dll"))
+      || (library = LoadLibrary ("jpeg.dll")))
+    {
+      if (init_jpeg_functions (library))
+       define_image_type (&jpeg_type);
+    }
 #endif
 
 #if HAVE_TIFF
-  define_image_type (&tiff_type);
+  if (library = LoadLibrary ("libtiff.dll"))
+    {
+      if (init_tiff_functions (library))
+        define_image_type (&tiff_type);
+    }
 #endif
 
 #if HAVE_GIF
-  define_image_type (&gif_type);
+  if (library = LoadLibrary ("libungif.dll"))
+    {
+      if (init_gif_functions (library))
+        define_image_type (&gif_type);
+    }
 #endif
 
 #if HAVE_PNG
-  define_image_type (&png_type);
+  /* Ensure zlib is loaded.  Try debug version first.  */
+  if (!LoadLibrary ("zlibd.dll"))
+    LoadLibrary ("zlib.dll");
+
+  /* Try loading libpng under probable names.  */
+  if ((library = LoadLibrary ("libpng13d.dll"))
+      || (library = LoadLibrary ("libpng13.dll"))
+      || (library = LoadLibrary ("libpng12d.dll"))
+      || (library = LoadLibrary ("libpng12.dll"))
+      || (library = LoadLibrary ("libpng.dll")))
+    {
+      if (init_png_functions (library))
+       define_image_type (&png_type);
+    }
+#endif
+}
+
+void
+init_xfns ()
+{
+  image_types = NULL;
+  Vimage_types = Qnil;
+
+  define_image_type (&pbm_type);
+  define_image_type (&xbm_type);
+
+#if 0 /* TODO : Ghostscript support for W32 */
+  define_image_type (&gs_type);
 #endif
+
+  /* Image types that rely on external libraries are loaded dynamically
+     if the library is available.  */
+  init_external_image_libraries ();
 }
 
 #undef abort