(x_set_cursor_color): Set cursor_gc as well.
[bpt/emacs.git] / src / w32fns.c
index 5cfd25c..319f8d9 100644 (file)
@@ -277,7 +277,6 @@ Lisp_Object Qfullboth;
 
 extern Lisp_Object Qtop;
 extern Lisp_Object Qdisplay;
-extern Lisp_Object Qtool_bar_lines;
 
 /* State variables for emulating a three button mouse. */
 #define LMOUSE 1
@@ -2287,11 +2286,18 @@ x_set_cursor_color (f, arg, oldval)
        fore_pixel = FRAME_BACKGROUND_PIXEL (f);
     }
 
-  FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
+  f->output_data.w32->cursor_foreground_pixel = fore_pixel;
   f->output_data.w32->cursor_pixel = pixel;
 
   if (FRAME_W32_WINDOW (f) != 0)
     {
+      BLOCK_INPUT;
+      /* Update frame's cursor_gc.  */
+      f->output_data.w32->cursor_gc->foreground = fore_pixel;
+      f->output_data.w32->cursor_gc->background = pixel;
+
+      UNBLOCK_INPUT;
+
       if (FRAME_VISIBLE_P (f))
        {
          x_update_cursor (f, 0);
@@ -5671,7 +5677,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   
   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 (0),
+  x_default_parameter (f, parms, Qtool_bar_lines, make_number (HAVE_IMAGES),
                        "toolBar", "ToolBar", RES_TYPE_NUMBER);
   x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
                       "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
@@ -6451,7 +6457,8 @@ w32_to_all_x_charsets (fncharset)
       /* Handle startup case of w32-charset-info-alist not
          being set up yet. */
       if (NILP(Vw32_charset_info_alist))
-        return "iso8859-1";
+        return Fcons (build_string ("iso8859-1"), Qnil);
+
       charset_type = Qw32_charset_ansi;
       break;
     case DEFAULT_CHARSET:
@@ -6639,8 +6646,8 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
   char height_dpi[8];
   char width_pixels[8];
   char *fontname_dash;
-  int display_resy = one_w32_display_info.resy;
-  int display_resx = one_w32_display_info.resx;
+  int display_resy = (int) one_w32_display_info.resy;
+  int display_resx = (int) one_w32_display_info.resx;
   int bufsz;
   struct coding_system coding;
 
@@ -6756,7 +6763,7 @@ x_to_w32_font (lpxstr, lplogfont)
       char name[50], weight[20], slant, pitch, pixels[10], height[10],
         width[10], resy[10], remainder[50];
       char * encoding;
-      int dpi = one_w32_display_info.resy;
+      int dpi = (int) one_w32_display_info.resy;
 
       fields = sscanf (lpxstr,
                       "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
@@ -8141,7 +8148,6 @@ DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
 }
 
 \f
-\f
 /***********************************************************************
                            Image types
  ***********************************************************************/
@@ -8167,8 +8173,8 @@ Lisp_Object Qxbm;
 /* Keywords.  */
 
 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata;
-Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
+extern Lisp_Object QCdata, QCtype;
+Lisp_Object QCascent, QCmargin, QCrelief;
 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
 
@@ -8498,6 +8504,64 @@ image_spec_value (spec, key, found)
 }
      
 
+#ifdef HAVE_IMAGES
+DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
+       doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
+PIXELS non-nil means return the size in pixels, otherwise return the
+size in canonical character units.
+FRAME is the frame on which the image will be displayed.  FRAME nil
+or omitted means use the selected frame.  */)
+     (spec, pixels, frame)
+     Lisp_Object spec, pixels, frame;
+{
+  Lisp_Object size;
+
+  size = Qnil;
+  if (valid_image_p (spec))
+    {
+      struct frame *f = check_x_frame (frame);
+      int id = lookup_image (f, spec);
+      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)));
+      else
+       size = Fcons (make_number (width), make_number (height));
+    }
+  else
+    error ("Invalid image specification");
+
+  return size;
+}
+
+
+DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
+       doc: /* Return t if image SPEC has a mask bitmap.
+FRAME is the frame on which the image will be displayed.  FRAME nil
+or omitted means use the selected frame.  */)
+     (spec, frame)
+     Lisp_Object spec, frame;
+{
+  Lisp_Object mask;
+
+  mask = Qnil;
+  if (valid_image_p (spec))
+    {
+      struct frame *f = check_x_frame (frame);
+      int id = lookup_image (f, spec);
+      struct image *img = IMAGE_FROM_ID (f, id);
+      if (img->mask)
+       mask = Qt;
+    }
+  else
+    error ("Invalid image specification");
+
+  return mask;
+}
+#endif
 
 \f
 /***********************************************************************
@@ -8600,7 +8664,7 @@ image_ascent (img, face)
        ascent = height / 2;
     }
   else
-    ascent = height * img->ascent / 100.0;
+    ascent = (int) (height * img->ascent / 100.0);
 
   return ascent;
 }
@@ -8609,20 +8673,21 @@ image_ascent (img, face)
 \f
 /* Image background colors.  */
 
