(enum fringe_bitmap_type): Define here.
[bpt/emacs.git] / src / w32fns.c
index 2e0352a..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 ();
@@ -64,16 +68,6 @@ extern void w32_free_menu_strings P_ ((HWND));
 
 extern int quit_char;
 
-/* A definition of XColor for non-X frames.  */
-#ifndef HAVE_X_WINDOWS
-typedef struct {
-  unsigned long pixel;
-  unsigned short red, green, blue;
-  char flags;
-  char pad;
-} XColor;
-#endif
-
 extern char *lispy_function_keys[];
 
 /* The gray bitmap `bitmaps/gray'.  This is done because w32term.c uses
@@ -162,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;
@@ -293,10 +291,15 @@ static unsigned mouse_move_timer = 0;
 
 /* Window that is tracking the mouse.  */
 static HWND track_mouse_window;
-FARPROC track_mouse_event_fn;
+
+typedef BOOL (WINAPI * TrackMouseEvent_Proc) (
+    IN OUT LPTRACKMOUSEEVENT lpEventTrack
+    );
+
+TrackMouseEvent_Proc track_mouse_event_fn=NULL;
 
 /* W95 mousewheel handler */
-unsigned int msh_mousewheel = 0;       
+unsigned int msh_mousewheel = 0;
 
 /* Timers */
 #define MOUSE_BUTTON_ID        1
@@ -346,7 +349,7 @@ check_w32 ()
 
 /* Nonzero if we can use mouse menus.
    You should not call this unless HAVE_MENUS is defined.  */
-  
+
 int
 have_menus_p ()
 {
@@ -371,7 +374,7 @@ check_x_frame (frame)
   return f;
 }
 
-/* Let the user specify an display with a frame.
+/* Let the user specify a display with a frame.
    nil stands for the selected frame--or, if that is not a w32 frame,
    the first display on the list.  */
 
@@ -382,7 +385,7 @@ check_x_display_info (frame)
   if (NILP (frame))
     {
       struct frame *sf = XFRAME (selected_frame);
-      
+
       if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
        return FRAME_W32_DISPLAY_INFO (sf);
       else
@@ -590,7 +593,7 @@ x_create_bitmap_from_file (f, file)
   if (hinst == NULL)
       return -1;
 
-  
+
   result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
                            filename, &width, &height, &bitmap, &xhot, &yhot);
   if (result != BitmapSuccess)
@@ -863,7 +866,7 @@ x_set_frame_parameters (f, alist)
      They are independent of other properties, but other properties (e.g.,
      cursor_color) are dependent upon them.  */
   /* Process default font as well, since fringe widths depends on it.  */
-  for (p = 0; p < i; p++) 
+  for (p = 0; p < i; p++)
     {
       Lisp_Object prop, val;
 
@@ -882,7 +885,7 @@ x_set_frame_parameters (f, alist)
          if (NILP (Fequal (val, old_value)))
            {
              store_frame_param (f, prop, val);
-             
+
              param_index = Fget (prop, Qx_frame_parameter);
              if (NATNUMP (param_index)
                  && (XFASTINT (param_index)
@@ -978,7 +981,7 @@ x_set_frame_parameters (f, alist)
          position.  Resize of the frame is taken care of in the code after
          this if-statement. */
       int new_left, new_top;
-      
+
       x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
       x_fullscreen_move (f, new_top, new_left);
     }
@@ -1245,13 +1248,13 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string.  */)
 }
 
 /* The default colors for the w32 color map */
-typedef struct colormap_t 
+typedef struct colormap_t
 {
   char *name;
   COLORREF colorref;
 } colormap_t;
 
-colormap_t w32_color_map[] = 
+colormap_t w32_color_map[] =
 {
   {"snow"                      , PALETTERGB (255,250,250)},
   {"ghost white"               , PALETTERGB (248,248,255)},
@@ -1502,36 +1505,36 @@ DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
   int i;
   colormap_t *pc = w32_color_map;
   Lisp_Object cmap;
-  
+
   BLOCK_INPUT;
-  
+
   cmap = Qnil;
-  
-  for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]); 
+
+  for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
        pc++, i++)
     cmap = Fcons (Fcons (build_string (pc->name),
                         make_number (pc->colorref)),
                  cmap);
-  
+
   UNBLOCK_INPUT;
-  
+
   return (cmap);
 }
 
-Lisp_Object 
+Lisp_Object
 w32_to_x_color (rgb)
      Lisp_Object rgb;
 {
   Lisp_Object color;
-  
+
   CHECK_NUMBER (rgb);
-  
+
   BLOCK_INPUT;
-  
+
   color = Frassq (rgb, Vw32_color_map);
-  
+
   UNBLOCK_INPUT;
-  
+
   if (!NILP (color))
     return (Fcar (color));
   else
@@ -1570,7 +1573,7 @@ w32_color_map_lookup (colorname)
   return ret;
 }
 