-static unsigned long
+/* 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)
-     XImage *ximg;
+     HDC ximg;
      unsigned long width, height;
 {
-#if 0 /* TODO: Image support.  */
-  unsigned long corners[4], best;
+  COLORREF corners[4], best;
   int i, best_count;
 
   /* Get the colors at the corners of ximg.  */
-  corners[0] = XGetPixel (ximg, 0, 0);
-  corners[1] = XGetPixel (ximg, width - 1, 0);
-  corners[2] = XGetPixel (ximg, width - 1, height - 1);
-  corners[3] = XGetPixel (ximg, 0, height - 1);
+  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);
 
   /* Choose the most frequently found color as background.  */
   for (i = best_count = 0; i < 4; ++i)
@@ -8638,9 +8703,6 @@ four_corners_best (ximg, width, height)
     }
 
   return best;
-#else
-  return 0;
-#endif
 }
 
 /* Return the `background' field of IMG.  If IMG doesn't have one yet,
@@ -8738,29 +8800,29 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
      struct image *img;
      int pixmap_p, mask_p, colors_p;
 {
-#if 0 /* TODO: W32 image support  */
   if (pixmap_p && img->pixmap)
     {
-      XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
-      img->pixmap = None;
+      DeleteObject (img->pixmap);
+      img->pixmap = NULL;
       img->background_valid = 0;
     }
 
   if (mask_p && img->mask)
     {
-      XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
-      img->mask = None;
+      DeleteObject (img->mask);
+      img->mask = NULL;
       img->background_transparent_valid = 0;
     }
       
   if (colors_p && img->ncolors)
     {
+#if 0  /* TODO: color table support.  */
       x_free_colors (f, img->colors, img->ncolors);
+#endif
       xfree (img->colors);
       img->colors = NULL;
       img->ncolors = 0;
     }
-#endif
 }
 
 /* Free X resources of image IMG which is used on frame F.  */
@@ -8770,18 +8832,18 @@ x_clear_image (f, img)
      struct frame *f;
      struct image *img;
 {
-#if 0 /* TODO: W32 image support  */
-
   if (img->pixmap)
     {
       BLOCK_INPUT;
-      XFreePixmap (NULL, img->pixmap);
+      DeleteObject (img->pixmap);
       img->pixmap = 0;
       UNBLOCK_INPUT;
     }
 
   if (img->ncolors)
     {
+#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
@@ -8797,12 +8859,12 @@ x_clear_image (f, img)
                       img->ncolors, 0);
          UNBLOCK_INPUT;
        }
+#endif
       
       xfree (img->colors);
       img->colors = NULL;
       img->ncolors = 0;
     }
-#endif
 }
 
 
@@ -8818,7 +8880,6 @@ x_alloc_image_color (f, img, color_name, dflt)
      Lisp_Object color_name;
      unsigned long dflt;
 {
-#if 0 /* TODO: allocing colors.  */
   XColor color;
   unsigned long result;
 
@@ -8838,8 +8899,6 @@ x_alloc_image_color (f, img, color_name, dflt)
   else
     result = dflt;
   return result;
-#endif
-  return 0;
 }
 
 
@@ -8914,20 +8973,23 @@ clear_image_cache (f, force_p)
     {
       EMACS_TIME t;
       unsigned long old;
-      int i, any_freed_p = 0;
+      int i, nfreed;
 
       EMACS_GET_TIME (t);
       old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
       
-      for (i = 0; i < c->used; ++i)
+      /* 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];
          if (img != NULL
-             && (force_p
-                 || (img->timestamp > old)))
+             && (force_p || (img->timestamp < old)))
            {
              free_image (f, img);
-             any_freed_p = 1;
+             ++nfreed;
            }
        }
 
@@ -8935,11 +8997,22 @@ clear_image_cache (f, force_p)
         Emacs was iconified for a longer period of time.  In that
         case, current matrices may still contain references to
         images freed above.  So, clear these matrices.  */
-      if (any_freed_p)
+      if (nfreed)
        {
-         clear_current_matrices (f);
+         Lisp_Object tail, frame;
+         
+         FOR_EACH_FRAME (tail, frame)
+           {
+             struct frame *f = XFRAME (frame);
+             if (FRAME_W32_P (f)
+                 && FRAME_X_IMAGE_CACHE (f) == c)
+               clear_current_matrices (f);
+           }
+
          ++windows_or_buffers_changed;
        }
+
+      UNBLOCK_INPUT;
     }
 }
 
@@ -9015,7 +9088,7 @@ postprocess_image (f, img)
            }
          else if (NILP (mask) && found_p && img->mask)
            {
-             XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+             DeleteObject (img->mask);
              img->mask = NULL;
            }
        }
@@ -9230,8 +9303,6 @@ forall_images_in_image_cache (f, fn)
                            W32 support code
  ***********************************************************************/
 
-#if 0 /* TODO: W32 specific image code.  */
-
 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
                                             XImage **, Pixmap *));
 static void x_destroy_x_image P_ ((XImage *));
@@ -9241,8 +9312,10 @@ static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
    frame F.  Set *XIMG and *PIXMAP to the XImage and Pixmap created.
    Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
-   via xmalloc.  Print error messages via image_error if an error
-   occurs.  Value is non-zero if successful.  */
+   via xmalloc.  DEPTH of zero signifies a 24 bit image, otherwise
+   DEPTH should indicate the bit depth of the image.  Print error
+   messages via image_error if an error occurs.  Value is non-zero if
+   successful.  */
 
 static int
 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