-COLORREF 
+COLORREF
 x_to_w32_color (colorname)
      char * colorname;
 {
@@ -1584,7 +1587,7 @@ x_to_w32_color (colorname)
       char *color;
       int size;
       color = colorname + 1;
-      
+
       size = strlen(color);
       if (size == 3 || size == 6 || size == 9 || size == 12)
        {
@@ -1593,7 +1596,7 @@ x_to_w32_color (colorname)
          pos = 0;
          size /= 3;
          colorval = 0;
-         
+
          for (i = 0; i < 3; i++)
            {
              char *end;
@@ -1649,7 +1652,7 @@ x_to_w32_color (colorname)
        {
          char *end;
          unsigned long value;
-         
+
          /* The check for 'x' in the following conditional takes into
             account the fact that strtol allows a "0x" in front of
             our numbers, and we don't.  */
@@ -1712,7 +1715,7 @@ x_to_w32_color (colorname)
          if (value < 0.0 || value > 1.0)
            break;
          val = (UINT)(0x100 * value);
-         /* We used 0x100 instead of 0xFF to give an continuous
+         /* We used 0x100 instead of 0xFF to give a continuous
              range between 0.0 and 1.0 inclusive.  The next statement
              fixes the 1.0 case.  */
          if (val == 0x100)
@@ -1736,27 +1739,27 @@ x_to_w32_color (colorname)
      RGB.  */
 
   /* If we fail to lookup the color name in w32_color_map, then check the
-     colorname to see if it can be crudely approximated: If the X color 
+     colorname to see if it can be crudely approximated: If the X color
      ends in a number (e.g., "darkseagreen2"), strip the number and
      return the result of looking up the base color name.  */
   ret = w32_color_map_lookup (colorname);
-  if (NILP (ret)) 
+  if (NILP (ret))
     {
       int len = strlen (colorname);
 
-      if (isdigit (colorname[len - 1])) 
+      if (isdigit (colorname[len - 1]))
        {
          char *ptr, *approx = alloca (len + 1);
 
          strcpy (approx, colorname);
          ptr = &approx[len - 1];
-         while (ptr > approx && isdigit (*ptr)) 
+         while (ptr > approx && isdigit (*ptr))
              *ptr-- = '\0';
 
          ret = w32_color_map_lookup (approx);
        }
     }
-  
+
   UNBLOCK_INPUT;
   return ret;
 }
@@ -1911,7 +1914,7 @@ w32_defined_color (f, color, color_def, alloc)
 
   tem = x_to_w32_color (color);
 
-  if (!NILP (tem)) 
+  if (!NILP (tem))
     {
       if (f)
         {
@@ -1928,7 +1931,7 @@ w32_defined_color (f, color, color_def, alloc)
            one_w32_display_info.color_list;
          struct w32_palette_entry ** prev =
            &one_w32_display_info.color_list;
-      
+
          /* check if color is already mapped */
          while (entry)
            {
@@ -1958,13 +1961,13 @@ w32_defined_color (f, color, color_def, alloc)
       w32_color_ref = XUINT (tem) | 0x2000000;
 
       color_def->pixel = w32_color_ref;
-      color_def->red = GetRValue (w32_color_ref);
-      color_def->green = GetGValue (w32_color_ref);
-      color_def->blue = GetBValue (w32_color_ref);
+      color_def->red = GetRValue (w32_color_ref) * 256;
+      color_def->green = GetGValue (w32_color_ref) * 256;
+      color_def->blue = GetBValue (w32_color_ref) * 256;
 
       return 1;
     }
-  else 
+  else
     {
       return 0;
     }
@@ -2166,7 +2169,7 @@ x_set_mouse_color (f, arg, oldval)
   else
     hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
   x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
-  
+
   x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
   if (!EQ (Qnil, Vx_mode_pointer_shape))
     {
@@ -2198,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");
@@ -2226,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,11 +2254,12 @@ x_set_mouse_color (f, arg, oldval)
       && f->output_data.w32->modeline_cursor != 0)
     XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
   f->output_data.w32->modeline_cursor = mode_cursor;
-  
+
   if (cross_cursor != f->output_data.w32->cross_cursor
       && 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;
@@ -2279,7 +2285,7 @@ x_set_cursor_color (f, arg, oldval)
     fore_pixel = FRAME_BACKGROUND_PIXEL (f);
 
   pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-  
+
   /* Make sure that the cursor color differs from the background color.  */
   if (pixel == FRAME_BACKGROUND_PIXEL (f))
     {
@@ -2312,7 +2318,7 @@ x_set_cursor_color (f, arg, oldval)
 
 /* Set the border-color of frame F to pixel value PIX.
    Note that this does not fully take effect if done before
-   F has an window.  */
+   F has a window.  */
 void
 x_set_border_pixel (f, pix)
      struct frame *f;
@@ -2354,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
@@ -2369,7 +2374,7 @@ x_set_icon_type (f, arg, oldval)
   if (NILP (arg) && NILP (oldval))
     return;
 
-  if (STRINGP (arg) && STRINGP (oldval) 
+  if (STRINGP (arg) && STRINGP (oldval)
       && EQ (Fstring_equal (oldval, arg), Qt))
     return;
 
@@ -2474,7 +2479,7 @@ x_set_font (f, arg, oldval)
             ? x_new_fontset (f, SDATA (fontset_name))
             : x_new_font (f, SDATA (arg)));
   UNBLOCK_INPUT;
-  
+
   if (EQ (result, Qnil))
     error ("Font `%s' is not defined", SDATA (arg));
   else if (EQ (result, Qt))
@@ -2741,7 +2746,7 @@ x_set_name (f, name, explicit)
      Lisp_Object name;
      int explicit;
 {
-  /* Make sure that requests from lisp code override requests from 
+  /* Make sure that requests from lisp code override requests from
      Emacs redisplay code.  */
   if (explicit)
     {
@@ -2889,7 +2894,7 @@ x_set_vertical_scroll_bars (f, arg, oldval)
        /* Put scroll bars on the right by default, as is conventional
            on MS-Windows.  */
        EQ (Qleft, arg)
-       ? vertical_scroll_bar_left 
+       ? vertical_scroll_bar_left
        : vertical_scroll_bar_right;
 
       /* We set this parameter before creating the window for the
@@ -2930,10 +2935,10 @@ x_set_scroll_bar_width (f, arg, oldval)
     }
   change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
-  XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0; 
+  XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
 }
 \f
-/* Subroutines of creating an frame.  */
+/* Subroutines of creating a frame.  */
 
 /* Make sure that Vx_resource_name is set to a reasonable value.
    Fix it up, or set it to `emacs' if it is too hopeless.  */
@@ -3068,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)
@@ -3099,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.  */
@@ -3160,7 +3166,7 @@ w32_get_arg (alist, param, attribute, class, type)
              if (!strcmp (SDATA (tem), "on")
                  || !strcmp (SDATA (tem), "true"))
                return Qt;
-             else 
+             else
                return Qnil;
 
            case RES_TYPE_STRING:
@@ -3422,10 +3428,25 @@ 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 ();
 
-BOOL 
+BOOL
 w32_init_class (hinst)
      HINSTANCE hinst;
 {
@@ -3437,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;
@@ -3445,7 +3466,7 @@ w32_init_class (hinst)
   return (RegisterClass (&wc));
 }
 
-HWND 
+HWND
 w32_createscrollbar (f, bar)
      struct frame *f;
      struct scroll_bar * bar;
@@ -3453,7 +3474,7 @@ w32_createscrollbar (f, bar)
   return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
                        /* Position and size of scroll bar.  */
                        XINT(bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                        XINT(bar->top), 
+                        XINT(bar->top),
                        XINT(bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                         XINT(bar->height),
                        FRAME_W32_WINDOW (f),
@@ -3462,7 +3483,7 @@ w32_createscrollbar (f, bar)
                        NULL));
 }
 
-void 
+void
 w32_createwindow (f)
      struct frame *f;
 {
@@ -3472,17 +3493,17 @@ w32_createwindow (f)
   rect.left = rect.top = 0;
   rect.right = PIXEL_WIDTH (f);
   rect.bottom = PIXEL_HEIGHT (f);
-      
+
   AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
                    FRAME_EXTERNAL_MENU_BAR (f));
-  
+
   /* Do first time app init */
-  
+
   if (!hprevinst)
     {
       w32_init_class (hinst);
     }
-  
+
   FRAME_W32_WINDOW (f) = hwnd
     = CreateWindow (EMACS_CLASS,
                    f->namebuf,
@@ -3506,13 +3527,13 @@ w32_createwindow (f)
 
       /* Enable drag-n-drop.  */
       DragAcceptFiles (hwnd, TRUE);
-      
+
       /* Do this to discard the default setting specified by our parent. */
       ShowWindow (hwnd, SW_HIDE);
     }
 }
 
-void 
+void
 my_post_msg (wmsg, hwnd, msg, wParam, lParam)
      W32Msg * wmsg;
      HWND hwnd;
@@ -3609,7 +3630,7 @@ record_keyup (unsigned int wparam, unsigned int lparam)
 }
 
 /* Emacs can lose focus while a modifier key has been pressed.  When
-   it regains focus, be conservative and clear all modifiers since 
+   it regains focus, be conservative and clear all modifiers since
    we cannot reconstruct the left and right modifier state.  */
 static void
 reset_modifiers ()
@@ -3664,10 +3685,10 @@ sync_modifiers ()
   if (!modifiers_recorded)
     return;
 
-  if (!(GetKeyState (VK_CONTROL) & 0x8000)) 
+  if (!(GetKeyState (VK_CONTROL) & 0x8000))
     modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
 
-  if (!(GetKeyState (VK_MENU) & 0x8000)) 
+  if (!(GetKeyState (VK_MENU) & 0x8000))
     modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
 }
 
@@ -3877,7 +3898,7 @@ w32_msg_pump (deferred_msg * msg_buf)
   HWND focus_window;
 
   msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
-  
+
   while (GetMessage (&msg, NULL, 0, 0))
     {
       if (msg.hwnd == NULL)
@@ -4067,7 +4088,7 @@ cancel_all_deferred_msgs ()
   PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
 }
 
-DWORD 
+DWORD
 w32_msg_worker (dw)
      DWORD dw;
 {
@@ -4075,9 +4096,9 @@ w32_msg_worker (dw)
   deferred_msg dummy_buf;
 
   /* Ensure our message queue is created */
-  
+
   PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
-  
+
   if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
     abort ();
 
@@ -4156,7 +4177,7 @@ post_character_message (hwnd, msg, wParam, lParam, modifiers)
 
 /* Main window procedure */
 
-LRESULT CALLBACK 
+LRESULT CALLBACK
 w32_wnd_proc (hwnd, msg, wParam, lParam)
      HWND hwnd;
      UINT msg;
@@ -4185,7 +4206,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
      w32_clear_rect, because these functions must obtain a DC handle
      from the frame struct using get_frame_dc which is thread-aware.  */
 
-  switch (msg) 
+  switch (msg)
     {
     case WM_ERASEBKGND:
       f = x_window_to_frame (dpyinfo, hwnd);
@@ -4254,7 +4275,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
             leave_crit ();
 
             my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
-          
+
             return 0;
           }
 
@@ -4374,13 +4395,13 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
            return 0;
          break;
        case VK_MENU:
-         if (NILP (Vw32_pass_alt_to_system)) 
+         if (NILP (Vw32_pass_alt_to_system))
            /* Prevent DefWindowProc from activating the menu bar if an
                Alt key is pressed and released by itself.  */
            return 0;
          windows_translate = 1;
          break;
-       case VK_CAPITAL: 
+       case VK_CAPITAL:
          /* Decide whether to treat as modifier or function key.  */
          if (NILP (Vw32_enable_caps_lock))
            goto disable_lock_key;
@@ -4417,7 +4438,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
                                  w32_get_key_modifiers (wParam, lParam));
          windows_translate = 1;
          break;
-       case VK_CONTROL: 
+       case VK_CONTROL:
        case VK_SHIFT:
        case VK_PROCESSKEY:  /* Generated by IME.  */
          windows_translate = 1;
@@ -4475,7 +4496,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
                      int add;
                      int isdead = 0;
                      KEY_EVENT_RECORD key;
-                 
+
                      key.bKeyDown = TRUE;
                      key.wRepeatCount = 1;
                      key.wVirtualKeyCode = wParam;
@@ -4516,7 +4537,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
        }
 
       /* Fall through */
-      
+
     case WM_SYSCHAR:
     case WM_CHAR:
       post_character_message (hwnd, msg, wParam, lParam,
@@ -4652,7 +4673,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          {
            if (up) ReleaseCapture ();
            else SetCapture (hwnd);
-           button = (button == 0) ? LMOUSE : 
+           button = (button == 0) ? LMOUSE :
              ((button == 1) ? MMOUSE  : RMOUSE);
            if (up)
              button_state &= ~button;
@@ -4660,7 +4681,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
              button_state |= button;
          }
       }
-      
+
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
 
@@ -4693,7 +4714,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
          return 0;
        }
-  
+
       /* Hang onto mouse move and scroll messages for a bit, to avoid
         sending such events to Emacs faster than it can process them.
         If we get more events before the timer from the first message
@@ -4711,7 +4732,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       saved_mouse_move_msg.msg.lParam = lParam;
       saved_mouse_move_msg.msg.time = GetMessageTime ();
       saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
-  
+
       return 0;
 
     case WM_MOUSEWHEEL:
@@ -4759,7 +4780,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
            }
        }
       return 0;
-  
+
     case WM_NCACTIVATE:
       /* Windows doesn't send us focus messages when putting up and
         taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
@@ -4963,7 +4984,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          if (menu_free_timer)
            {
              KillTimer (hwnd, menu_free_timer);
-             menu_free_timer = 0;        
+             menu_free_timer = 0;
            }
        }
     case WM_MOVE:
@@ -4988,7 +5009,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
 
        wp.length = sizeof (WINDOWPLACEMENT);
        GetWindowPlacement (hwnd, &wp);
-       
+
        if (wp.showCmd != SW_SHOWMINIMIZED && (lppos->flags & SWP_NOSIZE) == 0)
          {
            RECT rect;
@@ -4999,21 +5020,21 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
            DWORD internal_border;
            DWORD scrollbar_extra;
            RECT wr;
-           
+
            wp.length = sizeof(wp);
            GetWindowRect (hwnd, &wr);
-           
+
            enter_crit ();
-           
+
            font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
            line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
            internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
            scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
-           
+
            leave_crit ();
-           
+
            memset (&rect, 0, sizeof (rect));
-           AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE), 
+           AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
                              GetMenu (hwnd) != NULL);
 
            /* Force width and height of client area to be exact
@@ -5024,17 +5045,17 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
            hdiff = (lppos->cy - (rect.bottom - rect.top)
                     - 2 * internal_border)
              % line_height;
-           
+
            if (wdiff || hdiff)
              {
-               /* For right/bottom sizing we can just fix the sizes.  
-                  However for top/left sizing we will need to fix the X 
+               /* For right/bottom sizing we can just fix the sizes.
+                  However for top/left sizing we will need to fix the X
                   and Y positions as well.  */
-               
+
                lppos->cx -= wdiff;
                lppos->cy -= hdiff;
-               
-               if (wp.showCmd != SW_SHOWMAXIMIZED 
+
+               if (wp.showCmd != SW_SHOWMAXIMIZED
                    && (lppos->flags & SWP_NOMOVE) == 0)
                  {
                    if (lppos->x != wr.left || lppos->y != wr.top)
@@ -5047,12 +5068,12 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
                        lppos->flags |= SWP_NOMOVE;
                      }
                  }
-               
+
                return 0;
              }
          }
       }
-      
+
       goto dflt;
 
     case WM_GETMINMAXINFO:
@@ -5065,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);
@@ -5130,7 +5165,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          CreateCaret (hwnd, NULL, 0,
                       w32_system_caret_height);
        }
-      
+
       if (!SetCaretPos (w32_system_caret_x, w32_system_caret_y))
        return 0;
       /* Ensure visible caret gets turned on when requested.  */
@@ -5161,7 +5196,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          flags |= TPM_LEFTBUTTON;
        else if (button_state & RMOUSE)
          flags |= TPM_RIGHTBUTTON;
-       
+
        /* Remember we did a SetCapture on the initial mouse down event,
           so for safety, we make sure the capture is cancelled now.  */
        ReleaseCapture ();
@@ -5172,8 +5207,8 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
        f = x_window_to_frame (dpyinfo, hwnd);
        if (f)
          f->output_data.w32->menubar_active = 1;
-       
-       if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y, 
+
+       if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y,
                            0, hwnd, NULL))
          {
            MSG amsg;
@@ -5206,17 +5241,17 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
          return 0;
        }
-      
+
     dflt:
       return DefWindowProc (hwnd, msg, wParam, lParam);
     }
-  
+
 
   /* The most common default return code for handled messages is 0.  */
   return 0;
 }
 