@@ -9251,37 +9324,71 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
      XImage **ximg;
      Pixmap *pixmap;
 {
-#if 0 /* TODO: Image support for W32 */
-  Display *display = FRAME_W32_DISPLAY (f);
-  Screen *screen = FRAME_X_SCREEN (f);
-  Window window = FRAME_W32_WINDOW (f);
+  BITMAPINFOHEADER *header;
+  HDC hdc;
+  int scanline_width_bits;
+  int remainder;
+  int palette_colors = 0;
 
-  xassert (interrupt_input_blocked);
+  if (depth == 0)
+    depth = 24;
+
+  if (depth != 1 && depth != 4 && depth != 8
+      && depth != 16 && depth != 24 && depth != 32)
+    {
+      image_error ("Invalid image bit depth specified", Qnil, Qnil);
+      return 0;
+    }
 
-  if (depth <= 0)
-    depth = one_w32_display_info.n_cbits;
-  *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
-                       depth, ZPixmap, 0, NULL, width, height,
-                       depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
+  scanline_width_bits = width * depth;
+  remainder = scanline_width_bits % 32;
+
+  if (remainder)
+    scanline_width_bits += 32 - remainder;
+
+  /* Bitmaps with a depth less than 16 need a palette.  */
+  /* BITMAPINFO structure already contains the first RGBQUAD.  */
+  if (depth < 16)
+    palette_colors = 1 << depth - 1;
+
+  *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
   if (*ximg == NULL)
     {
-      image_error ("Unable to allocate X image", Qnil, Qnil);
+      image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
       return 0;
     }
 
-  /* Allocate image raster.  */
-  (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
+  header = &((*ximg)->info.bmiHeader);
+  bzero (&((*ximg)->info), sizeof (BITMAPINFO));
+  header->biSize = sizeof (*header);
+  header->biWidth = width;
+  header->biHeight = -height;  /* negative indicates a top-down bitmap.  */
+  header->biPlanes = 1;
+  header->biBitCount = depth;
+  header->biCompression = BI_RGB;
+  header->biClrUsed = palette_colors;
+
+  hdc = get_frame_dc (f);
 
-  /* Allocate a pixmap of the same size.  */
-  *pixmap = XCreatePixmap (display, window, width, height, depth);
-  if (*pixmap == 0)
+  /* Create a DIBSection and raster array for the bitmap,
+     and store its handle in *pixmap.  */
+  *pixmap = CreateDIBSection (hdc, &((*ximg)->info), DIB_RGB_COLORS,
+                             &((*ximg)->data), NULL, 0);
+
+  /* Realize display palette and garbage all frames. */
+  release_frame_dc (f, hdc);
+
+  if (*pixmap == NULL)
     {
+      DWORD err = GetLastError();
+      Lisp_Object errcode;
+      /* All system errors are < 10000, so the following is safe.  */
+      XSETINT (errcode, (int) err);
+      image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
       x_destroy_x_image (*ximg);
-      *ximg = NULL;
-      image_error ("Unable to create X pixmap", Qnil, Qnil);
       return 0;
     }
-#endif
+
   return 1;
 }
 
@@ -9295,9 +9402,9 @@ x_destroy_x_image (ximg)
   xassert (interrupt_input_blocked);
   if (ximg)
     {
-      xfree (ximg->data);
+      /* Data will be freed by DestroyObject.  */
       ximg->data = NULL;
-      XDestroyImage (ximg);
+      xfree (ximg);
     }
 }
 
@@ -9311,15 +9418,16 @@ x_put_x_image (f, ximg, pixmap, width, height)
      XImage *ximg;
      Pixmap pixmap;
 {
+
+#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);
-}
-
 #endif
+}
 
 \f
 /***********************************************************************
@@ -9843,6 +9951,8 @@ xbm_load_image (f, img, contents, end)
   if (rc)
     {
       int depth = one_w32_display_info.n_cbits;
+      int planes = one_w32_display_info.n_planes;
+
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       Lisp_Object value;
@@ -9860,16 +9970,9 @@ xbm_load_image (f, img, contents, end)
          img->background = background;
          img->background_valid = 1;
        }
-      
-#if 0 /* TODO : Port image display to W32 */
       img->pixmap
-       = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
-                                      FRAME_W32_WINDOW (f),
-                                      data,
-                                      img->width, img->height,
-                                      foreground, background,
-                                      depth);
-#endif
+       = CreateBitmap (img->width, img->height, planes, depth, data);
+
       xfree (data);
 
       if (img->pixmap == 0)
@@ -10477,13 +10580,14 @@ colors_in_color_table (n)
 #endif /* TODO */
 
 \f
+#ifdef HAVE_IMAGES /* TODO */
 /***********************************************************************
                              Algorithms
  ***********************************************************************/
-#if 0 /* TODO: image support. */
 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
+static void XPutPixel (XImage *, int, int, COLORREF);
 
 /* Non-zero means draw a cross on images having `:conversion
    disabled'.  */