-void 
+void
 my_create_window (f)
      struct frame * f;
 {
@@ -5232,7 +5267,7 @@ my_create_window (f)
    indirectly via the Window thread, as we do not need to process Window
    messages for the tooltip.  Creating tooltips indirectly also creates
    deadlocks when tooltips are created for menu items.  */
-void 
+void
 my_create_tip_window (f)
      struct frame *f;
 {
@@ -5289,7 +5324,7 @@ w32_window (f, window_prompting, minibuffer_only)
      for the window manager, so GC relocation won't bother it.
 
      Elsewhere we specify the window name for the window manager.  */
-     
+
   {
     char *str = (char *) SDATA (Vx_resource_name);
     f->namebuf = (char *) xmalloc (strlen (str) + 1);
@@ -5413,7 +5448,7 @@ unwind_create_frame (frame)
 #ifdef GLYPH_DEBUG
       struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 #endif
-      
+
       x_free_frame_resources (f);
 
       /* Check that reference counts are indeed correct.  */
@@ -5422,7 +5457,7 @@ unwind_create_frame (frame)
 
       return Qt;
     }
-  
+
   return Qnil;
 }
 
@@ -5586,7 +5621,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
     if (! STRINGP (font))
       font = build_string ("Fixedsys");
 
-    x_default_parameter (f, parms, Qfont, font, 
+    x_default_parameter (f, parms, Qfont, font,
                         "font", "Font", RES_TYPE_STRING);
   }
 
@@ -5639,7 +5674,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
      end up in init_iterator with a null face cache, which should not
      happen.  */
   init_frame_faces (f);
-  
+
   x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
                       "menuBar", "MenuBar", RES_TYPE_NUMBER);
   x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
@@ -5655,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
@@ -5664,7 +5707,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   if (FRAME_TOOL_BAR_LINES (f))
     {
       int margin, relief, bar_height;
-      
+
       relief = (tool_bar_button_relief >= 0
                ? tool_bar_button_relief
                : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
@@ -5678,7 +5721,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
        margin = XFASTINT (XCDR (Vtool_bar_button_margin));
       else
        margin = 0;
-         
+
       bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
       f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
     }
@@ -5776,11 +5819,11 @@ This function is an internal primitive--use `make-frame' instead.  */)
        ;
     }
   UNGCPRO;
-  
+
   /* Make sure windows on this frame appear in calls to next-window
      and similar functions.  */
   Vwindow_list = Qnil;
-  
+
   return unbind_to (count, frame);
 }
 
@@ -5903,9 +5946,7 @@ w32_load_system_font (f,fontname,size)
            ended up with. */
       return NULL;
 
-    /* Specify anti-aliasing to prevent Cleartype fonts being used,
-       since those fonts leave garbage behind.  */
-    lf.lfQuality = ANTIALIASED_QUALITY;
+    lf.lfQuality = DEFAULT_QUALITY;
 
     font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
     bzero (font, sizeof (*font));
@@ -5917,11 +5958,11 @@ w32_load_system_font (f,fontname,size)
 
     font->hfont = CreateFontIndirect (&lf);
 
-    if (font->hfont == NULL) 
+    if (font->hfont == NULL)
       {
        ok = FALSE;
-      } 
-    else 
+      }
+    else
       {
        HDC hdc;
        HANDLE oldobj;
@@ -6090,12 +6131,12 @@ int size;
 }
 
 
-void 
+void
 w32_unload_font (dpyinfo, font)
      struct w32_display_info *dpyinfo;
      XFontStruct * font;
 {
-  if (font) 
+  if (font)
     {
       if (font->per_char) xfree (font->per_char);
       if (font->bdf) w32_free_bdf_font (font->bdf);
@@ -6128,7 +6169,7 @@ w32_unload_font (dpyinfo, font)
  *      )
  */
 
-static LONG 
+static LONG
 x_to_w32_weight (lpw)
      char * lpw;
 {
@@ -6149,7 +6190,7 @@ x_to_w32_weight (lpw)
 }
 
 
-static char * 
+static char *
 w32_to_x_weight (fnweight)
      int fnweight;
 {
@@ -6336,7 +6377,7 @@ w32_to_x_charset (fncharset)
       sprintf (buf, "*-#%u", fncharset);
       return buf;
     }
-  
+
   {
     Lisp_Object rest;
     char * best_match = NULL;
@@ -6390,7 +6431,7 @@ w32_to_x_charset (fncharset)
                 int this_enc = atoi (x_charset + 8);
                 if (this_enc > 0 && this_enc < best_enc)
                   best_match = x_charset;
-              }                
+              }
           }
       }
 
@@ -6497,7 +6538,7 @@ w32_to_all_x_charsets (fncharset)
       sprintf (buf, "*-#%u", fncharset);
       return Fcons (build_string (buf), Qnil);
     }
-  
+
   {
     Lisp_Object rest;
     /* Look through w32-charset-info-alist for the character set.
@@ -6548,7 +6589,7 @@ w32_to_all_x_charsets (fncharset)
 /* Get the Windows codepage corresponding to the specified font.  The
    charset info in the font name is used to look up
    w32-charset-to-codepage-alist.  */
-int 
+int
 w32_codepage_for_font (char *fontname)
 {
   Lisp_Object codepage, entry;
@@ -6599,7 +6640,7 @@ w32_codepage_for_font (char *fontname)
 }
 
 
-static BOOL 
+static BOOL
 w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
      LOGFONT * lplogfont;
      char * lpxstr;
@@ -6682,7 +6723,7 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
              ? 'p' : 'c',                            /* spacing */
             width_pixels,                           /* avg width */
             specific_charset ? specific_charset
-             : w32_to_x_charset (lplogfont->lfCharSet) 
+             : w32_to_x_charset (lplogfont->lfCharSet)
              /* charset registry and encoding */
             );
 
@@ -6690,7 +6731,7 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
   return (TRUE);
 }
 
-static BOOL 
+static BOOL
 x_to_w32_font (lpxstr, lplogfont)
      char * lpxstr;
      LOGFONT * lplogfont;
@@ -6725,7 +6766,7 @@ x_to_w32_font (lpxstr, lplogfont)
    * format:
    *   "<font name>[:height in pixels[:width in pixels[:weight]]]"
    */
-  
+
   if (*lpxstr == '-')
     {
       int fields, tem;
@@ -6993,7 +7034,7 @@ xlfd_strip_height (char *fontname)
 }
 
 /* Assume parameter 1 is fully qualified, no wildcards. */
-static BOOL 
+static BOOL
 w32_font_match (fontname, pattern)
     char * fontname;
     char * pattern;
@@ -7055,7 +7096,7 @@ w32_font_match (fontname, pattern)
    font from each family, the second pass lists all the fonts from
    each family.  */
 
-typedef struct enumfont_t 
+typedef struct enumfont_t
 {
   HDC hdc;
   int numFonts;
@@ -7070,7 +7111,7 @@ static void
 enum_font_maybe_add_to_list (enumfont_t *, LOGFONT *, char *, Lisp_Object);
 
 
-static int CALLBACK 
+static int CALLBACK
 enum_font_cb2 (lplf, lptm, FontType, lpef)
     ENUMLOGFONT * lplf;
     NEWTEXTMETRIC * lptm;
@@ -7226,7 +7267,7 @@ enum_font_maybe_add_to_list (lpef, logfont, match_charset, width)
 }
 
 
-static int CALLBACK 
+static int CALLBACK
 enum_font_cb1 (lplf, lptm, FontType, lpef)
      ENUMLOGFONT * lplf;
      NEWTEXTMETRIC * lptm;
@@ -7300,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;
         }
     }
@@ -7314,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)
@@ -7413,7 +7455,7 @@ w32_list_fonts (f, pattern, size, maxnames)
 
       newlist = second_best = Qnil;
 
-      /* Make a list of the fonts that have the right width.  */          
+      /* Make a list of the fonts that have the right width.  */
       for (; CONSP (list); list = XCDR (list))
         {
           int found_size;
@@ -7427,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;
@@ -7466,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
@@ -7475,7 +7517,7 @@ w32_list_fonts (f, pattern, size, maxnames)
             {
               if (NILP (second_best))
                 second_best = tem;
-                  
+
               else if (found_size < size)
                 {
                   if (XINT (XCDR (second_best)) > size
@@ -7502,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);
@@ -7761,9 +7803,9 @@ If omitted or nil, that stands for the selected frame's display.  */)
      and because probably is more meaningful on Windows anyway */
   if (cap < 0)
     cap = 1 << min(dpyinfo->n_planes * dpyinfo->n_cbits, 24);
-  
+
   ReleaseDC (dpyinfo->root_window, hdc);
-  
+
   return make_number (cap);
 }
 
@@ -7835,11 +7877,11 @@ If omitted or nil, that stands for the selected frame's display.  */)
   int cap;
 
   hdc = GetDC (dpyinfo->root_window);
-  
+
   cap = GetDeviceCaps (hdc, VERTSIZE);
-  
+
   ReleaseDC (dpyinfo->root_window, hdc);
-  
+
   return make_number (cap);
 }
 
@@ -7857,11 +7899,11 @@ If omitted or nil, that stands for the selected frame's display.  */)
   int cap;
 
   hdc = GetDC (dpyinfo->root_window);
-  
+
   cap = GetDeviceCaps (hdc, HORZSIZE);
-  
+
   ReleaseDC (dpyinfo->root_window, hdc);
-  
+
   return make_number (cap);
 }
 
@@ -8226,7 +8268,7 @@ valid_image_p (object)
      Lisp_Object object;
 {
   int valid_p = 0;
-  
+
   if (CONSP (object) && EQ (XCAR (object), Qimage))
     {
       Lisp_Object tem;
@@ -8361,7 +8403,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
         was found more than once, it's an error.  */
       keywords[i].value = value;
       ++keywords[i].count;
-      
+
       if (keywords[i].count > 1)
        return 0;
 
@@ -8416,7 +8458,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
 
        case IMAGE_FUNCTION_VALUE:
          value = indirect_function (value);
-         if (SUBRP (value) 
+         if (SUBRP (value)
              || COMPILEDP (value)
              || (CONSP (value) && EQ (XCAR (value), Qlambda)))
            break;
@@ -8465,7 +8507,7 @@ image_spec_value (spec, key, found)
      int *found;
 {
   Lisp_Object tail;
-  
+
   xassert (valid_image_p (spec));
 
   for (tail = XCDR (spec);
@@ -8479,12 +8521,12 @@ image_spec_value (spec, key, found)
          return XCAR (XCDR (tail));
        }
     }
-  
+
   if (found)
     *found = 0;
   return Qnil;
 }
-     
+
 
 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
        doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
@@ -8505,7 +8547,7 @@ or omitted means use the selected frame.  */)
       struct image *img = IMAGE_FROM_ID (f, id);
       int width = img->width + 2 * img->hmargin;
       int height = img->height + 2 * img->vmargin;
-  
+
       if (NILP (pixels))
        size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
                      make_float ((double) height / CANON_Y_UNIT (f)));
@@ -8550,6 +8592,7 @@ or omitted means use the selected frame.  */)
 
 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
 static void free_image P_ ((struct frame *f, struct image *img));
+static void x_destroy_x_image P_ ((XImage *));
 
 
 /* Allocate and return a new image structure for image specification
@@ -8561,7 +8604,7 @@ make_image (spec, hash)
      unsigned hash;
 {
   struct image *img = (struct image *) xmalloc (sizeof *img);
-  
+
   xassert (valid_image_p (spec));
   bzero (img, sizeof *img);
   img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
@@ -8622,7 +8665,7 @@ prepare_image_for_display (f, img)
   if (img->pixmap == 0 && !img->load_failed_p)
     img->load_failed_p = img->type->load (f, img) == 0;
 }
-     
+
 
 /* Value is the number of pixels for the ascent of image IMG when
    drawn in face FACE.  */
@@ -8656,24 +8699,24 @@ image_ascent (img, face)
 /* Find the "best" corner color of a bitmap.  XIMG is assumed to a device
    context with the bitmap selected.  */
 static COLORREF
-four_corners_best (ximg, width, height)
-     HDC ximg;
+four_corners_best (img_dc, width, height)
+     HDC img_dc;
      unsigned long width, height;
 {
   COLORREF corners[4], best;
   int i, best_count;
 
-  /* Get the colors at the corners of ximg.  */
-  corners[0] = GetPixel (ximg, 0, 0);
-  corners[1] = GetPixel (ximg, width - 1, 0);
-  corners[2] = GetPixel (ximg, width - 1, height - 1);
-  corners[3] = GetPixel (ximg, 0, height - 1);
+  /* Get the colors at the corners of img_dc.  */
+  corners[0] = GetPixel (img_dc, 0, 0);
+  corners[1] = GetPixel (img_dc, width - 1, 0);
+  corners[2] = GetPixel (img_dc, width - 1, height - 1);
+  corners[3] = GetPixel (img_dc, 0, height - 1);
 
   /* Choose the most frequently found color as background.  */
   for (i = best_count = 0; i < 4; ++i)
     {
       int j, n;
-         
+
       for (j = n = 0; j < 4; ++j)
        if (corners[i] == corners[j])
          ++n;
@@ -8686,32 +8729,39 @@ four_corners_best (ximg, width, height)
 }
 
 /* Return the `background' field of IMG.  If IMG doesn't have one yet,
-   it is guessed heuristically.  If non-zero, XIMG is an existing XImage
-   object to use for the heuristic.  */
+   it is guessed heuristically.  If non-zero, IMG_DC is an existing
+   device context with the image selected to use for the heuristic.  */
 
 unsigned long
-image_background (img, f, ximg)
+image_background (img, f, img_dc)
      struct image *img;
      struct frame *f;
-     XImage *ximg;
+     HDC img_dc;
 {
   if (! img->background_valid)
     /* IMG doesn't have a background yet, try to guess a reasonable value.  */
     {
-#if 0 /* TODO: Image support.  */
-      int free_ximg = !ximg;
+      int free_ximg = !img_dc;
+      HGDIOBJ prev;
 
-      if (! ximg)
-       ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
-                         0, 0, img->width, img->height, ~0, ZPixmap);
+      if (free_ximg)
+       {
+         HDC frame_dc = get_frame_dc (f);
+         img_dc = CreateCompatibleDC (frame_dc);
+         release_frame_dc (f, frame_dc);
+
+         prev = SelectObject (img_dc, img->pixmap);
+       }
 
-      img->background = four_corners_best (ximg, img->width, img->height);
+      img->background = four_corners_best (img_dc, img->width, img->height);
 
       if (free_ximg)
-       XDestroyImage (ximg);
+       {
+         SelectObject (img_dc, prev);
+         DeleteDC (img_dc);
+       }
 
       img->background_valid = 1;
-#endif
     }
 
   return img->background;
@@ -8725,28 +8775,35 @@ int
 image_background_transparent (img, f, mask)
      struct image *img;
      struct frame *f;
-     XImage *mask;
+     HDC mask;
 {
   if (! img->background_transparent_valid)
     /* IMG doesn't have a background yet, try to guess a reasonable value.  */
     {
-#if 0 /* TODO: Image support.  */
       if (img->mask)
        {
          int free_mask = !mask;
+         HGDIOBJ prev;
+
+         if (free_mask)
+           {
+             HDC frame_dc = get_frame_dc (f);
+             mask = CreateCompatibleDC (frame_dc);
+             release_frame_dc (f, frame_dc);
 
-         if (! mask)
-           mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
-                             0, 0, img->width, img->height, ~0, ZPixmap);
+             prev = SelectObject (mask, img->mask);
+           }
 
          img->background_transparent
            = !four_corners_best (mask, img->width, img->height);
 
          if (free_mask)
-           XDestroyImage (mask);
+           {
+             SelectObject (mask, prev);
+             DeleteDC (mask);
+           }
        }
       else
-#endif
        img->background_transparent = 0;
 
       img->background_transparent_valid = 1;
@@ -8793,7 +8850,7 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
       img->mask = NULL;
       img->background_transparent_valid = 0;
     }
-      
+
   if (colors_p && img->ncolors)
     {
 #if 0  /* TODO: color table support.  */
@@ -8825,7 +8882,7 @@ x_clear_image (f, img)
 #if 0 /* TODO: color table support  */
 
       int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
-      
+
       /* If display has an immutable color map, freeing colors is not
         necessary and some servers don't allow it.  So don't do it.  */
       if (class != StaticColor
@@ -8840,7 +8897,7 @@ x_clear_image (f, img)
          UNBLOCK_INPUT;
        }
 #endif
-      
+
       xfree (img->colors);
       img->colors = NULL;
       img->ncolors = 0;
@@ -8889,6 +8946,7 @@ x_alloc_image_color (f, img, color_name, dflt)
 
 static void cache_image P_ ((struct frame *f, struct image *img));
 static void postprocess_image P_ ((struct frame *, struct image *));
+static void x_disable_image P_ ((struct frame *, struct image *));
 
 
 /* Return a new, initialized image cache that is allocated from the
@@ -8899,7 +8957,7 @@ make_image_cache ()
 {
   struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
   int size;
-  
+
   bzero (c, sizeof *c);
   c->size = 50;
   c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
@@ -8924,7 +8982,7 @@ free_image_cache (f)
 
       /* Cache should not be referenced by any frame when freed.  */
       xassert (c->refcount == 0);
-      
+
       for (i = 0; i < c->used; ++i)
        free_image (f, c->images[i]);
       xfree (c->images);
@@ -8957,11 +9015,11 @@ clear_image_cache (f, force_p)
 
       EMACS_GET_TIME (t);
       old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
-      
+
       /* Block input so that we won't be interrupted by a SIGIO
         while being in an inconsistent state.  */
       BLOCK_INPUT;
-      
+
       for (i = nfreed = 0; i < c->used; ++i)
        {
          struct image *img = c->images[i];
@@ -8980,7 +9038,7 @@ clear_image_cache (f, force_p)
       if (nfreed)
        {
          Lisp_Object tail, frame;
-         
+
          FOR_EACH_FRAME (tail, frame)
            {
              struct frame *f = XFRAME (frame);
@@ -9008,7 +9066,7 @@ FRAME t means clear the image caches of all frames.  */)
   if (EQ (frame, Qt))
     {
       Lisp_Object tail;
-      
+
       FOR_EACH_FRAME (tail, frame)
        if (FRAME_W32_P (XFRAME (frame)))
          clear_image_cache (XFRAME (frame), 1);
@@ -9028,7 +9086,6 @@ postprocess_image (f, img)
      struct frame *f;
      struct image *img;
 {
-#if 0  /* TODO: image support.  */
   /* Manipulation of the image's mask.  */
   if (img->pixmap)
     {
@@ -9036,7 +9093,7 @@ postprocess_image (f, img)
       Lisp_Object mask;
 
       spec = img->spec;
-      
+
       /* `:heuristic-mask t'
         `:mask heuristic'
         means build a mask heuristically.
@@ -9046,16 +9103,16 @@ postprocess_image (f, img)
         image.
         `:mask nil'
         means remove a mask, if any.  */
-             
+
       mask = image_spec_value (spec, QCheuristic_mask, NULL);
       if (!NILP (mask))
        x_build_heuristic_mask (f, img, mask);
       else
        {
          int found_p;
-                   
+
          mask = image_spec_value (spec, QCmask, &found_p);
-                 
+
          if (EQ (mask, Qheuristic))
            x_build_heuristic_mask (f, img, Qt);
          else if (CONSP (mask)
@@ -9072,8 +9129,8 @@ postprocess_image (f, img)
              img->mask = NULL;
            }
        }
-         
+
+
       /* Should we apply an image transformation algorithm?  */
       conversion = image_spec_value (spec, QCconversion, NULL);
       if (EQ (conversion, Qdisabled))
@@ -9093,7 +9150,6 @@ postprocess_image (f, img)
                              Fplist_get (tem, QCcolor_adjustment));
        }
     }
-#endif
 }
 
 
@@ -9116,7 +9172,7 @@ lookup_image (f, spec)
      specification.  */
   xassert (FRAME_WINDOW_P (f));
   xassert (valid_image_p (spec));
-  
+
   GCPRO1 (spec);
 
   /* Look up SPEC in the hash table of the image cache.  */
@@ -9154,7 +9210,7 @@ lookup_image (f, spec)
       else
        {
          /* Handle image type independent image attributes
-            `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF',
+            `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
             `:background COLOR'.  */
          Lisp_Object ascent, margin, relief, bg;
 
@@ -9175,7 +9231,7 @@ lookup_image (f, spec)
              if (XINT (XCDR (margin)) > 0)
                img->vmargin = XFASTINT (XCDR (margin));
            }
-         
+
          relief = image_spec_value (spec, QCrelief, NULL);
          if (INTEGERP (relief))
            {
@@ -9209,9 +9265,9 @@ lookup_image (f, spec)
   /* We're using IMG, so set its timestamp to `now'.  */
   EMACS_GET_TIME (now);
   img->timestamp = EMACS_SECS (now);
-  
+
   UNGCPRO;
-  
+
   /* Value is the image id.  */
   return img->id;
 }
@@ -9283,9 +9339,17 @@ 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_destroy_x_image P_ ((XImage *));
 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
 
 
@@ -9348,11 +9412,25 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
   header->biCompression = BI_RGB;
   header->biClrUsed = palette_colors;
 
+  /* TODO: fill in palette.  */
+  if (depth == 1)
+    {
+      (*ximg)->info.bmiColors[0].rgbBlue = 0;
+      (*ximg)->info.bmiColors[0].rgbGreen = 0;
+      (*ximg)->info.bmiColors[0].rgbRed = 0;
+      (*ximg)->info.bmiColors[0].rgbReserved = 0;
+      (*ximg)->info.bmiColors[1].rgbBlue = 255;
+      (*ximg)->info.bmiColors[1].rgbGreen = 255;
+      (*ximg)->info.bmiColors[1].rgbRed = 255;
+      (*ximg)->info.bmiColors[1].rgbReserved = 0;
+    }
+
   hdc = get_frame_dc (f);
 
   /* Create a DIBSection and raster array for the bitmap,
      and store its handle in *pixmap.  */
-  *pixmap = CreateDIBSection (hdc, &((*ximg)->info), DIB_RGB_COLORS,
+  *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
+                             (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
                              &((*ximg)->data), NULL, 0);
 
   /* Realize display palette and garbage all frames. */
@@ -9397,15 +9475,12 @@ x_put_x_image (f, ximg, pixmap, width, height)
      struct frame *f;
      XImage *ximg;
      Pixmap pixmap;
+     int width, height;
 {
-
-#if TODO  /* W32 specific image code.  */
-  GC gc;
-
-  xassert (interrupt_input_blocked);
-  gc = XCreateGC (NULL, pixmap, 0, NULL);
-  XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
-  XFreeGC (NULL, gc);
+#if 0  /* I don't think this is necessary looking at where it is used.  */
+  HDC hdc = get_frame_dc (f);
+  SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
+  release_frame_dc (f, hdc);
 #endif
 }
 
@@ -9436,7 +9511,7 @@ x_find_image_file (file)
 
   /* Try to find FILE in data-directory, then x-bitmap-file-path.  */
   fd = openp (search_path, file, Qnil, &file_found, Qnil);
-  
+
   if (fd == -1)
     file_found = Qnil;
   else
@@ -9478,7 +9553,7 @@ slurp_file (file, size)
          buf = NULL;
        }
     }
-  
+
   return buf;
 }
 
@@ -9557,7 +9632,7 @@ enum xbm_token
   XBM_TK_NUMBER
 };
 