@@ -10530,7 +10634,7 @@ x_to_xcolors (f, img, rgb_p)
   XImage *ximg;
 
   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);
@@ -10550,9 +10654,37 @@ x_to_xcolors (f, img, rgb_p)
     }
 
   XDestroyImage (ximg);
+#endif
   return colors;
 }
 
+/* Put a pixel of COLOR at position X, Y in XIMG.  XIMG must have been
+   created with CreateDIBSection, with the pointer to the bit values
+   stored in ximg->data.  */
+
+static void XPutPixel (ximg, x, y, color)
+     XImage * ximg;
+     int x, y;
+     COLORREF 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);
+}
+
 
 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
    RGB members are set.  F is the frame on which this all happens.
@@ -10568,9 +10700,9 @@ x_from_xcolors (f, img, colors)
   XImage *oimg;
   Pixmap pixmap;
   XColor *p;
-  
+#if 0   /* TODO: color tables.  */
   init_color_table ();
-  
+#endif
   x_create_x_image_and_pixmap (f, img->width, img->height, 0,
                               &oimg, &pixmap);
   p = colors;
@@ -10578,7 +10710,11 @@ x_from_xcolors (f, img, colors)
     for (x = 0; x < img->width; ++x, ++p)
       {
        unsigned long pixel;
+#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);
+#endif
        XPutPixel (oimg, x, y, pixel);
       }
 
@@ -10588,8 +10724,10 @@ x_from_xcolors (f, img, colors)
   x_put_x_image (f, oimg, pixmap, img->width, img->height);
   x_destroy_x_image (oimg);
   img->pixmap = pixmap;
+#if 0  /* TODO: color tables.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
 }
 
 
@@ -10740,9 +10878,9 @@ x_disable_image (f, img)
      struct frame *f;
      struct image *img;
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
-  if (dpyinfo->n_planes >= 2)
+  if (dpyinfo->n_planes * dpyinfo->n_cbits >= 2)
     {
       /* Color (or grayscale).  Convert to gray, and equalize.  Just
         drawing such images with a stipple can look very odd, so
@@ -10766,8 +10904,9 @@ x_disable_image (f, img)
 
   /* Draw a cross over the disabled image, if we must or if we
      should.  */
-  if (dpyinfo->n_planes < 2 || cross_disabled_images)
+  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;
 
@@ -10789,6 +10928,7 @@ x_disable_image (f, img)
                     img->width - 1, 0);
          XFreeGC (dpy, gc);
        }
+#endif
     }
 }
 
@@ -10806,6 +10946,7 @@ 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;
   int x, y, rc, use_img_background;
@@ -10869,9 +11010,11 @@ x_build_heuristic_mask (f, img, how)
   XDestroyImage (ximg);
 
   return 1;
+#else
+  return 0;
+#endif
 }
-#endif /* TODO */
-
+#endif
 \f
 /***********************************************************************
                       PBM (mono, gray, color)
@@ -11136,12 +11279,13 @@ pbm_load (f, img)
       || (type != PBM_MONO && max_color_idx < 0))
     goto error;
 
-  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))
     goto error;
 
+#if 0  /* TODO: color tables.  */
   /* Initialize the color hash table.  */
   init_color_table ();
+#endif
 
   if (type == PBM_MONO)
     {
@@ -11206,28 +11350,32 @@ pbm_load (f, img)
            
            if (r < 0 || g < 0 || b < 0)
              {
-               xfree (ximg->data);
-               ximg->data = NULL;
-               XDestroyImage (ximg);
+               x_destroy_x_image (ximg);
                image_error ("Invalid pixel value in image `%s'",
                             img->spec, Qnil);
                 goto error;
              }
            
            /* RGB values are now in the range 0..max_color_idx.
-              Scale this to the range 0..0xffff supported by X.  */
-           r = (double) r * 65535 / max_color_idx;
-           g = (double) g * 65535 / max_color_idx;
-           b = (double) b * 65535 / max_color_idx;
-           XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
+              Scale this to the range 0..0xff supported by W32.  */
+           r = (int) ((double) r * 255 / max_color_idx);
+           g = (int) ((double) g * 255 / max_color_idx);
+           b = (int) ((double) b * 255 / max_color_idx);
+           XPutPixel (ximg, x, y,
+#if 0  /* TODO: color tables.  */
+                      lookup_rgb_color (f, r, g, b));
+#else
+           PALETTERGB (r, g, b));
+#endif
          }
     }