-  
+
 /* Return non-zero if OBJECT is a valid XBM-type image specification.
    A valid specification is a list starting with the symbol `image'
    The rest of the list is a property list which must contain an
@@ -9592,7 +9667,7 @@ xbm_image_p (object)
      Lisp_Object object;
 {
   struct image_keyword kw[XBM_LAST];
-  
+
   bcopy (xbm_format, kw, sizeof kw);
   if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
     return 0;
@@ -9624,13 +9699,13 @@ xbm_image_p (object)
       data = kw[XBM_DATA].value;
       width = XFASTINT (kw[XBM_WIDTH].value);
       height = XFASTINT (kw[XBM_HEIGHT].value);
-      
+
       /* Check type of data, and width and height against contents of
         data.  */
       if (VECTORP (data))
        {
          int i;
-         
+
          /* Number of elements of the vector must be >= height.  */
          if (XVECTOR (data)->size < height)
            return 0;
@@ -9700,7 +9775,7 @@ xbm_scan (s, end, sval, ival)
   else if (isdigit (c))
     {
       int value = 0, digit;
-      
+
       if (c == '0' && *s < end)
        {
          c = *(*s)++;
@@ -9794,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++)
     {
@@ -9803,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;
 }
@@ -9838,7 +9912,7 @@ xbm_read_bitmap_data (contents, end, width, height, data)
      if (LA1 != (TOKEN))       \
        goto failure;           \
      else                      \
-       match ()        
+       match ()
 
 #define expect_ident(IDENT)                                    \
      if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
@@ -9881,7 +9955,7 @@ xbm_read_bitmap_data (contents, end, width, height, data)
     {
       if (strcmp (buffer, "unsigned") == 0)
        {
-         match (); 
+         match ();
          expect_ident ("char");
        }
       else if (strcmp (buffer, "short") == 0)
@@ -9896,7 +9970,7 @@ xbm_read_bitmap_data (contents, end, width, height, data)
       else
        goto failure;
     }
-  else 
+  else
     goto failure;
 
   expect (XBM_TK_IDENT);
@@ -9916,10 +9990,10 @@ xbm_read_bitmap_data (contents, end, width, height, data)
          int val = value;
          expect (XBM_TK_NUMBER);
 
-         *p++ = val;
+         *p++ = val;
          if (!padding_p || ((i + 2) % bytes_per_line))
-           *p++ = value >> 8;
-         
+           *p++ = ~ (value >> 8);
+
          if (LA1 == ',' || LA1 == '}')
            match ();
          else
@@ -9932,8 +10006,8 @@ xbm_read_bitmap_data (contents, end, width, height, data)
        {
          int val = value;
          expect (XBM_TK_NUMBER);
-         
-         *p++ = val;
+
+         *p++ = val;
 
          if (LA1 == ',' || LA1 == '}')
            match ();
@@ -9959,6 +10033,38 @@ xbm_read_bitmap_data (contents, end, width, height, data)
 #undef expect_ident
 }
 
+static void convert_mono_to_color_image (f, img, foreground, background)
+     struct frame *f;
+     struct image *img;
+     COLORREF foreground, background;
+{
+  HDC hdc, old_img_dc, new_img_dc;
+  HGDIOBJ old_prev, new_prev;
+  HBITMAP new_pixmap;
+
+  hdc = get_frame_dc (f);
+  old_img_dc = CreateCompatibleDC (hdc);
+  new_img_dc = CreateCompatibleDC (hdc);
+  new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
+  release_frame_dc (f, hdc);
+  old_prev = SelectObject (old_img_dc, img->pixmap);
+  new_prev = SelectObject (new_img_dc, new_pixmap);
+  SetTextColor (new_img_dc, foreground);
+  SetBkColor (new_img_dc, background);
+
+  BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
+         0, 0, SRCCOPY);
+
+  SelectObject (old_img_dc, old_prev);
+  SelectObject (new_img_dc, new_prev);
+  DeleteDC (old_img_dc);
+  DeleteDC (new_img_dc);
+  DeleteObject (img->pixmap);
+  if (new_pixmap == 0)
+    fprintf (stderr, "Failed to convert image to color.\n");
+  else
+    img->pixmap = new_pixmap;
+}
 
 /* Load XBM image IMG which will be displayed on frame F from buffer
    CONTENTS.  END is the end of the buffer. Value is non-zero if
@@ -9973,30 +10079,39 @@ xbm_load_image (f, img, contents, end)
   int rc;
   unsigned char *data;
   int success_p = 0;
-  
+
   rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
   if (rc)
     {
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
+      int non_default_colors = 0;
       Lisp_Object value;
-      
+
       xassert (img->width > 0 && img->height > 0);
 
       /* Get foreground and background colors, maybe allocate colors.  */
       value = image_spec_value (img->spec, QCforeground, NULL);
       if (!NILP (value))
-       foreground = x_alloc_image_color (f, img, value, foreground);
+       {
+         foreground = x_alloc_image_color (f, img, value, foreground);
+         non_default_colors = 1;
+       }
       value = image_spec_value (img->spec, QCbackground, NULL);
       if (!NILP (value))
        {
          background = x_alloc_image_color (f, img, value, background);
          img->background = background;
          img->background_valid = 1;
+         non_default_colors = 1;
        }
       img->pixmap
        = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
 
+      /* If colors were specified, transfer the bitmap to a color one.  */
+      if (non_default_colors)
+       convert_mono_to_color_image (f, img, foreground, background);
+
       xfree (data);
 
       if (img->pixmap == 0)
@@ -10028,7 +10143,7 @@ xbm_file_p (data)
                                   &w, &h, NULL));
 }
 
-    
+
 /* Fill image IMG which is used on frame F with pixmap data.  Value is
    non-zero if successful.  */
 
@@ -10075,9 +10190,9 @@ xbm_load (f, img)
     {
       struct image_keyword fmt[XBM_LAST];
       Lisp_Object data;
-      int depth;
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
+      int non_default_colors = 0;
       char *bits;
       int parsed_p;
       int in_memory_file_p = 0;
@@ -10102,12 +10217,19 @@ xbm_load (f, img)
       /* Get foreground and background colors, maybe allocate colors.  */
       if (fmt[XBM_FOREGROUND].count
          && STRINGP (fmt[XBM_FOREGROUND].value))
-       foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
-                                         foreground);
+       {
+         foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
+                                           foreground);
+         non_default_colors = 1;
+       }
+
       if (fmt[XBM_BACKGROUND].count
          && STRINGP (fmt[XBM_BACKGROUND].value))