-  
+
+#if 0  /* TODO: color tables.  */
   /* Store in IMG->colors the colors allocated for the image, and
      free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
-  
+#endif
   /* 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);
@@ -14549,14 +14697,16 @@ If the underlying system call fails, value is nil.  */)
 
     if (pfn_GetDiskFreeSpaceEx)
       {
+       /* Unsigned large integers cannot be cast to double, so
+          use signed ones instead.  */
        LARGE_INTEGER availbytes;
        LARGE_INTEGER freebytes;
        LARGE_INTEGER totalbytes;
 
        if (pfn_GetDiskFreeSpaceEx(rootname,
-                                  &availbytes,
-                                  &totalbytes,
-                                  &freebytes))
+                                  (ULARGE_INTEGER *)&availbytes,
+                                  (ULARGE_INTEGER *)&totalbytes,
+                                  (ULARGE_INTEGER *)&freebytes))
          value = list3 (make_float ((double) totalbytes.QuadPart),
                         make_float ((double) freebytes.QuadPart),
                         make_float ((double) availbytes.QuadPart));
@@ -15105,12 +15255,10 @@ versions of Windows) characters.  */);
   set_frame_fontset_func = x_set_font;
   check_window_system_func = check_w32;
 
-#if 0 /* TODO Image support for W32 */
+#ifdef IMAGES
   /* Images.  */
   Qxbm = intern ("xbm");
   staticpro (&Qxbm);
-  QCtype = intern (":type");
-  staticpro (&QCtype);
   QCconversion = intern (":conversion");
   staticpro (&QCconversion);
   QCheuristic_mask = intern (":heuristic-mask");
@@ -15125,6 +15273,7 @@ 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");
@@ -15133,10 +15282,12 @@ versions of Windows) characters.  */);
   staticpro (&QCpt_width);
   QCpt_height = intern (":pt-height");
   staticpro (&QCpt_height);
+#endif
   QCindex = intern (":index");
   staticpro (&QCindex);
   Qpbm = intern ("pbm");
   staticpro (&Qpbm);
+#endif
 
 #if HAVE_XPM
   Qxpm = intern ("xpm");
@@ -15163,13 +15314,16 @@ versions of Windows) characters.  */);
   staticpro (&Qpng);
 #endif
 
+#ifdef HAVE_IMAGES
   defsubr (&Sclear_image_cache);
+  defsubr (&Simage_size);
+  defsubr (&Simage_mask_p);
+#endif
 
 #if GLYPH_DEBUG
   defsubr (&Simagep);
   defsubr (&Slookup_image);
 #endif
-#endif /* TODO */
 
   hourglass_atimer = NULL;
   hourglass_shown_p = 0;
@@ -15193,10 +15347,14 @@ init_xfns ()
   image_types = NULL;
   Vimage_types = Qnil;
 
+#if HAVE_PBM
+  define_image_type (&pbm_type);
+#endif
+
 #if 0 /* TODO : Image support for W32 */
   define_image_type (&xbm_type);
   define_image_type (&gs_type);
-  define_image_type (&pbm_type);
+#endif
   
 #if HAVE_XPM
   define_image_type (&xpm_type);
@@ -15217,7 +15375,6 @@ init_xfns ()
 #if HAVE_PNG
   define_image_type (&png_type);
 #endif
-#endif /* TODO */
 }
 
 #undef abort