-       background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
-                                         background);
+       {
+         background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
+                                           background);
+         non_default_colors = 1;
+       }
 
       if (in_memory_file_p)
        success_p = xbm_load_image (f, img, SDATA (data),
@@ -10120,7 +10242,7 @@ xbm_load (f, img)
              int i;
              char *p;
              int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
-         
+
              p = bits = (char *) alloca (nbytes * img->height);
              for (i = 0; i < img->height; ++i, p += nbytes)
                {
@@ -10137,11 +10259,14 @@ xbm_load (f, img)
            bits = XBOOL_VECTOR (data)->data;
 
          /* Create the pixmap.  */
-         depth = one_w32_display_info.n_cbits;
          img->pixmap
            = w32_create_pixmap_from_bitmap_data (img->width, img->height,
                                                  bits);
 
+         /* If colors were specified, transfer the bitmap to a color one.  */
+         if (non_default_colors)
+           convert_mono_to_color_image (f, img, foreground, background);
+
          if (img->pixmap)
            success_p = 1;
          else
@@ -10155,20 +10280,30 @@ xbm_load (f, img)
 
   return success_p;
 }
-  
+
 
 \f
 /***********************************************************************
                              XPM images
  ***********************************************************************/
 
-#if HAVE_XPM 
+#if HAVE_XPM
 
 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.  */
 
@@ -10200,7 +10335,7 @@ static struct image_keyword xpm_format[XPM_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -10210,7 +10345,7 @@ static struct image_keyword xpm_format[XPM_LAST] =
   {":background",       IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
-/* Structure describing the image type XBM.  */
+/* Structure describing the image type XPM.  */
 
 static struct image_type xpm_type =
 {
@@ -10222,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.  */
@@ -10258,9 +10413,7 @@ xpm_image_p (object)
          /* Either no `:color-symbols' or it's a list of conses
             whose car and cdr are strings.  */
          && (fmt[XPM_COLOR_SYMBOLS].count == 0
-             || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
-         && (fmt[XPM_ASCENT].count == 0
-             || XFASTINT (fmt[XPM_ASCENT].value) < 100));
+             || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
 }
 
 
@@ -10272,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;
@@ -10300,7 +10459,7 @@ xpm_load (f, img)
       Lisp_Object tail;
       XpmColorSymbol *xpm_syms;
       int i, size;
-      
+
       attrs.valuemask |= XpmColorSymbols;
 
       /* Count number of symbols.  */
@@ -10330,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
@@ -10370,30 +10566,30 @@ 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:
          image_error ("Error opening XPM file (%s)", img->spec, Qnil);
          break;
-         
+
        case XpmFileInvalid:
          image_error ("Invalid XPM file (%s)", img->spec, Qnil);
          break;
-         
+
        case XpmNoMemory:
          image_error ("Out of memory (%s)", img->spec, Qnil);
          break;
-         
+
        case XpmColorFailed:
          image_error ("Color allocation error (%s)", img->spec, Qnil);
          break;
-         
+
        default:
          image_error ("Unknown error (%s)", img->spec, Qnil);
          break;
@@ -10542,7 +10738,7 @@ lookup_pixel_color (f, pixel)
       int rc;
 
       BLOCK_INPUT;
-      
+
       cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
       color.pixel = pixel;
       XQueryColor (NULL, cmap, &color);
@@ -10552,7 +10748,7 @@ lookup_pixel_color (f, pixel)
       if (rc)
        {
          ++ct_colors_allocated;
-      
+
          p = (struct ct_color *) xmalloc (sizeof *p);
          p->r = color.red;
          p->g = color.green;
@@ -10589,7 +10785,7 @@ colors_in_color_table (n)
       colors = (unsigned long *) xmalloc (ct_colors_allocated
                                          * sizeof *colors);
       *n = ct_colors_allocated;
-      
+
       for (i = j = 0; i < CT_SIZE; ++i)
        for (p = ct_table[i]; p; p = p->next)
          colors[j++] = p->pixel;
@@ -10651,13 +10847,16 @@ x_to_xcolors (f, img, rgb_p)
 {
   int x, y;
   XColor *colors, *p;
-  XImage *ximg;
+  HDC hdc, bmpdc;
+  HGDIOBJ prev;
 
   colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
-#if 0 /* TODO: implement image colors.  */
-  /* Get the X image IMG->pixmap.  */
-  ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
-                   0, 0, img->width, img->height, ~0, ZPixmap);
+
+  /* Load the image into a memory device context.  */
+  hdc = get_frame_dc (f);
+  bmpdc = CreateCompatibleDC (hdc);
+  release_frame_dc (f, hdc);
+  prev = SelectObject (bmpdc, img->pixmap);
 
   /* Fill the `pixel' members of the XColor array.  I wished there
      were an easy and portable way to circumvent XGetPixel.  */
@@ -10665,16 +10864,24 @@ x_to_xcolors (f, img, rgb_p)
   for (y = 0; y < img->height; ++y)
     {
       XColor *row = p;
-      
+
       for (x = 0; x < img->width; ++x, ++p)
-       p->pixel = XGetPixel (ximg, x, y);
+       {
+         /* TODO: palette support needed here?  */
+         p->pixel = GetPixel (bmpdc, x, y);
 
-      if (rgb_p)
-       x_query_colors (f, row, img->width);
+         if (rgb_p)
+           {
+             p->red = 256 * GetRValue (p->pixel);
+             p->green = 256 * GetGValue (p->pixel);
+             p->blue = 256 * GetBValue (p->pixel);
+           }
+       }
     }
 
-  XDestroyImage (ximg);
-#endif
+  SelectObject (bmpdc, prev);
+  DeleteDC (bmpdc);
+
   return colors;
 }
 
@@ -10689,23 +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;
-  *pixel = 255 - GetRValue (color);
-  *(pixel + 1) = 255 - GetGValue (color);
-  *(pixel + 2) = 255 - GetBValue (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.  */
@@ -10733,7 +10957,7 @@ x_from_xcolors (f, img, colors)
 #if 0  /* TODO: color tables.  */
        pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
 #else
-       pixel = PALETTERGB (p->red, p->green, p->blue);
+       pixel = PALETTERGB (p->red / 256, p->green / 256, p->blue / 256);
 #endif
        XPutPixel (oimg, x, y, pixel);
       }
@@ -10755,7 +10979,7 @@ x_from_xcolors (f, img, colors)
 
    MATRIX is a nine-element array specifying the transformation
    matrix.  See emboss_matrix for an example.
-   
+
    COLOR_ADJUST is a color adjustment added to each pixel of the
    outgoing image.  */
 
@@ -10783,7 +11007,7 @@ x_detect_edges (f, img, matrix, color_adjust)
       p = COLOR (new, img->width - 1, y);
       p->red = p->green = p->blue = 0xffff/2;
     }
-  
+
   for (x = 1; x < img->width - 1; ++x)
     {
       p = COLOR (new, x, 0);
@@ -10795,7 +11019,7 @@ x_detect_edges (f, img, matrix, color_adjust)
   for (y = 1; y < img->height - 1; ++y)
     {
       p = COLOR (new, 1, y);
-      
+
       for (x = 1; x < img->width - 1; ++x, ++p)
        {
          int r, g, b, y1, x1;
@@ -10869,7 +11093,7 @@ x_edge_detection (f, img, matrix, color_adjust)
 {
   int i = 0;
   int trans[9];
-  
+
   if (CONSP (matrix))
     {
       for (i = 0;
@@ -10926,29 +11150,32 @@ x_disable_image (f, img)
      should.  */
   if (dpyinfo->n_planes * dpyinfo->n_cbits < 2 || cross_disabled_images)
     {
-#if 0 /* TODO: full image support  */
-      Display *dpy = FRAME_X_DISPLAY (f);
-      GC gc;
+      HDC hdc, bmpdc;
+      HGDIOBJ prev;
+
+      hdc = get_frame_dc (f);
+      bmpdc = CreateCompatibleDC (hdc);
+      release_frame_dc (f, hdc);
+
+      prev = SelectObject (bmpdc, img->pixmap);
 
-      gc = XCreateGC (dpy, img->pixmap, 0, NULL);
-      XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
-      XDrawLine (dpy, img->pixmap, gc, 0, 0,
-                img->width - 1, img->height - 1);
-      XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
-                img->width - 1, 0);
-      XFreeGC (dpy, gc);
+      SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
+      MoveToEx (bmpdc, 0, 0, NULL);
+      LineTo (bmpdc, img->width - 1, img->height - 1);
+      MoveToEx (bmpdc, 0, img->height - 1, NULL);
+      LineTo (bmpdc, img->width - 1, 0);
 
       if (img->mask)
        {
-         gc = XCreateGC (dpy, img->mask, 0, NULL);
-         XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
-         XDrawLine (dpy, img->mask, gc, 0, 0,
-                    img->width - 1, img->height - 1);
-         XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
-                    img->width - 1, 0);
-         XFreeGC (dpy, gc);
+         SelectObject (bmpdc, img->mask);
+         SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
+         MoveToEx (bmpdc, 0, 0, NULL);
+         LineTo (bmpdc, img->width - 1, img->height - 1);
+         MoveToEx (bmpdc, 0, img->height - 1, NULL);
+         LineTo (bmpdc, img->width - 1, 0);
        }
-#endif
+      SelectObject (bmpdc, prev);
+      DeleteDC (bmpdc);
     }
 }
 
@@ -10966,33 +11193,35 @@ x_build_heuristic_mask (f, img, how)
      struct image *img;
      Lisp_Object how;
 {
-#if 0 /* TODO: full image support.  */
-  Display *dpy = FRAME_W32_DISPLAY (f);
-  XImage *ximg, *mask_img;
+  HDC img_dc, frame_dc;
+  HGDIOBJ prev;
+  char *mask_img;
   int x, y, rc, use_img_background;
   unsigned long bg = 0;
+  int row_width;
 
   if (img->mask)
     {
-      XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
-      img->mask = None;
+      DeleteObject (img->mask);
+      img->mask = NULL;
       img->background_transparent_valid = 0;
     }
 
-  /* Create an image and pixmap serving as mask.  */
-  rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
-                                   &mask_img, &img->mask);
-  if (!rc)
-    return 0;
+  /* Create the bit array serving as mask.  */
+  row_width = (img->width + 7) / 8;
+  mask_img = xmalloc (row_width * img->height);
+  bzero (mask_img, row_width * img->height);
 
-  /* Get the X image of IMG->pixmap.  */
-  ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
-                   ~0, ZPixmap);
+  /* Create a memory device context for IMG->pixmap.  */
+  frame_dc = get_frame_dc (f);
+  img_dc = CreateCompatibleDC (frame_dc);
+  release_frame_dc (f, frame_dc);
+  prev = SelectObject (img_dc, img->pixmap);
 
-  /* Determine the background color of ximg.  If HOW is `(R G B)'
+  /* Determine the background color of img_dc.  If HOW is `(R G B)'
      take that as color.  Otherwise, use the image's background color.  */
   use_img_background = 1;
-  
+
   if (CONSP (how))
     {
       int rgb[3], i;
@@ -11007,32 +11236,40 @@ x_build_heuristic_mask (f, img, how)
        {
          char color_name[30];
          sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
-         bg = x_alloc_image_color (f, img, build_string (color_name), 0);
+         bg = x_alloc_image_color (f, img, build_string (color_name), 0)
+           & 0x00ffffff; /* Filter out palette info.  */
          use_img_background = 0;
        }
     }
-  
+
   if (use_img_background)
-    bg = four_corners_best (ximg, img->width, img->height);
+    bg = four_corners_best (img_dc, img->width, img->height);
 
   /* Set all bits in mask_img to 1 whose color in ximg is different
      from the background color bg.  */
   for (y = 0; y < img->height; ++y)
     for (x = 0; x < img->width; ++x)
-      XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
+      {
+       COLORREF p = GetPixel (img_dc, x, y);
+       if (p != bg)
+         mask_img[y * row_width + x / 8] |= 1 << (x % 8);
+      }
+
+  /* Create the mask image.  */
+  img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
+                                                 mask_img);
 
   /* Fill in the background_transparent field while we have the mask handy. */
-  image_background_transparent (img, f, mask_img);
+  SelectObject (img_dc, img->mask);
+
+  image_background_transparent (img, f, img_dc);
 
   /* Put mask_img into img->mask.  */
-  x_put_x_image (f, mask_img, img->mask, img->width, img->height);
-  x_destroy_x_image (mask_img);
-  XDestroyImage (ximg);
+  x_destroy_x_image ((XImage *)mask_img);
+  SelectObject (img_dc, prev);
+  DeleteDC (img_dc);
 
   return 1;
-#else
-  return 0;
-#endif
 }
 
 \f
@@ -11074,7 +11311,7 @@ static struct image_keyword pbm_format[PBM_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -11103,12 +11340,10 @@ pbm_image_p (object)
      Lisp_Object object;
 {
   struct image_keyword fmt[PBM_LAST];
-  
+
   bcopy (pbm_format, fmt, sizeof fmt);
-  
-  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
-      || (fmt[PBM_ASCENT].count 
-         && XFASTINT (fmt[PBM_ASCENT].value) > 100))
+
+  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
     return 0;
 
   /* Must specify either :data or :file.  */
@@ -11185,14 +11420,14 @@ pbm_read_file (file, size)
          buf = NULL;
        }
     }
-  
+
   return buf;
 }
 
 
 /* Load PBM image IMG for use on frame F.  */
 
-static int 
+static int
 pbm_load (f, img)
      struct frame *f;
      struct image *img;
@@ -11255,7 +11490,7 @@ pbm_load (f, img)
     case '1':
       raw_p = 0, type = PBM_MONO;
       break;
-      
+
     case '2':
       raw_p = 0, type = PBM_GRAY;
       break;
@@ -11267,11 +11502,11 @@ pbm_load (f, img)
     case '4':
       raw_p = 1, type = PBM_MONO;
       break;
-      
+
     case '5':
       raw_p = 1, type = PBM_GRAY;
       break;
-      
+
     case '6':
       raw_p = 1, type = PBM_COLOR;
       break;
@@ -11292,7 +11527,7 @@ pbm_load (f, img)
       if (raw_p && max_color_idx > 255)
        max_color_idx = 255;
     }
-  
+
   if (width < 0
       || height < 0
       || (type != PBM_MONO && max_color_idx < 0))
@@ -11316,7 +11551,7 @@ pbm_load (f, img)
       /* Parse the image specification.  */
       bcopy (pbm_format, fmt, sizeof fmt);
       parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
-      
+
       /* Get foreground and background colors, maybe allocate colors.  */
       if (fmt[PBM_FOREGROUND].count
          && STRINGP (fmt[PBM_FOREGROUND].value))
@@ -11351,7 +11586,7 @@ pbm_load (f, img)
        for (x = 0; x < width; ++x)
          {
            int r, g, b;
-           
+
            if (type == PBM_GRAY)
              r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
            else if (raw_p)
@@ -11366,7 +11601,7 @@ pbm_load (f, img)
                g = pbm_scan_number (&p, end);
                b = pbm_scan_number (&p, end);
              }
-           
+
            if (r < 0 || g < 0 || b < 0)
              {
                x_destroy_x_image (ximg);
@@ -11374,7 +11609,7 @@ pbm_load (f, img)
                             img->spec, Qnil);
                 goto error;
              }
-           
+
            /* RGB values are now in the range 0..max_color_idx.
               Scale this to the range 0..0xff supported by W32.  */
            r = (int) ((double) r * 255 / max_color_idx);
@@ -11398,11 +11633,11 @@ pbm_load (f, img)
   /* Maybe fill in the background field while we have ximg handy.  */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
     IMAGE_BACKGROUND (img, f, ximg);
-  
+
   /* Put the image into a pixmap.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-      
+
   img->width = width;
   img->height = height;
 
@@ -11454,7 +11689,7 @@ static struct image_keyword png_format[PNG_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -11474,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.  */
 
@@ -11483,10 +11771,8 @@ png_image_p (object)
 {
   struct image_keyword fmt[PNG_LAST];
   bcopy (png_format, fmt, sizeof fmt);
-  
-  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
-      || (fmt[PNG_ASCENT].count 
-         && XFASTINT (fmt[PNG_ASCENT].value) > 100))
+
+  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -11538,11 +11824,11 @@ 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;
 }
@@ -11564,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 */
@@ -11586,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
     {
@@ -11621,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;
@@ -11633,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);
@@ -11642,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;
@@ -11666,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);
@@ -11676,68 +11961,66 @@ 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 
+  /* 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;
 
-  /* This function is easier to write if we only have to handle 
+  /* This function is easier to write if we only have to handle
      one data format: RGB or RGBA with 8 bits per channel.  Let's
      transform other formats into that format.  */
 
   /* 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 
+  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.  */
        {
@@ -11747,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))
-       /* Image contains a background color with which to 
+      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 
+            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);
@@ -11804,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);
@@ -11816,7 +12101,7 @@ png_load (f, img)
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
                                    &img->pixmap))
     goto error;
-  
+
   /* Create an image and pixmap serving as mask if the PNG image
      contains an alpha channel.  */
   if (channels == 4
@@ -11825,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)
     {
@@ -11841,22 +12127,25 @@ 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 
+            transparency with an image.  Where other image formats
+            support binary transparency---fully transparent or fully
             opaque---PNG allows up to 254 levels of partial transparency.
             The PNG library implements partial transparency by combining
             the image with a specified background color.
 
             I'm not sure how to handle this here nicely: because the
             background on which the image is displayed may change, for
-            real alpha channel support, it would be necessary to create 
-            a new image for each possible background.  
+            real alpha channel support, it would be necessary to create
+            a new image for each possible background.
 
             What I'm doing now is that a mask is created if we have
             boolean transparency information.  Otherwise I'm using
@@ -11876,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);
 
@@ -11974,7 +12270,7 @@ static struct image_keyword jpeg_format[JPEG_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -11995,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
@@ -12002,12 +12336,10 @@ jpeg_image_p (object)
      Lisp_Object object;
 {
   struct image_keyword fmt[JPEG_LAST];
-  
+
   bcopy (jpeg_format, fmt, sizeof fmt);
-  
-  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
-      || (fmt[JPEG_ASCENT].count 
-         && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
+
+  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -12021,6 +12353,7 @@ struct my_jpeg_error_mgr
   jmp_buf setjmp_buffer;
 };
 
+
 static void
 my_error_exit (cinfo)
      j_common_ptr cinfo;
@@ -12029,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.  */
@@ -12075,7 +12409,7 @@ our_skip_input_data (cinfo, num_bytes)
     {
       if (num_bytes > src->bytes_in_buffer)
        ERREXIT (cinfo, JERR_INPUT_EOF);
-      
+
       src->bytes_in_buffer -= num_bytes;
       src->next_input_byte += num_bytes;
     }
@@ -12113,12 +12447,12 @@ jpeg_memory_src (cinfo, data, len)
       src = (struct jpeg_source_mgr *) cinfo->src;
       src->next_input_byte = data;
     }
-  
+
   src = (struct jpeg_source_mgr *) cinfo->src;
   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;
@@ -12128,7 +12462,7 @@ jpeg_memory_src (cinfo, data, len)
 /* Load image IMG for use on frame F.  Patterned after example.c
    from the JPEG lib.  */
 
-static int 
+static int
 jpeg_load (f, img)
      struct frame *f;
      struct image *img;
@@ -12156,26 +12490,26 @@ 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)
     {
       if (rc == 1)
@@ -12186,44 +12520,43 @@ jpeg_load (f, img)
          image_error ("Error reading JPEG image `%s': %s", img->spec,
                       build_string (buffer));
        }
-         
+
       /* 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);
 
       /* Free pixmap and colors.  */
       x_clear_image (f, img);
-      
+
       UNGCPRO;
       return 0;
     }
 
   /* 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,
@@ -12241,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.  */
@@ -12270,25 +12609,24 @@ 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)))
     IMAGE_BACKGROUND (img, f, ximg);
-  
+
   /* 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;
 }
@@ -12337,7 +12675,7 @@ static struct image_keyword tiff_format[TIFF_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -12357,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.  */
 
@@ -12366,12 +12726,10 @@ tiff_image_p (object)
 {
   struct image_keyword fmt[TIFF_LAST];
   bcopy (tiff_format, fmt, sizeof fmt);
-  
-  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
-      || (fmt[TIFF_ASCENT].count 
-         && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
+
+  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
     return 0;
-  
+
   /* Must specify either the :data or :file keyword.  */
   return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
 }
@@ -12432,22 +12790,22 @@ tiff_seek_in_memory (data, off, whence)
     case SEEK_SET:             /* Go from beginning of source.  */
       idx = off;
       break;
-      
+
     case SEEK_END:             /* Go from end of source.  */
       idx = src->len + off;
       break;
-      
+
     case SEEK_CUR:             /* Go from current position.  */
       idx = src->index + off;
       break;
-      
+
     default:                   /* Invalid `whence'.   */
       return -1;
     }
-  
+
   if (idx > src->len || idx < 0)
     return -1;
-  
+
   src->index = idx;
   return src->index;
 }
@@ -12494,7 +12852,7 @@ tiff_error_handler (title, format, ap)
 {
   char buf[512];
   int len;
-  
+
   len = sprintf (buf, "TIFF error: %s ", title);
   vsprintf (buf + len, format, ap);
   add_to_log (buf, Qnil, Qnil);
@@ -12508,7 +12866,7 @@ tiff_warning_handler (title, format, ap)
 {
   char buf[512];
   int len;
-  
+
   len = sprintf (buf, "TIFF warning: %s ", title);
   vsprintf (buf + len, format, ap);
   add_to_log (buf, Qnil, Qnil);
@@ -12538,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))
     {
@@ -12551,9 +12909,9 @@ tiff_load (f, img)
          UNGCPRO;
          return 0;
        }
-         
+
       /* 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);
@@ -12568,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)
        {
@@ -12587,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);
@@ -12609,27 +12967,35 @@ 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)
     {
       uint32 *row = buf + y * width;
-      
+
       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;
-         XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b)); 
+         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;
@@ -12657,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));
@@ -12692,7 +13060,7 @@ static struct image_keyword gif_format[GIF_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -12713,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
@@ -12721,12 +13108,10 @@ gif_image_p (object)
 {
   struct image_keyword fmt[GIF_LAST];
   bcopy (gif_format, fmt, sizeof fmt);
-  
-  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
-      || (fmt[GIF_ASCENT].count 
-         && XFASTINT (fmt[GIF_ASCENT].value) > 100))
+
+  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
     return 0;
-  
+
   /* Must specify either the :data or :file keyword.  */
   return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
 }
@@ -12799,9 +13184,9 @@ gif_load (f, img)
           UNGCPRO;
           return 0;
         }
-  
+
       /* Open the GIF file.  */
-      gif = DGifOpenFileName (SDATA (file));
+      gif = fn_DGifOpenFileName (SDATA (file));
       if (gif == NULL)
         {
           image_error ("Cannot open `%s'", file, Qnil);
@@ -12817,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);
@@ -12827,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;
     }
@@ -12842,42 +13227,50 @@ 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;
     }
-  
+
   /* Allocate colors.  */
   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 
+     the image from the GIF file.  Full animated GIF support
      requires more than can be done here (see the gif89 spec,
      disposal methods).  Let's simply assume that the part
      not covered by a sub-image is in the frame's background color.  */
@@ -12924,14 +13317,14 @@ gif_load (f, img)
              while (row >= image_height)
                row = interlace_start[++pass];
            }
-         
+
          for (x = 0; x < image_width; x++)
            {
              int i = raster[(y * image_width) + x];
              XPutPixel (ximg, x + image_left, row + image_top,
                         pixel_colors[i]);
            }
-         
+
          row += interlace_increment[pass];
        }
     }
@@ -12944,8 +13337,8 @@ gif_load (f, img)
            XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
          }
     }
-  
-  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)))
@@ -12954,7 +13347,7 @@ gif_load (f, img)
   /* Put the image into the pixmap, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-      
+
   UNGCPRO;
   return 1;
 }
@@ -12969,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));
@@ -13011,7 +13408,7 @@ static struct image_keyword gs_format[GS_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     1},
   {":loader",          IMAGE_FUNCTION_VALUE,                   0},
   {":bounding-box",    IMAGE_DONT_CHECK_VALUE_TYPE,            1},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -13055,12 +13452,10 @@ gs_image_p (object)
   struct image_keyword fmt[GS_LAST];
   Lisp_Object tem;
   int i;
-  
+
   bcopy (gs_format, fmt, sizeof fmt);
-  
-  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
-      || (fmt[GS_ASCENT].count 
-         && XFASTINT (fmt[GS_ASCENT].value) > 100))
+
+  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
     return 0;
 
   /* Bounding box must be a list or vector containing 4 integers.  */
@@ -13127,7 +13522,7 @@ gs_load (f, img)
       image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
       return 0;
     }
-    
+
   /* Call the loader to fill the pixmap.  It returns a process object
      if successful.  We do not record_unwind_protect here because
      other places in redisplay like calling window scroll functions
@@ -13138,12 +13533,12 @@ gs_load (f, img)
           (unsigned long) FRAME_W32_WINDOW (f),
           (unsigned long) img->pixmap);
   window_and_pixmap_id = build_string (buffer);
-  
+
   sprintf (buffer, "%lu %lu",
           FRAME_FOREGROUND_PIXEL (f),
           FRAME_BACKGROUND_PIXEL (f));
   pixel_colors = build_string (buffer);
-  
+
   XSETFRAME (frame, f);
   loader = image_spec_value (img->spec, QCloader, NULL);
   if (NILP (loader))
@@ -13205,10 +13600,10 @@ x_kill_gs_process (pixmap, f)
       if (ximg)
        {
          int x, y;
-         
+
          /* Initialize the color table.  */
          init_color_table ();
-      
+
          /* For each pixel of the image, look its color up in the
             color table.  After having done so, the color table will
             contain an entry for each color used by the image.  */
@@ -13238,7 +13633,7 @@ x_kill_gs_process (pixmap, f)
       else
        image_error ("Cannot get X image of `%s'; colors will not be freed",
                     img->spec, Qnil);
-      
+
       UNBLOCK_INPUT;
     }
 
@@ -13350,8 +13745,8 @@ value.  */)
       rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
                               prop_atom, 0, bytes_remaining,
                               False, XA_STRING,
-                              &actual_type, &actual_format, 
-                              &actual_size, &bytes_remaining, 
+                              &actual_type, &actual_format,
+                              &actual_size, &bytes_remaining,
                               (unsigned char **) &tmp_data);
       if (rc == Success)
        prop_value = make_string (tmp_data, size);
@@ -13405,7 +13800,7 @@ start_hourglass ()
 #if 0 /* TODO: cursor shape changes.  */
   EMACS_TIME delay;
   int secs, usecs = 0;
-  
+
   cancel_hourglass ();
 
   if (INTEGERP (Vhourglass_delay)
@@ -13421,7 +13816,7 @@ start_hourglass ()
     }
   else
     secs = DEFAULT_HOURGLASS_DELAY;
-  
+
   EMACS_SET_SECS_USECS (delay, secs, usecs);
   hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
                                   show_hourglass, NULL);
@@ -13440,7 +13835,7 @@ cancel_hourglass ()
       cancel_atimer (hourglass_atimer);
       hourglass_atimer = NULL;
     }
-  
+
   if (hourglass_shown_p)
     hide_hourglass ();
 }
@@ -13467,23 +13862,23 @@ show_hourglass (timer)
   if (!hourglass_shown_p)
     {
       Lisp_Object rest, frame;
-  
+
       BLOCK_INPUT;
-  
+
       FOR_EACH_FRAME (rest, frame)
        if (FRAME_W32_P (XFRAME (frame)))
          {
            struct frame *f = XFRAME (frame);
-       
+
            f->output_data.w32->hourglass_p = 1;
-       
+
            if (!f->output_data.w32->hourglass_window)
              {
                unsigned long mask = CWCursor;
                XSetWindowAttributes attrs;
-           
+
                attrs.cursor = f->output_data.w32->hourglass_cursor;
-           
+
                f->output_data.w32->hourglass_window
                  = XCreateWindow (FRAME_X_DISPLAY (f),
                                   FRAME_OUTER_WINDOW (f),
@@ -13492,7 +13887,7 @@ show_hourglass (timer)
                                   CopyFromParent,
                                   mask, &attrs);
              }
-       
+
            XMapRaised (FRAME_X_DISPLAY (f),
                        f->output_data.w32->hourglass_window);
            XFlush (FRAME_X_DISPLAY (f));
@@ -13519,7 +13914,7 @@ hide_hourglass ()
       FOR_EACH_FRAME (rest, frame)
        {
          struct frame *f = XFRAME (frame);
-      
+
          if (FRAME_W32_P (f)
              /* Watch out for newly created frames.  */
              && f->output_data.x->hourglass_window)
@@ -13549,7 +13944,7 @@ static Lisp_Object x_create_tip_frame P_ ((struct w32_display_info *,
                                           Lisp_Object, Lisp_Object));
 static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
                                Lisp_Object, int, int, int *, int *));
-     
+
 /* The frame of a currently visible tooltip.  */
 
 Lisp_Object tip_frame;
@@ -13582,7 +13977,7 @@ unwind_create_tip_frame (frame)
       tip_window = NULL;
       tip_frame = Qnil;
     }
-  
+
   return deleted;
 }
 
@@ -13648,7 +14043,7 @@ x_create_tip_frame (dpyinfo, parms, text)
   Ferase_buffer ();
   Finsert (1, &text);
   set_buffer_internal_1 (old_buffer);
-  
+
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   record_unwind_protect (unwind_create_tip_frame, frame);
 
@@ -13706,7 +14101,7 @@ x_create_tip_frame (dpyinfo, parms, text)
        else
          font = x_new_font (f, SDATA (font));
       }
-    
+
     /* Try out a font which we hope has bold and italic variations.  */
     if (!STRINGP (font))
       font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
@@ -13816,7 +14211,7 @@ x_create_tip_frame (dpyinfo, parms, text)
   if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
     Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
                                            Qnil));
-  
+
   /* Set up faces after all frame parameters are known.  This call
      also merges in face attributes specified for new frames.
 
@@ -13831,12 +14226,12 @@ x_create_tip_frame (dpyinfo, parms, text)
     /* Set tip_frame here, so that */
     tip_frame = frame;
     call1 (Qface_set_after_frame_default, frame);
-    
+
     if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
       Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
                                              Qnil));
   }
-  
+
   f->no_split = 1;
 
   UNGCPRO;
@@ -13876,11 +14271,11 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
      int *root_x, *root_y;
 {
   Lisp_Object left, top;
-  
+
   /* User-specified position?  */
   left = Fcdr (Fassq (Qleft, parms));
   top  = Fcdr (Fassq (Qtop, parms));
-  
+
   /* Move the tooltip window where the mouse pointer is.  Resize and
      show it.  */
   if (!INTEGERP (left) || !INTEGERP (top))
@@ -13952,7 +14347,7 @@ Text larger than the specified size is clipped.  */)
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   int old_windows_or_buffers_changed = windows_or_buffers_changed;
   int count = SPECPDL_INDEX ();
-  
+
   specbind (Qinhibit_redisplay, Qt);
 
   GCPRO4 (string, parms, frame, timeout);
@@ -13968,7 +14363,7 @@ Text larger than the specified size is clipped.  */)
     dx = make_number (5);
   else
     CHECK_NUMBER (dx);
-  
+
   if (NILP (dy))
     dy = make_number (-10);
   else
@@ -13988,7 +14383,7 @@ Text larger than the specified size is clipped.  */)
          && !NILP (Fequal (last_parms, parms)))
        {
          struct frame *f = XFRAME (tip_frame);
-         
+
          /* Only DX and DY have changed.  */
          if (!NILP (tip_timer))
            {
@@ -14063,7 +14458,7 @@ Text larger than the specified size is clipped.  */)
       w->width = make_number (80);
       w->height = make_number (40);
     }
-  
+
   f->window_width = XINT (w->width);
   adjust_glyphs (f);
   w->pseudo_window_p = 1;
@@ -14104,7 +14499,7 @@ Text larger than the specified size is clipped.  */)
       else
 #endif
        row_width = row->pixel_width;
-      
+
       /* TODO: find why tips do not draw along baseline as instructed.  */
       height += row->height;
       width = max (width, row_width);
@@ -14176,16 +14571,16 @@ Value is t if tooltip was open, nil otherwise.  */)
   /* Return quickly if nothing to do.  */
   if (NILP (tip_timer) && NILP (tip_frame))
     return Qnil;
-  
+
   frame = tip_frame;
   timer = tip_timer;
   GCPRO2 (frame, timer);
   tip_frame = tip_timer = deleted = Qnil;
-  
+
   count = SPECPDL_INDEX ();
   specbind (Qinhibit_redisplay, Qt);
   specbind (Qinhibit_quit, Qt);
-  
+
   if (!NILP (timer))
     call1 (Qcancel_timer, timer);
 
@@ -14804,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 = GetProcAddress (user32_lib, "TrackMouseEvent");
   track_mouse_window = NULL;
 
   w32_visible_system_caret_hwnd = NULL;
@@ -14953,13 +15343,13 @@ When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.  *
              doc: /* If non-zero, the virtual key code for an alternative quit key.  */);
   XSETINT (Vw32_quit_key, 0);
 
-  DEFVAR_LISP ("w32-pass-lwindow-to-system", 
+  DEFVAR_LISP ("w32-pass-lwindow-to-system",
               &Vw32_pass_lwindow_to_system,
               doc: /* Non-nil if the left \"Windows\" key is passed on to Windows.
 When non-nil, the Start menu is opened by tapping the key.  */);
   Vw32_pass_lwindow_to_system = Qt;
 
-  DEFVAR_LISP ("w32-pass-rwindow-to-system", 
+  DEFVAR_LISP ("w32-pass-rwindow-to-system",
               &Vw32_pass_rwindow_to_system,
               doc: /* Non-nil if the right \"Windows\" key is passed on to Windows.
 When non-nil, the Start menu is opened by tapping the key.  */);
@@ -14977,13 +15367,13 @@ acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
      means that this hack won't interfere with any real key code.  */
   Vw32_phantom_key_code = 255;
 
-  DEFVAR_LISP ("w32-enable-num-lock", 
+  DEFVAR_LISP ("w32-enable-num-lock",
               &Vw32_enable_num_lock,
               doc: /* Non-nil if Num Lock should act normally.
 Set to nil to see Num Lock as the key `kp-numlock'.  */);
   Vw32_enable_num_lock = Qt;
 
-  DEFVAR_LISP ("w32-enable-caps-lock", 
+  DEFVAR_LISP ("w32-enable-caps-lock",
               &Vw32_enable_caps_lock,
               doc: /* Non-nil if Caps Lock should act normally.
 Set to nil to see Caps Lock as the key `capslock'.  */);
@@ -15059,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,
@@ -15090,7 +15480,7 @@ or when you set the mouse color.  */);
   DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
               doc: /* Non-zero means Emacs displays an hourglass pointer on window systems.  */);
   display_hourglass_p = 1;
-  
+
   DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
               doc: /* *Seconds to wait before displaying an hourglass pointer.
 Value must be an integer or float.  */);
@@ -15118,7 +15508,7 @@ or when you set the mouse color.  */);
               doc: /* Maximum size for tooltips.
 Value is a pair (COLUMNS . ROWS). Text larger than this is clipped.  */);
   Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
-  
+
   DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
               doc: /* Non-nil if no window manager is in use.
 Emacs doesn't try to figure this out; this is always nil
@@ -15330,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");
@@ -15339,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");
@@ -15349,16 +15737,16 @@ versions of Windows) characters.  */);
   Qxpm = intern ("xpm");
   staticpro (&Qxpm);
 #endif
-  
+
 #if HAVE_JPEG
   Qjpeg = intern ("jpeg");
   staticpro (&Qjpeg);
-#endif 
+#endif
 
 #if HAVE_TIFF
   Qtiff = intern ("tiff");
   staticpro (&Qtiff);
-#endif 
+#endif
 
 #if HAVE_GIF
   Qgif = intern ("gif");
@@ -15395,42 +15783,105 @@ 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");
+}
+
+/* Initialize image types. Based on which libraries are available.  */
+static void
+init_external_image_libraries ()
+{
+  HINSTANCE library;
 
-  define_image_type (&pbm_type);
-  define_image_type (&xbm_type);
-#if 0 /* TODO : Image support for W32 */
-  define_image_type (&gs_type);
-#endif
-  
 #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
 
-void 
+void
 w32_abort()
 {
   int button;