]> code.delx.au - gnu-emacs/commitdiff
Inserting Yamomotosan's changes for MacOSX image support, better support
authorSteven Tamm <steventamm@mac.com>
Thu, 26 Feb 2004 17:46:48 +0000 (17:46 +0000)
committerSteven Tamm <steventamm@mac.com>
Thu, 26 Feb 2004 17:46:48 +0000 (17:46 +0000)
of Asian fonts, and some long awaited header cleanup and centralization.

src/ChangeLog
src/dispextern.h
src/emacs.c
src/macfns.c
src/macgui.h
src/macmenu.c
src/macterm.c
src/macterm.h
src/s/darwin.h

index 892e7c621a52a8e3ea70975c04811f62853ac826..0fe8fbf9225b8672b572f76badfad00653d526bd 100644 (file)
@@ -1,3 +1,215 @@
+2004-02-26  YAMAMOTO Mitsuharu  <mituharu@math.s.chiba-u.ac.jp>
+       
+       * s/darwin.h (LD_SWITCH_SYSTEM_TEMACS): Add `-framework
+       QuickTime'.
+       
+       * dispextern.h [MAC_OSX]: Do not include Carbon/Carbon.h (now in
+       macgui.h).
+       
+       * emacs.c (main) [HAVE_CARBON]: Call init_xfns.
+       
+       * macgui.h [MAC_OSX]: Include Carbon/Carbon.h.
+       (mktime, DEBUG, Z, free, malloc, realloc, max, min)
+       (init_process) [MAC_OSX] : Avoid conflicts with Carbon/Carbon.h.
+       [!MAC_OSX]: Include QDOffscreen.h and Controls.h.
+       (INFINITY) [MAC_OSX]: Avoid conflict with definition in math.h.
+       (Bitmap): Remove typedef.
+       (Pixmap): Change int to GWorldPtr.
+
+       * macmenu.c [MAC_OSX]: Do not include Carbon/Carbon.h (now in
+       macgui.h).
+       
+       * macterm.h [MAC_OSX]: Do not include Carbon/Carbon.h (now in
+       macgui.h).
+       (RED16_FROM_ULONG, GREEN16_FROM_ULONG, BLUE16_FROM_ULONG): New
+       #define to extract 16-bit depth color components from unsigned
+       long representation.
+       (PIX_MASK_DRAW, PIX_MASK_RETAIN): New #define to represent pixel
+       colors used for masks.
+       (struct mac_display_info): Add color_p.  Remove n_cbits.
+       
+       * macfns.c: Include sys/types.h and sys/stat.h.
+       [MAC_OSX]: Do not include Carbon/Carbon.h (now in macgui.h).
+       Include QuickTime/QuickTime.h.
+       (XCreatePixmap, XCreatePixmapFromBitmapData, XFreePixmap)
+       (XSetForeground, mac_draw_line_to_pixmap): Add externs for
+       functions defined in macterm.c.
+       (XImagePtr): New typedef.  Corresponds to XImage * in xfns.c.
+       (ZPixmap): New #define for compatibility with xfns.c.
+       (XGetImage, XPutPixel, XGetPixel, XDestroyImage)
+       (x_create_x_image_and_pixmap, x_destroy_x_image, x_put_x_image)
+       (find_image_fsspec, image_load_qt_1, image_load_quicktime): New
+       functions.
+       (four_corners_best, x_create_x_image_and_pixmap)
+       (x_destroy_x_image, unwind_create_frame, x_disable_image,
+       (x_edge_detection, init_color_table, colors_in_color_table,
+       (lookup_rgb_color, lookup_pixel_color, postprocess_image)
+       (x_put_x_image, slurp_file, xbm_scan, xbm_load, xbm_load_image)
+       (xbm_image_p, xbm_read_bitmap_data, xbm_file_p, x_to_xcolors)
+       (x_from_xcolors, x_detect_edges): New declarations (from xfns.c).
+       (mac_color_map_lookup, x_to_mac_color): Fix Lisp_Object/unsigned
+       long mixup.
+       (mac_defined_color, x_to_x_colors): Use RED16_FROM_ULONG etc.
+       (x_decode_color): Don't use n_cbits (in struct mac_display_info).
+       (x_set_foreground_color, x_set_cursor_color): Sync with w32fns.c.
+       (x_set_cursor_type, Fxw_color_values, valid_image_p)
+       (image_value_type, parse_image_spec, image_ascent, x_clear_image)
+       (x_alloc_image_color, clear_image_cache, lookup_image)
+       (x_find_image_file, xbm_read_bitmap_file_data)
+       (enum xbm_keyword_index, xbm_format, xbm_image_p, xbm_scan)
+       (xbm_read_bitmap_data, xbm_load, pbm_image_p, pbm_scan_number)
+       (enum pbm_keyword_index, pbm_format, enum png_keyword_index)
+       (png_format, png_image_p, enum jpeg_keyword_index, jpeg_format)
+       (jpeg_image_p, enum tiff_keyword_index, tiff_format, tiff_image_p)
+       (enum gif_keyword_index, gif_format, gif_image_p): Sync with
+       xfns.c.
+       (x_make_gc): Sync with xfns.c.  Enclose unused `border_tile' with
+       #if 0.
+       (x_free_gcs): Sync with xfns.c.  Enclose unused `border_tile' with
+       #if 0.  Free white_relief.gc and black_relief.gc.
+       (unwind_create_frame, x_emboss, x_laplace, x_edge_detection): New
+       functions (from xfns.c).
+       (Fx_create_frame): Record unwind_create_frame.
+       (Fxw_display_color_p): Use dpyinfo->color_p.
+       (Fx_display_grayscale_p, Fx_display_planes): Don't use
+       dpyinfo->n_cbits.
+       (Fx_display_color_cells): Use dpyinfo->n_planes;
+       (QCmatrix, QCcolor_adjustment, QCmask, Qemboss, Qedge_detection)
+       (Qheuristic, cross_disabled_images, emboss_matrix)
+       (laplace_matrix): New variables (from xfns.c).
+       (Fimage_size, Fimage_mask_p, four_corners_best, image_background)
+       (x_clear_image_1, postprocess_image, slurp_file, xbm_load_image)
+       (xbm_file_p, x_to_xcolors, x_from_xcolors, x_detect_edges)
+       (image_background_transparent): New function (from xfns.c).  Use
+       PIX_MASK_DRAW/PIX_MASK_RETAIN.
+       (image_load_quicktime): Add declaration.
+       [MAC_OSX] (image_load_quartz2d): Likewise.
+       [MAC_OSX] (CGImageCreateWithPNGDataProviderProcType): New typedef.
+       [MAC_OSX] (MyCGImageCreateWithPNGDataProvider): New variable.
+       [MAC_OSX] (init_image_func_pointer, image_load_quartz2d): New
+       functions.
+       (xbm_load_image_from_file, x_laplace_read_row)
+       (x_laplace_write_row, pbm_read_file): Remove functions.
+       [HAVE_XPM] (enum xpm_keyword_index, xpm_format, xpm_image_p)
+       (xpm_load): Sync with xfns.c (although XPM is not supported yet).
+       (colors_in_color_table): Sync with xfns.c (although not used).
+       (lookup_rgb_color): Don't lookup color table.  Just do gamma
+       correction.
+       (COLOR_INTENSITY): New #define (from xfns.c).
+       (x_disable_image): New function (from xfns.c).  Use
+       PIX_MASK_DRAW/PIX_MASK_RETAIN.
+       (x_build_heuristic_mask): Sync with xfns.c.  Use
+       PIX_MASK_DRAW/PIX_MASK_RETAIN.
+       (HAVE_PBM): Remove #ifdef.
+       (pbm_load): Sync with xfns.c.  Set img->width and img->height
+       before IMAGE_BACKGROUND.
+       (png_image_p, png_load): Don't enclose declarations with #if
+       HAVE_PNG.
+       (Qpng, enum png_keyword_index, png_format, png_type, png_image_p):
+       Don't enclose with #if HAVE_PNG.
+       [!HAVE_PNG] (png_load) [MAC_OSX]: Use image_load_quartz2d if a
+       symbol _CGImageCreateWithPNGDataProvider is defined.  Otherwise
+       use image_load_quicktime.
+       [!HAVE_PNG] (png_load) [!MAC_OSX]: Use image_load_quicktime.
+       [HAVE_PNG] (png_load): Sync with xfns.c.  Use
+       PIX_MASK_DRAW/PIX_MASK_RETAIN.
+       (jpeg_image_p, jpeg_load): Don't enclose declarations with #if
+       HAVE_JPEG.
+       (Qjpeg, enum jpeg_keyword_index, jpeg_format, jpeg_type)
+       (jpeg_image_p): Don't enclose with #if HAVE_JPEG.
+       [!HAVE_JPEG] (jpeg_load) [MAC_OSX]: Use image_load_quartz2d.
+       [!HAVE_JPEG] (jpeg_load) [!MAC_OSX]: Use image_load_quicktime.
+       [HAVE_JPEG] (jpeg_load): Sync with xfns.c.
+       (tiff_image_p, tiff_load): Don't enclose declarations with #if
+       HAVE_TIFF.
+       (Qtiff, enum tiff_keyword_index, tiff_format, tiff_type)
+       (tiff_image_p): Don't enclose with #if HAVE_TIFF.
+       [!HAVE_TIFF] (tiff_load): Use image_load_quicktime.
+       [HAVE_TIFF] (tiff_error_handler, tiff_warning_handler): New
+       functions (from xfns.c).
+       [HAVE_TIFF] (tiff_load): Sync with xfns.c.
+       (gif_image_p, gif_load): Don't enclose declarations with #if
+       HAVE_GIF.
+       (Qgif, enum gif_keyword_index, gif_format, gif_type, gif_image_p):
+       Don't enclose with #if HAVE_GIF.
+       [!HAVE_GIF] (gif_load): Use Quicktime Movie Toolbox if it is
+       animated gif.  Otherwise use image_load_quicktime.
+       [HAVE_GIF] (gif_lib.h): Temporarily define DrawText as
+       gif_DrawText to avoid conflict with QuickdrawText.h.
+       [HAVE_GIF] (gif_load): Sync with xfns.c.
+       (enum gs_keyword_index, gs_format, gs_image_p, gs_load)
+       [HAVE_GHOSTSCRIPT] (x_kill_gs_process): Sync with xfns.c (although
+       Ghostscript is not supported yet).
+       (syms_of_macfns): Initialize Qemboss, Qedge_detection, Qheuristic,
+       QCmatrix, QCcolor_adjustment, and QCmask.  Add DEFVAR_BOOL
+       cross_disabled_images (from xfns.c).  Remove #if 0 for supported
+       image types.  Remove #if HAVE_JPEG, HAVE_TIFF, HAVE_GIF, and
+       HAVE_PNG.  Add defsubr for Simage_size and Simage_mask_p.
+       (init_xfns): Remove #if HAVE_JPEG, HAVE_TIFF, HAVE_GIF, and
+       HAVE_PNG.  Call EnterMovies to support animated gifs.  Call
+       init_image_func_pointer to bind a symbol
+       _CGImageCreateWithPNGDataProvider if it is defined.
+       
+       * macterm.c [MAC_OSX]: Do not include Carbon/Carbon.h (now in
+       macgui.h).
+       (x_draw_bar_cursor): Sync declaration with xterm.c.
+       (XFreePixmap, mac_draw_rectangle_to_pixmap, mac_copy_area)
+       (mac_copy_area_to_pixmap): Implementation with GWorld (offscreen
+       graphics).
+       (mac_set_forecolor, mac_set_backcolor): Use RED16_FROM_ULONG etc.
+       (mac_draw_line_to_pixmap, XCreatePixmap)
+       (XCreatePixmapFromBitmapData, mac_fill_rectangle_to_pixmap)
+       (mac_copy_area_with_mask, mac_copy_area_with_mask_to_pixmap): New
+       functions.
+       (mac_draw_bitmap) [TARGET_API_MAC_CARBON]: Use
+       GetPortBitMapForCopyBits instead of the cast to Bitmap *.  Cast
+       bits to char *.
+       (reflect_byte): New function (from w32fns.c).
+       (mac_create_bitmap_from_bitmap_data): Use it and don't stuff bits
+       due to byte alignment.
+       (mac_scroll_area) [TARGET_API_MAC_CARBON]: Use
+       GetPortBitMapForCopyBits instead of the cast to Bitmap *.
+       (XSetForeground): Remove static (now used in macfns.c).
+       (HIGHLIGHT_COLOR_DARK_BOOST_LIMIT): New #define (from w32term.c).
+       (mac_alloc_lighter_color, x_destroy_window): Sync with w32term.c.
+       (x_setup_relief_color, x_setup_relief_colors, x_draw_box_rect)
+       (x_draw_glyph_string_box, x_draw_image_foreground)
+       (x_draw_image_foreground_1, x_draw_image_glyph_string)
+       (x_draw_stretch_glyph_string, x_draw_glyph_string)
+       (x_draw_hollow_cursor, x_draw_bar_cursor, mac_draw_window_cursor):
+       Sync with xterm.c.
+       (x_draw_relief_rect): Sync with xterm.c.  Make 1 pixel shorter
+       than the xterm.c version when a strictly horizontal or vertical
+       line is drawn.
+       (XTset_terminal_window): Add static.
+       (x_make_frame_visible): Add UNBLOCK_INPUT.
+       (x_free_frame_resources): New funcion (from xterm.c).
+       (XTread_socket): Call handle_tool_bar_click if mouse up/down event
+       occurs in tool bar area.
+       (mac_initialize_display_info): Remove dpyinfo->n_cbits.  Set
+       dpyinfo->color_p.  Determine dpyinfo->n_planes using HasDepth.
+       Initialize image cache.
+       (stricmp, wildstrieq, mac_font_pattern_match, mac_font_match):
+       Enclose unused functions with #if 0.
+       (Qbig5, Qcn_gb, Qsjis, Qeuc_kr): New variables.
+       (decode_mac_font_name): New function to apply code conversions
+       from a mac font name to an XLFD font name according to its script
+       code.
+       (x_font_name_to_mac_font_name): Apply code conversion from an XLFD
+       font name to a mac font name according to REGISTRY and ENCODING
+       fields.
+       (init_font_name_table) [TARGET_API_MAC_CARBON]: Don't use a font
+       whose name starts with `.'.
+       (init_font_name_table): Use decode_mac_font_name.  Add both
+       jisx0208.1983-sjis and jisx0201.1976-0 entries if the script code
+       of a font is smJapanese.
+       (mac_do_list_fonts): New function to list fonts that match a given
+       pattern.
+       (x_list_fonts, XLoadQueryFont): Use it.
+       (XLoadQueryFont): Set rbearing field for each variable width
+       character to avoid needless redraw.
+       (syms_of_macterm): Initialize Qbig5, Qcn_gb, Qsjis, and Qeuc_kr.
+
 2004-02-26  Kim F. Storm  <storm@cua.dk>
 
        * keyboard.c (NREAD_INPUT_EVENTS): Temporarily increase to 512
index fc27c6e185e89a603be68e11bc0b028d1dc7b5ca..bb421e0618b524e512b34c32ff4eee796e45c687 100644 (file)
@@ -61,38 +61,8 @@ typedef struct w32_display_info Display_Info;
 #ifdef HAVE_CARBON
 #include "macgui.h"
 typedef struct mac_display_info Display_Info;
-
-/* Include Carbon.h to define Cursor and Rect.  */
-#undef mktime
-#undef DEBUG
-#undef Z
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef Z
-#define Z (current_buffer->text->z)
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
-
 #endif
 
-
 #ifndef NativeRectangle
 #define NativeRectangle int
 #endif
index 283f7949bfd1a79ccd3213aec982b0125a6bb18e..66a2af72fb5f8a74473301843bfdadda5c52bd3d 100644 (file)
@@ -1589,7 +1589,7 @@ main (argc, argv
   init_vmsproc ();     /* And this too.  */
 #endif /* VMS */
   init_sys_modes ();   /* Init system terminal modes (RAW or CBREAK, etc.).  */
-#if defined (HAVE_X_WINDOWS) || defined (WINDOWSNT)
+#if defined (HAVE_X_WINDOWS) || defined (WINDOWSNT) || defined (HAVE_CARBON)
   init_xfns ();
 #endif /* HAVE_X_WINDOWS */
   init_fns ();
index a01811048fe71c5afc4ed64fd2872fe0455bd4b1..1b854489480758e2b4c4bce231f4035d2aba83ad 100644 (file)
@@ -54,6 +54,8 @@ static unsigned char gray_bits[] = {
 /*#include <commdlg.h>
 #include <shellapi.h>*/
 #include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -62,32 +64,7 @@ static unsigned char gray_bits[] = {
 #endif
 
 #ifdef MAC_OSX
-#undef mktime
-#undef DEBUG
-#undef Z
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef Z
-#define Z (current_buffer->text->z)
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
+#include <QuickTime/QuickTime.h>
 #else /* not MAC_OSX */
 #include <Windows.h>
 #include <Gestalt.h>
@@ -209,6 +186,12 @@ extern struct font_info *x_load_font (struct frame *, char *, int);
 extern void x_find_ccl_program (struct font_info *);
 extern struct font_info *x_query_font (struct frame *, char *);
 extern void mac_initialize ();
+extern Pixmap XCreatePixmap (Display *, WindowPtr, unsigned int, unsigned int, unsigned int);
+extern Pixmap XCreatePixmapFromBitmapData (Display *, WindowPtr, char *, unsigned int, unsigned int, unsigned long, unsigned long, unsigned int);
+extern void XFreePixmap (Display *, Pixmap);
+extern void XSetForeground (Display *, GC, unsigned long);
+extern void mac_draw_line_to_pixmap (Display *, Pixmap, GC, int, int, int, int);
+
 
 /* compare two strings ignoring case */
 
@@ -552,13 +535,89 @@ x_destroy_all_bitmaps (dpyinfo)
       xfree (dpyinfo->bitmaps[i].bitmap_data);
   dpyinfo->bitmaps_last = 0;
 }
+
+
+\f
+/* Mac equivalent of XImage.  */
+typedef Pixmap XImagePtr;
+#define ZPixmap 0              /* arbitrary */
+
+static XImagePtr
+XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
+     Display *display;         /* not used */
+     Pixmap pixmap;
+     int x, y;                 /* not used */
+     unsigned int width, height; /* not used */
+     unsigned long plane_mask;         /* not used */
+     int format;               /* not used */
+{
+#if GLYPH_DEBUG
+  xassert (x == 0 && y == 0);
+  {
+    Rect ri, rp;
+    SetRect (&ri, 0, 0, width, height);
+    xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
+  }
+  xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
+#endif
+
+  LockPixels (GetGWorldPixMap (pixmap));
+
+  return pixmap;
+}
+
+static void
+XPutPixel (ximage, x, y, pixel)
+     XImagePtr ximage;
+     int x, y;
+     unsigned long pixel;
+{
+  RGBColor color;
+
+  SetGWorld (ximage, NULL);
+
+  color.red = RED16_FROM_ULONG (pixel);
+  color.green = GREEN16_FROM_ULONG (pixel);
+  color.blue = BLUE16_FROM_ULONG (pixel);
+  SetCPixel (x, y, &color);
+}
+
+static unsigned long
+XGetPixel (ximage, x, y)
+     XImagePtr ximage;
+     int x, y;
+{
+  RGBColor color;
+
+  SetGWorld (ximage, NULL);
+
+  GetCPixel (x, y, &color);
+  return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
+}
+
+static void
+XDestroyImage (ximg)
+     XImagePtr ximg;
+{
+  UnlockPixels (GetGWorldPixMap (ximg));
+}
+
+
 \f
-/* Connect the frame-parameter names for W32 frames
-   to the ways of passing the parameter values to the window system.
+/* Useful functions defined in the section
+   `Image type independent image structures' below. */
+
+static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
+                                           unsigned long height));
+
+static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
+                                           int depth, XImagePtr *ximg,
+                                           Pixmap *pixmap));
+
+static void x_destroy_x_image P_ ((XImagePtr ximg));
 
-   The name of a parameter, as a Lisp symbol,
-   has an `x-frame-parameter' property which is an integer in Lisp
-   but can be interpreted as an `enum x_frame_parm' in C.  */
+static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
+static void x_disable_image P_ ((struct frame *, struct image *));
 
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
@@ -581,6 +640,13 @@ static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
                                                             Lisp_Object,
                                                             char *, char *,
                                                             int));
+static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
+                                 Lisp_Object));
+static void init_color_table P_ ((void));
+static void free_color_table P_ ((void));
+static unsigned long *colors_in_color_table P_ ((int *n));
+static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
+static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
 
 /* Store the screen positions of frame F into XPTR and YPTR.
    These are the positions of the containing window manager window,
@@ -1382,7 +1448,7 @@ colormap_t mac_color_map[] =
   { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
 };
 
-unsigned long
+Lisp_Object
 mac_color_map_lookup (colorname)
      char *colorname;
 {
@@ -1394,7 +1460,7 @@ mac_color_map_lookup (colorname)
   for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
     if (stricmp (colorname, mac_color_map[i].name) == 0)
       {
-        ret = mac_color_map[i].color;
+        ret = make_number (mac_color_map[i].color);
         break;
       }
 
@@ -1463,7 +1529,7 @@ x_to_mac_color (colorname)
              if (i == 2)
                {
                  UNBLOCK_INPUT;
-                 return (colorval);
+                 return make_number (colorval);
                }
              color = end;
            }
@@ -1516,7 +1582,7 @@ x_to_mac_color (colorname)
              if (*end != '\0')
                break;
              UNBLOCK_INPUT;
-             return (colorval);
+             return make_number (colorval);
            }
          if (*end != '/')
            break;
@@ -1557,7 +1623,7 @@ x_to_mac_color (colorname)
              if (*end != '\0')
                break;
              UNBLOCK_INPUT;
-             return (colorval);
+             return make_number (colorval);
            }
          if (*end != '/')
            break;
@@ -1616,9 +1682,9 @@ mac_defined_color (f, color, color_def, alloc)
         }
 
       color_def->pixel = mac_color_ref;
-      color_def->red = RED_FROM_ULONG (mac_color_ref);
-      color_def->green = GREEN_FROM_ULONG (mac_color_ref);
-      color_def->blue = BLUE_FROM_ULONG (mac_color_ref);
+      color_def->red = RED16_FROM_ULONG (mac_color_ref);
+      color_def->green = GREEN16_FROM_ULONG (mac_color_ref);
+      color_def->blue = BLUE16_FROM_ULONG (mac_color_ref);
 
       return 1;
     }
@@ -1649,8 +1715,7 @@ x_decode_color (f, arg, def)
     return WHITE_PIX_DEFAULT (f);
 
 #if 0
-  if ((FRAME_MAC_DISPLAY_INFO (f)->n_planes
-       * FRAME_MAC_DISPLAY_INFO (f)->n_cbits) == 1)
+  if (FRAME_MAC_DISPLAY_INFO (f)->n_planes) == 1)
     return def;
 #endif
 
@@ -1674,8 +1739,11 @@ x_set_foreground_color (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  FRAME_FOREGROUND_PIXEL (f)
-    = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+  unsigned long fg, old_fg;
+
+  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+  old_fg = FRAME_FOREGROUND_PIXEL (f);
+  FRAME_FOREGROUND_PIXEL (f) = fg;
 
   if (FRAME_MAC_WINDOW (f) != 0)
     {
@@ -1856,36 +1924,42 @@ x_set_cursor_color (f, arg, oldval)
      struct frame *f;
      Lisp_Object arg, oldval;
 {
-  unsigned long fore_pixel;
+  unsigned long fore_pixel, pixel;
 
   if (!NILP (Vx_cursor_fore_pixel))
     fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
                                 WHITE_PIX_DEFAULT (f));
   else
     fore_pixel = FRAME_BACKGROUND_PIXEL (f);
-  f->output_data.mac->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+
+  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
 
   /* Make sure that the cursor color differs from the background color.  */
-  if (f->output_data.mac->cursor_pixel == FRAME_BACKGROUND_PIXEL (f))
+  if (pixel == FRAME_BACKGROUND_PIXEL (f))
     {
-      f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel;
-      if (f->output_data.mac->cursor_pixel == fore_pixel)
+      pixel = f->output_data.mac->mouse_pixel;
+      if (pixel == fore_pixel)
        fore_pixel = FRAME_BACKGROUND_PIXEL (f);
     }
-  FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
 
-#if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */
+  f->output_data.mac->cursor_foreground_pixel = fore_pixel;
+  f->output_data.mac->cursor_pixel = pixel;
+
   if (FRAME_MAC_WINDOW (f) != 0)
     {
+      BLOCK_INPUT;
+      /* Update frame's cursor_gc.  */
+      f->output_data.mac->cursor_gc->foreground = fore_pixel;
+      f->output_data.mac->cursor_gc->background = pixel;
+
+      UNBLOCK_INPUT;
+
       if (FRAME_VISIBLE_P (f))
        {
-         BLOCK_INPUT;
-         display_and_set_cursor (f, 0);
-         display_and_set_cursor (f, 1);
-         UNBLOCK_INPUT;
+         x_update_cursor (f, 0);
+         x_update_cursor (f, 1);
        }
     }
-#endif
 
   update_face_from_frame_parameter (f, Qcursor_color, arg);
 }
@@ -1893,11 +1967,13 @@ 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 a window.  */
+
 void
 x_set_border_pixel (f, pix)
      struct frame *f;
      int pix;
 {
+
   f->output_data.mac->border_pixel = pix;
 
   if (FRAME_MAC_WINDOW (f) != 0 && f->border_width > 0)
@@ -1926,6 +2002,7 @@ x_set_border_color (f, arg, oldval)
   update_face_from_frame_parameter (f, Qborder_color, arg);
 }
 
+
 void
 x_set_cursor_type (f, arg, oldval)
      FRAME_PTR f;
@@ -1933,9 +2010,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
 #if 0 /* MAC_TODO: really no icon for Mac */
@@ -2597,7 +2673,7 @@ x_make_gc (f)
 
   BLOCK_INPUT;
 
-  /* Create the GC's of this frame.
+  /* Create the GCs of this frame.
      Note that many default values are used.  */
 
   /* Normal video */
@@ -2629,10 +2705,104 @@ x_make_gc (f)
   f->output_data.mac->white_relief.gc = 0;
   f->output_data.mac->black_relief.gc = 0;
 
+#if 0
+  /* Create the gray border tile used when the pointer is not in
+     the frame.  Since this depends on the frame's pixel values,
+     this must be done on a per-frame basis.  */
+  f->output_data.x->border_tile
+    = (XCreatePixmapFromBitmapData
+       (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
+       gray_bits, gray_width, gray_height,
+       f->output_data.x->foreground_pixel,
+       f->output_data.x->background_pixel,
+       DefaultDepth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f))));
+#endif
+
+  UNBLOCK_INPUT;
+}
+
+
+/* Free what was was allocated in x_make_gc.  */
+
+void
+x_free_gcs (f)
+     struct frame *f;
+{
+  Display *dpy = FRAME_MAC_DISPLAY (f);
+
+  BLOCK_INPUT;
+
+  if (f->output_data.mac->normal_gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->normal_gc);
+      f->output_data.mac->normal_gc = 0;
+    }
+
+  if (f->output_data.mac->reverse_gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->reverse_gc);
+      f->output_data.mac->reverse_gc = 0;
+    }
+
+  if (f->output_data.mac->cursor_gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->cursor_gc);
+      f->output_data.mac->cursor_gc = 0;
+    }
+
+#if 0
+  if (f->output_data.mac->border_tile)
+    {
+      XFreePixmap (dpy, f->output_data.mac->border_tile);
+      f->output_data.mac->border_tile = 0;
+    }
+#endif
+
+  if (f->output_data.mac->white_relief.gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->white_relief.gc);
+      f->output_data.mac->white_relief.gc = 0;
+    }
+
+  if (f->output_data.mac->black_relief.gc)
+    {
+      XFreeGC (dpy, f->output_data.mac->black_relief.gc);
+      f->output_data.mac->black_relief.gc = 0;
+    }
+
   UNBLOCK_INPUT;
 }
 
 
+/* Handler for signals raised during x_create_frame and
+   x_create_top_frame.  FRAME is the frame which is partially
+   constructed.  */
+
+static Lisp_Object
+unwind_create_frame (frame)
+     Lisp_Object frame;
+{
+  struct frame *f = XFRAME (frame);
+
+  /* If frame is ``official'', nothing to do.  */
+  if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
+    {
+#if GLYPH_DEBUG
+      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+#endif
+
+      x_free_frame_resources (f);
+
+      /* Check that reference counts are indeed correct.  */
+      xassert (dpyinfo->reference_count == dpyinfo_refcount);
+      xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
+      return Qt;
+    }
+
+  return Qnil;
+}
+
+
 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        1, 1, 0,
        doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
@@ -2736,10 +2906,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   FRAME_FONTSET (f) = -1;
   f->output_data.mac->scroll_bar_foreground_pixel = -1;
   f->output_data.mac->scroll_bar_background_pixel = -1;
-
-#if 0
-  FRAME_FONTSET (f) = -1;
-#endif
+  record_unwind_protect (unwind_create_frame, frame);
 
   f->icon_name
     = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
@@ -2790,17 +2957,18 @@ This function is an internal primitive--use `make-frame' instead.  */)
     /* First, try whatever font the caller has specified.  */
     if (STRINGP (font))
       {
-        tem = Fquery_fontset (font, Qnil);
-        if (STRINGP (tem))
-          font = x_new_fontset (f, SDATA (tem));
-        else
-          font = x_new_font (f, SDATA (font));
+       tem = Fquery_fontset (font, Qnil);
+       if (STRINGP (tem))
+         font = x_new_fontset (f, SDATA (tem));
+       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, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
     /* If those didn't work, look for something which will at least work.  */
-    if (!STRINGP (font))
+    if (! STRINGP (font))
       font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
     if (! STRINGP (font))
       font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
@@ -3011,12 +3179,9 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
     {
       Lisp_Object rgb[3];
 
-      rgb[0] = make_number ((RED_FROM_ULONG (foo.pixel) << 8)
-                            | RED_FROM_ULONG (foo.pixel));
-      rgb[1] = make_number ((GREEN_FROM_ULONG (foo.pixel) << 8)
-                            | GREEN_FROM_ULONG (foo.pixel));
-      rgb[2] = make_number ((BLUE_FROM_ULONG (foo.pixel) << 8)
-                            | BLUE_FROM_ULONG (foo.pixel));
+      rgb[0] = make_number (foo.red);
+      rgb[1] = make_number (foo.green);
+      rgb[2] = make_number (foo.blue);
       return Flist (3, rgb);
     }
   else
@@ -3030,7 +3195,7 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
 {
   struct mac_display_info *dpyinfo = check_x_display_info (display);
 
-  if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
+  if (!dpyinfo->color_p)
     return Qnil;
 
   return Qt;
@@ -3048,7 +3213,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 {
   struct mac_display_info *dpyinfo = check_x_display_info (display);
 
-  if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
+  if (dpyinfo->n_planes <= 1)
     return Qnil;
 
   return Qt;
@@ -3093,7 +3258,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 {
   struct mac_display_info *dpyinfo = check_x_display_info (display);
 
-  return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
+  return make_number (dpyinfo->n_planes);
 }
 
 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
@@ -3108,7 +3273,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
   struct mac_display_info *dpyinfo = check_x_display_info (display);
 
   /* MAC_TODO: check whether this is right */
-  return make_number ((unsigned long) (pow (2, dpyinfo->n_cbits)));
+  return make_number (dpyinfo->n_planes >= 8 ? 256 : 1 << dpyinfo->n_planes - 1);
 }
 
 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
@@ -3446,6 +3611,7 @@ If DISPLAY is omitted or nil, that stands for the selected frame's display.  */)
   return Qnil;
 }
 
+
 \f
 /***********************************************************************
                            Image types
@@ -3470,11 +3636,11 @@ extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
 extern Lisp_Object QCdata, QCtype;
 Lisp_Object QCascent, QCmargin, QCrelief;
 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex;
+Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
 
 /* Other symbols.  */
 
-Lisp_Object Qlaplace;
+Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
 
 /* Time in seconds after which images should be removed from the cache
    if not displayed.  */
@@ -3487,6 +3653,7 @@ static void define_image_type P_ ((struct image_type *type));
 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
 static void x_laplace P_ ((struct frame *, struct image *));
+static void x_emboss P_ ((struct frame *, struct image *));
 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
                                       Lisp_Object));
 
@@ -3540,11 +3707,22 @@ valid_image_p (object)
 
   if (IMAGEP (object))
     {
-      Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
-      struct image_type *type = lookup_image_type (symbol);
+      Lisp_Object tem;
 
-      if (type)
-       valid_p = type->valid_p (object);
+      for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
+       if (EQ (XCAR (tem), QCtype))
+         {
+           tem = XCDR (tem);
+           if (CONSP (tem) && SYMBOLP (XCAR (tem)))
+             {
+               struct image_type *type;
+               type = lookup_image_type (XCAR (tem));
+               if (type)
+                 valid_p = type->valid_p (object);
+             }
+
+           break;
+         }
     }
 
   return valid_p;
@@ -3554,8 +3732,8 @@ valid_image_p (object)
 /* Log error message with format string FORMAT and argument ARG.
    Signaling an error, e.g. when an image cannot be loaded, is not a
    good idea because this would interrupt redisplay, and the error
-   message display would lead to another redisplay. This function
-   therefore simply displays a message. */
+   message display would lead to another redisplay.  This function
+   therefore simply displays a message.  */
 
 static void
 image_error (format, arg1, arg2)
@@ -3575,6 +3753,7 @@ enum image_value_type
 {
   IMAGE_DONT_CHECK_VALUE_TYPE,
   IMAGE_STRING_VALUE,
+  IMAGE_STRING_OR_NIL_VALUE,
   IMAGE_SYMBOL_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
@@ -3654,7 +3833,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
          break;
 
       if (i == nkeywords)
-        continue;
+       continue;
 
       /* Record that we recognized the keyword.  If a keywords
         was found more than once, it's an error.  */
@@ -3672,6 +3851,11 @@ parse_image_spec (spec, keywords, nkeywords, type)
            return 0;
          break;
 
+       case IMAGE_STRING_OR_NIL_VALUE:
+         if (!STRINGP (value) && !NILP (value))
+           return 0;
+         break;
+
        case IMAGE_SYMBOL_VALUE:
          if (!SYMBOLP (value))
            return 0;
@@ -3691,7 +3875,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
            break;
          return 0;
 
-        case IMAGE_ASCENT_VALUE:
+       case IMAGE_ASCENT_VALUE:
          if (SYMBOLP (value) && EQ (value, Qcenter))
            break;
          else if (INTEGERP (value)
@@ -3780,6 +3964,63 @@ image_spec_value (spec, key, found)
 }
 
 
+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 / FRAME_COLUMN_WIDTH (f)),
+                     make_float ((double) height / FRAME_LINE_HEIGHT (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;
+}
+
 
 \f
 /***********************************************************************
@@ -3876,8 +4117,12 @@ image_ascent (img, face)
   if (img->ascent == CENTERED_IMAGE_ASCENT)
     {
       if (face->font)
-       ascent = height / 2 - (FONT_DESCENT(face->font)
-                               - FONT_BASE(face->font)) / 2;
+       /* This expression is arranged so that if the image can't be
+          exactly centered, it will be moved slightly up.  This is
+          because a typical font is `top-heavy' (due to the presence
+          uppercase letters), so the image placement should err towards
+          being top-heavy too.  It also just generally looks better.  */
+       ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
       else
        ascent = height / 2;
     }
@@ -3887,58 +4132,165 @@ image_ascent (img, face)
   return ascent;
 }
 
+\f
+/* Image background colors.  */
+
+static unsigned long
+four_corners_best (ximg, width, height)
+     XImagePtr ximg;
+     unsigned long width, height;
+{
+  unsigned long 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);
+
+  /* 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;
+
+      if (n > best_count)
+       best = corners[i], best_count = n;
+    }
+
+  return best;
+}
+
+/* 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.  */
+
+unsigned long
+image_background (img, f, ximg)
+     struct image *img;
+     struct frame *f;
+     XImagePtr ximg;
+{
+  if (! img->background_valid)
+    /* IMG doesn't have a background yet, try to guess a reasonable value.  */
+    {
+      int free_ximg = !ximg;
+
+      if (! ximg)
+       ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
+                         0, 0, img->width, img->height, ~0, ZPixmap);
+
+      img->background = four_corners_best (ximg, img->width, img->height);
+
+      if (free_ximg)
+       XDestroyImage (ximg);
+
+      img->background_valid = 1;
+    }
+
+  return img->background;
+}
+
+/* Return the `background_transparent' field of IMG.  If IMG doesn't
+   have one yet, it is guessed heuristically.  If non-zero, MASK is an
+   existing XImage object to use for the heuristic.  */
+
+int
+image_background_transparent (img, f, mask)
+     struct image *img;
+     struct frame *f;
+     XImagePtr mask;
+{
+  if (! img->background_transparent_valid)
+    /* IMG doesn't have a background yet, try to guess a reasonable value.  */
+    {
+      if (img->mask)
+       {
+         int free_mask = !mask;
+
+         if (! mask)
+           mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
+                             0, 0, img->width, img->height, ~0, ZPixmap);
+
+         img->background_transparent
+           = four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN (f);
+
+         if (free_mask)
+           XDestroyImage (mask);
+       }
+      else
+       img->background_transparent = 0;
+
+      img->background_transparent_valid = 1;
+    }
+
+  return img->background_transparent;
+}
 
 \f
 /***********************************************************************
                  Helper functions for X image types
  ***********************************************************************/
 
+static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
+                                int, int));
 static void x_clear_image P_ ((struct frame *f, struct image *img));
 static unsigned long x_alloc_image_color P_ ((struct frame *f,
                                              struct image *img,
                                              Lisp_Object color_name,
                                              unsigned long dflt));
 
-/* Free X resources of image IMG which is used on frame F.  */
+
+/* Clear X resources of image IMG on frame F.  PIXMAP_P non-zero means
+   free the pixmap if any.  MASK_P non-zero means clear the mask
+   pixmap if any.  COLORS_P non-zero means free colors allocated for
+   the image, if any.  */
 
 static void
-x_clear_image (f, img)
+x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
      struct frame *f;
      struct image *img;
+     int pixmap_p, mask_p, colors_p;
 {
-#if 0 /* MAC_TODO: W32 image support  */
-
-  if (img->pixmap)
+  if (pixmap_p && img->pixmap)
     {
-      BLOCK_INPUT;
-      XFreePixmap (NULL, img->pixmap);
-      img->pixmap = 0;
-      UNBLOCK_INPUT;
+      XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
+      img->pixmap = NULL;
+      img->background_valid = 0;
     }
 
-  if (img->ncolors)
+  if (mask_p && img->mask)
     {
-      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
-         && class != StaticGray
-         && class != TrueColor)
-       {
-         Colormap cmap;
-         BLOCK_INPUT;
-         cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
-         XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
-                      img->ncolors, 0);
-         UNBLOCK_INPUT;
-       }
+      XFreePixmap (FRAME_X_DISPLAY (f), 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 /* MAC_TODO */
+}
+
+/* Free X resources of image IMG which is used on frame F.  */
+
+static void
+x_clear_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  BLOCK_INPUT;
+  x_clear_image_1 (f, img, 1, 1, 1);
+  UNBLOCK_INPUT;
 }
 
 
@@ -3954,13 +4306,12 @@ x_alloc_image_color (f, img, color_name, dflt)
      Lisp_Object color_name;
      unsigned long dflt;
 {
-#if 0 /* MAC_TODO: allocing colors.  */
   XColor color;
   unsigned long result;
 
   xassert (STRINGP (color_name));
 
-  if (w32_defined_color (f, SDATA (color_name), &color, 1))
+  if (mac_defined_color (f, SDATA (color_name), &color, 1))
     {
       /* This isn't called frequently so we get away with simply
         reallocating the color vector to the needed size, here.  */
@@ -3973,9 +4324,8 @@ x_alloc_image_color (f, img, color_name, dflt)
     }
   else
     result = dflt;
+
   return result;
-#endif /* MAC_TODO */
-  return 0;
 }
 
 
@@ -3985,6 +4335,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 *));
 
 
 /* Return a new, initialized image cache that is allocated from the
@@ -4049,20 +4400,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;
            }
        }
 
@@ -4070,11 +4424,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_MAC_P (f)
+                 && FRAME_X_IMAGE_CACHE (f) == c)
+               clear_current_matrices (f);
+           }
+
          ++windows_or_buffers_changed;
        }
+
+      UNBLOCK_INPUT;
     }
 }
 
@@ -4084,7 +4449,7 @@ DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
        doc: /* Clear the image cache of FRAME.
 FRAME nil or omitted means use the selected frame.
 FRAME t means clear the image caches of all frames.  */)
-  (frame)
+     (frame)
      Lisp_Object frame;
 {
   if (EQ (frame, Qt))
@@ -4102,27 +4467,102 @@ FRAME t means clear the image caches of all frames.  */)
 }
 
 
-/* Return the id of image with Lisp specification SPEC on frame F.
-   SPEC must be a valid Lisp image specification (see valid_image_p).  */
+/* Compute masks and transform image IMG on frame F, as specified
+   by the image's specification,  */
 
-int
-lookup_image (f, spec)
+static void
+postprocess_image (f, img)
      struct frame *f;
-     Lisp_Object spec;
+     struct image *img;
 {
-  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
-  struct image *img;
-  int i;
-  unsigned hash;
-  struct gcpro gcpro1;
-  EMACS_TIME now;
+  /* Manipulation of the image's mask.  */
+  if (img->pixmap)
+    {
+      Lisp_Object conversion, spec;
+      Lisp_Object mask;
 
-  /* F must be a window-system frame, and SPEC must be a valid image
-     specification.  */
-  xassert (FRAME_WINDOW_P (f));
-  xassert (valid_image_p (spec));
+      spec = img->spec;
 
-  GCPRO1 (spec);
+      /* `:heuristic-mask t'
+        `:mask heuristic'
+        means build a mask heuristically.
+        `:heuristic-mask (R G B)'
+        `:mask (heuristic (R G B))'
+        means build a mask from color (R G B) in the
+        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)
+                  && EQ (XCAR (mask), Qheuristic))
+           {
+             if (CONSP (XCDR (mask)))
+               x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
+             else
+               x_build_heuristic_mask (f, img, XCDR (mask));
+           }
+         else if (NILP (mask) && found_p && img->mask)
+           {
+             XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+             img->mask = NULL;
+           }
+       }
+
+
+      /* Should we apply an image transformation algorithm?  */
+      conversion = image_spec_value (spec, QCconversion, NULL);
+      if (EQ (conversion, Qdisabled))
+       x_disable_image (f, img);
+      else if (EQ (conversion, Qlaplace))
+       x_laplace (f, img);
+      else if (EQ (conversion, Qemboss))
+       x_emboss (f, img);
+      else if (CONSP (conversion)
+              && EQ (XCAR (conversion), Qedge_detection))
+       {
+         Lisp_Object tem;
+         tem = XCDR (conversion);
+         if (CONSP (tem))
+           x_edge_detection (f, img,
+                             Fplist_get (tem, QCmatrix),
+                             Fplist_get (tem, QCcolor_adjustment));
+       }
+    }
+}
+
+
+/* Return the id of image with Lisp specification SPEC on frame F.
+   SPEC must be a valid Lisp image specification (see valid_image_p).  */
+
+int
+lookup_image (f, spec)
+     struct frame *f;
+     Lisp_Object spec;
+{
+  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+  struct image *img;
+  int i;
+  unsigned hash;
+  struct gcpro gcpro1;
+  EMACS_TIME now;
+
+  /* F must be a window-system frame, and SPEC must be a valid image
+     specification.  */
+  xassert (FRAME_WINDOW_P (f));
+  xassert (valid_image_p (spec));
+
+  GCPRO1 (spec);
 
   /* Look up SPEC in the hash table of the image cache.  */
   hash = sxhash (spec, 0);
@@ -4135,11 +4575,12 @@ lookup_image (f, spec)
   /* If not found, create a new image and cache it.  */
   if (img == NULL)
     {
+      extern Lisp_Object Qpostscript;
+
       BLOCK_INPUT;
       img = make_image (spec, hash);
       cache_image (f, img);
       img->load_failed_p = img->type->load (f, img) == 0;
-      xassert (!interrupt_input_blocked);
 
       /* If we can't load the image, and we don't have a width and
         height, use some arbitrary width and height so that we can
@@ -4158,14 +4599,15 @@ lookup_image (f, spec)
       else
        {
          /* Handle image type independent image attributes
-            `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'.  */
-         Lisp_Object ascent, margin, relief;
+            `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
+            `:background COLOR'.  */
+         Lisp_Object ascent, margin, relief, bg;
 
          ascent = image_spec_value (spec, QCascent, NULL);
          if (INTEGERP (ascent))
            img->ascent = XFASTINT (ascent);
          else if (EQ (ascent, Qcenter))
-            img->ascent = CENTERED_IMAGE_ASCENT;
+           img->ascent = CENTERED_IMAGE_ASCENT;
 
          margin = image_spec_value (spec, QCmargin, NULL);
          if (INTEGERP (margin) && XINT (margin) >= 0)
@@ -4186,7 +4628,26 @@ lookup_image (f, spec)
              img->hmargin += abs (img->relief);
              img->vmargin += abs (img->relief);
            }
+
+         if (! img->background_valid)
+           {
+             bg = image_spec_value (img->spec, QCbackground, NULL);
+             if (!NILP (bg))
+               {
+                 img->background
+                   = x_alloc_image_color (f, img, bg,
+                                          FRAME_BACKGROUND_PIXEL (f));
+                 img->background_valid = 1;
+               }
+           }
+
+         /* Do image transformations and compute masks, unless we
+            don't have the image yet.  */
+         if (!EQ (*img->type->type, Qpostscript))
+           postprocess_image (f, img);
        }
+
+      UNBLOCK_INPUT;
     }
 
   /* We're using IMG, so set its timestamp to `now'.  */
@@ -4266,48 +4727,23 @@ forall_images_in_image_cache (f, fn)
                            Mac support code
  ***********************************************************************/
 
-#if 0 /* MAC_TODO: Mac 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 *));
-static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
-
+                                           XImagePtr *, Pixmap *));
+static void x_destroy_x_image P_ ((XImagePtr));
+static void x_put_x_image P_ ((struct frame *, XImagePtr, 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.  */
 
-static int
 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
      struct frame *f;
      int width, height, depth;
-     XImage **ximg;
+     XImagePtr *ximg;
      Pixmap *pixmap;
 {
-#if 0 /* MAC_TODO: Image support for Mac */
-  Display *display = FRAME_W32_DISPLAY (f);
-  Screen *screen = FRAME_X_SCREEN (f);
-  Window window = FRAME_W32_WINDOW (f);
+  Display *display = FRAME_MAC_DISPLAY (f);
+  Window window = FRAME_MAC_WINDOW (f);
 
   xassert (interrupt_input_blocked);
 
-  if (depth <= 0)
-    depth = DefaultDepthOfScreen (screen);
-  *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
-                       depth, ZPixmap, 0, NULL, width, height,
-                       depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
-  if (*ximg == NULL)
-    {
-      image_error ("Unable to allocate X image", Qnil, Qnil);
-      return 0;
-    }
-
-  /* Allocate image raster.  */
-  (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
-
   /* Allocate a pixmap of the same size.  */
   *pixmap = XCreatePixmap (display, window, width, height, depth);
   if (*pixmap == 0)
@@ -4317,52 +4753,39 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
       image_error ("Unable to create X pixmap", Qnil, Qnil);
       return 0;
     }
-#endif /* MAC_TODO */
+
+  LockPixels (GetGWorldPixMap (*pixmap));
+  *ximg = *pixmap;
   return 1;
 }
 
-
-/* Destroy XImage XIMG.  Free XIMG->data.  */
-
 static void
 x_destroy_x_image (ximg)
-     XImage *ximg;
+     XImagePtr ximg;
 {
   xassert (interrupt_input_blocked);
   if (ximg)
-    {
-      xfree (ximg->data);
-      ximg->data = NULL;
-      XDestroyImage (ximg);
-    }
+    XDestroyImage (ximg);
 }
 
-
-/* Put XImage XIMG into pixmap PIXMAP on frame F.  WIDTH and HEIGHT
-   are width and height of both the image and pixmap.  */
-
 static void
 x_put_x_image (f, ximg, pixmap, width, height)
      struct frame *f;
-     XImage *ximg;
+     XImagePtr ximg;
      Pixmap pixmap;
 {
-  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);
+  xassert (ximg == pixmap);
 }
 
-#endif /* MAC_TODO */
 
 \f
 /***********************************************************************
-                             Searching files
+                             File Handling
  ***********************************************************************/
 
 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
+static char *slurp_file P_ ((char *, int *));
+
 
 /* Find image file FILE.  Look in data-directory, then
    x-bitmap-file-path.  Value is the full name of the file found, or
@@ -4383,7 +4806,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 < 0)
+  if (fd == -1)
     file_found = Qnil;
   else
     close (fd);
@@ -4392,17 +4815,398 @@ x_find_image_file (file)
   return file_found;
 }
 
+
+/* Read FILE into memory.  Value is a pointer to a buffer allocated
+   with xmalloc holding FILE's contents.  Value is null if an error
+   occurred.  *SIZE is set to the size of the file.  */
+
+static char *
+slurp_file (file, size)
+     char *file;
+     int *size;
+{
+  FILE *fp = NULL;
+  char *buf = NULL;
+  struct stat st;
+
+  if (stat (file, &st) == 0
+      && (fp = fopen (file, "r")) != NULL
+      && (buf = (char *) xmalloc (st.st_size),
+         fread (buf, 1, st.st_size, fp) == st.st_size))
+    {
+      *size = st.st_size;
+      fclose (fp);
+    }
+  else
+    {
+      if (fp)
+       fclose (fp);
+      if (buf)
+       {
+         xfree (buf);
+         buf = NULL;
+       }
+    }
+
+  return buf;
+}
+
+
+\f
+/***********************************************************************
+                       Image Load Functions
+ ***********************************************************************/
+
+static int image_load_quicktime P_ ((struct frame *, struct image *img,
+                                    OSType));
+#ifdef MAC_OSX
+static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
+#endif
+
+
+static OSErr
+find_image_fsspec (specified_file, file, fss)
+     Lisp_Object specified_file, *file;
+     FSSpec *fss;
+{
+#if TARGET_API_MAC_CARBON
+  FSRef fsr;
+#else
+  Str255 mac_pathname;
+#endif
+  OSErr err;
+
+  *file = x_find_image_file (specified_file);
+  if (!STRINGP (*file))
+    return fnfErr;             /* file or directory not found;
+                                  incomplete pathname */
+  /* Try to open the image file.  */
+#if TARGET_API_MAC_CARBON
+  err = FSPathMakeRef (SDATA (*file), &fsr, NULL);
+  if (err == noErr)
+    err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL);
+#else
+  if (posix_to_mac_pathname (SDATA (*file), mac_pathname, MAXPATHLEN+1) == 0)
+    return fnfErr;
+  c2pstr (mac_pathname);
+  err = FSMakeFSSpec (0, 0, mac_pathname, fss);
+#endif
+  return err;
+}
+
+
+static int
+image_load_qt_1 (f, img, type, fss, dh)
+     struct frame *f;
+     struct image *img;
+     OSType type;
+     FSSpec *fss;
+     Handle dh;
+{
+  OSErr err;
+  GraphicsImportComponent gi;
+  Rect rect;
+  int width, height;
+  short draw_all_pixels;
+  Lisp_Object specified_bg;
+  XColor color;
+  XImagePtr ximg;
+  RGBColor bg_color;
+
+  err = OpenADefaultComponent (GraphicsImporterComponentType,
+                              type, &gi);
+  if (err != noErr)
+    {
+      image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
+      return 0;
+    }
+  if (dh == NULL)
+    {
+      /* read from file system spec */
+      err = GraphicsImportSetDataFile (gi, fss);
+      if (err != noErr)
+       {
+         image_error ("Cannot set fsspec to graphics importer for '%s'",
+                      img->spec, Qnil);
+         goto error;
+       }
+    }
+  else
+    {
+      /* read from data handle */
+      err = GraphicsImportSetDataHandle (gi, dh);
+      if (err != noErr)
+       {
+         image_error ("Cannot set data handle to graphics importer for `%s'",
+                      img->spec, Qnil);
+         goto error;
+       }
+    }
+  err = GraphicsImportGetNaturalBounds (gi, &rect);
+  if (err != noErr)
+    {
+      image_error ("Error reading `%s'", img->spec, Qnil);
+      goto error;
+    }
+  width = img->width = rect.right - rect.left;
+  height = img->height = rect.bottom - rect.top;
+  err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
+#if 0
+  /* Don't check the error code here.  It may have an undocumented
+     value -32766. */
+  if (err != noErr)
+    {
+      image_error ("Error reading `%s'", img->spec, Qnil);
+      goto error;
+    }
+#endif
+  if (draw_all_pixels != graphicsImporterDrawsAllPixels)
+    {
+      specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+      if (!STRINGP (specified_bg) ||
+         !mac_defined_color (f, SDATA (specified_bg), &color, 0))
+       {
+         color.pixel = FRAME_BACKGROUND_PIXEL (f);
+         color.red = RED16_FROM_ULONG (color.pixel);
+         color.green = GREEN16_FROM_ULONG (color.pixel);
+         color.blue = BLUE16_FROM_ULONG (color.pixel);
+       }
+    }
+
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    goto error;
+  if (draw_all_pixels != graphicsImporterDrawsAllPixels)
+    {
+      SetGWorld (ximg, NULL);
+      bg_color.red = color.red;
+      bg_color.green = color.green;
+      bg_color.blue = color.blue;
+      RGBBackColor (&bg_color);
+#if TARGET_API_MAC_CARBON
+      GetPortBounds (ximg, &rect);
+      EraseRect (&rect);
+#else
+      EraseRect (&(ximg->portRect));
+#endif
+    }
+  GraphicsImportSetGWorld (gi, ximg, NULL);
+  GraphicsImportDraw (gi);
+  CloseComponent (gi);
+
+  /* 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);
+  return 1;
+
+ error:
+  CloseComponent (gi);
+  return 0;
+}
+
+
+/* Load an image using the QuickTime Graphics Importer.
+   Note: The alpha channel does not work for PNG images. */
+static int
+image_load_quicktime (f, img, type)
+     struct frame *f;
+     struct image *img;
+     OSType type;
+{
+  Lisp_Object specified_file;
+  Lisp_Object specified_data;
+  OSErr err;
+
+  specified_file = image_spec_value (img->spec, QCfile, NULL);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+
+  if (NILP (specified_data))
+    {
+      /* Read from a file */
+      Lisp_Object file;
+      FSSpec fss;
+
+      err = find_image_fsspec (specified_file, &file, &fss);
+      if (err != noErr)
+       {
+         if (err == fnfErr)
+           image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         else
+           image_error ("Cannot open `%s'", file, Qnil);
+         return 0;
+       }
+      return image_load_qt_1 (f, img, type, &fss, NULL);
+    }
+  else
+    {
+      /* Memory source! */
+      int success_p;
+      Handle dh;
+
+      err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
+      if (err != noErr)
+       {
+         image_error ("Cannot allocate data handle for `%s'",
+                      img->spec, Qnil);
+         return 0;
+       }
+      success_p = image_load_qt_1 (f, img, type, NULL, dh);
+      DisposeHandle (dh);
+      return success_p;
+    }
+}
+
+
+#ifdef MAC_OSX
+/* Load a PNG/JPEG image using Quartz 2D decoding routines.
+   CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
+   So don't use this function directly but determine at runtime
+   whether it exists. */
+typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType)
+  (CGDataProviderRef, const float [], bool, CGColorRenderingIntent);
+static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider;
+
+
+static void
+init_image_func_pointer ()
+{
+  if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
+    {
+      MyCGImageCreateWithPNGDataProvider
+       = (CGImageCreateWithPNGDataProviderProcType)
+       NSAddressOfSymbol (NSLookupAndBindSymbol
+                          ("_CGImageCreateWithPNGDataProvider"));
+    }
+  else
+    MyCGImageCreateWithPNGDataProvider = NULL;
+}
+
+
+static int
+image_load_quartz2d (f, img, png_p)
+     struct frame *f;
+     struct image *img;
+     int png_p;
+{
+  Lisp_Object file, specified_file;
+  Lisp_Object specified_data, specified_bg;
+  struct gcpro gcpro1;
+  CGDataProviderRef source;
+  CGImageRef image;
+  int width, height;
+  XColor color;
+  XImagePtr ximg = NULL;
+  CGContextRef context;
+  CGRect rectangle;
+
+  /* Open the file.  */
+  specified_file = image_spec_value (img->spec, QCfile, NULL);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+
+  file = Qnil;
+  GCPRO1 (file);
+
+  if (NILP (specified_data))
+    {
+      CFStringRef path;
+      CFURLRef url;
+
+      file = x_find_image_file (specified_file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+      path = CFStringCreateWithCString (NULL, SDATA (file),
+                                       kCFStringEncodingUTF8);
+      url = CFURLCreateWithFileSystemPath (NULL, path,
+                                          kCFURLPOSIXPathStyle, 0);
+      CFRelease (path);
+      source = CGDataProviderCreateWithURL (url);
+      CFRelease (url);
+    }
+  else
+    source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
+                                          SBYTES (specified_data), NULL);
+
+  if (png_p)
+    image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
+                                                  kCGRenderingIntentDefault);
+  else
+    image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
+                                              kCGRenderingIntentDefault);
+
+  CGDataProviderRelease (source);
+  if (image == NULL)
+    {
+      UNGCPRO;
+      image_error ("Error reading image `%s'", img->spec, Qnil);
+      return 0;
+    }
+
+  if (png_p)
+    {
+      specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+      if (!STRINGP (specified_bg) ||
+         !mac_defined_color (f, SDATA (specified_bg), &color, 0))
+       {
+         color.pixel = FRAME_BACKGROUND_PIXEL (f);
+         color.red = RED16_FROM_ULONG (color.pixel);
+         color.green = GREEN16_FROM_ULONG (color.pixel);
+         color.blue = BLUE16_FROM_ULONG (color.pixel);
+       }
+    }
+  width = img->width = CGImageGetWidth (image);
+  height = img->height = CGImageGetHeight (image);
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    {
+      CGImageRelease (image);
+      UNGCPRO;
+      return 0;
+    }
+  rectangle = CGRectMake (0, 0, width, height);
+  QDBeginCGContext (ximg, &context);
+  if (png_p)
+    {
+      CGContextSetRGBFillColor (context, color.red / 65535.0,
+                               color.green / 65535.0,
+                               color.blue / 65535.0, 1.0);
+      CGContextFillRect (context, rectangle);
+    }
+  CGContextDrawImage (context, rectangle, image);
+  QDEndCGContext (ximg, &context);
+  CGImageRelease (image);
+
+  /* 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);
+  UNGCPRO;
+  return 1;
+}
+#endif
+
+
 \f
 /***********************************************************************
                              XBM images
  ***********************************************************************/
 
+static int xbm_scan P_ ((char **, char *, char *, int *));
 static int xbm_load P_ ((struct frame *f, struct image *img));
-static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
-                                        Lisp_Object file));
+static int xbm_load_image P_ ((struct frame *f, struct image *img,
+                              char *, char *));
 static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
-                                         unsigned char **));
+static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
+                                    unsigned char **));
+static int xbm_file_p P_ ((Lisp_Object));
 
 
 /* Indices of image specification fields in xbm_format, below.  */
@@ -4421,6 +5225,7 @@ enum xbm_keyword_index
   XBM_RELIEF,
   XBM_ALGORITHM,
   XBM_HEURISTIC_MASK,
+  XBM_MASK,
   XBM_LAST
 };
 
@@ -4434,13 +5239,14 @@ static struct image_keyword xbm_format[XBM_LAST] =
   {":width",           IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":height",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":data",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":foreground",      IMAGE_STRING_VALUE,                     0},
-  {":background",      IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":foreground",      IMAGE_STRING_OR_NIL_VALUE,              0},
+  {":background",      IMAGE_STRING_OR_NIL_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},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
 /* Structure describing the image type XBM.  */
@@ -4483,10 +5289,14 @@ enum xbm_token
    3. a vector of strings or bool-vectors, one for each line of the
    bitmap.
 
+   4. A string containing an in-memory XBM file.  WIDTH and HEIGHT
+   may not be specified in this case because they are defined in the
+   XBM file.
+
    Both the file and data forms may contain the additional entries
    `:background COLOR' and `:foreground COLOR'.  If not present,
    foreground and background of the frame on which the image is
-   displayed, is used.  */
+   displayed is used.  */
 
 static int
 xbm_image_p (object)
@@ -4505,6 +5315,12 @@ xbm_image_p (object)
       if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
        return 0;
     }
+  else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
+    {
+      /* In-memory XBM file.  */
+      if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
+       return 0;
+    }
   else
     {
       Lisp_Object data;
@@ -4566,11 +5382,6 @@ xbm_image_p (object)
        return 0;
     }
 
-  /* Baseline must be a value between 0 and 100 (a percentage).  */
-  if (kw[XBM_ASCENT].count
-      && XFASTINT (kw[XBM_ASCENT].value) > 100)
-    return 0;
-
   return 1;
 }
 
@@ -4582,30 +5393,33 @@ xbm_image_p (object)
    scanning a number, store its value in *IVAL.  */
 
 static int
-xbm_scan (fp, sval, ival)
-     FILE *fp;
+xbm_scan (s, end, sval, ival)
+     char **s, *end;
      char *sval;
      int *ival;
 {
   int c;
 
+ loop:
+
   /* Skip white space.  */
-  while ((c = fgetc (fp)) != EOF && isspace (c))
+  while (*s < end && (c = *(*s)++, isspace (c)))
     ;
 
-  if (c == EOF)
+  if (*s >= end)
     c = 0;
   else if (isdigit (c))
     {
       int value = 0, digit;
 
-      if (c == '0')
+      if (c == '0' && *s < end)
        {
-         c = fgetc (fp);
+         c = *(*s)++;
          if (c == 'x' || c == 'X')
            {
-             while ((c = fgetc (fp)) != EOF)
+             while (*s < end)
                {
+                 c = *(*s)++;
                  if (isdigit (c))
                    digit = c - '0';
                  else if (c >= 'a' && c <= 'f')
@@ -4620,53 +5434,66 @@ xbm_scan (fp, sval, ival)
          else if (isdigit (c))
            {
              value = c - '0';
-             while ((c = fgetc (fp)) != EOF
-                    && isdigit (c))
+             while (*s < end
+                    && (c = *(*s)++, isdigit (c)))
                value = 8 * value + c - '0';
            }
        }
       else
        {
          value = c - '0';
-         while ((c = fgetc (fp)) != EOF
-                && isdigit (c))
+         while (*s < end
+                && (c = *(*s)++, isdigit (c)))
            value = 10 * value + c - '0';
        }
 
-      if (c != EOF)
-       ungetc (c, fp);
+      if (*s < end)
+       *s = *s - 1;
       *ival = value;
       c = XBM_TK_NUMBER;
     }
   else if (isalpha (c) || c == '_')
     {
       *sval++ = c;
-      while ((c = fgetc (fp)) != EOF
-            && (isalnum (c) || c == '_'))
+      while (*s < end
+            && (c = *(*s)++, (isalnum (c) || c == '_')))
        *sval++ = c;
       *sval = 0;
-      if (c != EOF)
-       ungetc (c, fp);
+      if (*s < end)
+       *s = *s - 1;
       c = XBM_TK_IDENT;
     }
+  else if (c == '/' && **s == '*')
+    {
+      /* C-style comment.  */
+      ++*s;
+      while (**s && (**s != '*' || *(*s + 1) != '/'))
+       ++*s;
+      if (**s)
+       {
+         *s += 2;
+         goto loop;
+       }
+    }
 
   return c;
 }
 
 
 /* Replacement for XReadBitmapFileData which isn't available under old
-   X versions.  FILE is the name of the bitmap file to read.  Set
-   *WIDTH and *HEIGHT to the width and height of the image.  Return in
-   *DATA the bitmap data allocated with xmalloc.  Value is non-zero if
-   successful.  */
+   X versions.  CONTENTS is a pointer to a buffer to parse; END is the
+   buffer's end.  Set *WIDTH and *HEIGHT to the width and height of
+   the image.  Return in *DATA the bitmap data allocated with xmalloc.
+   Value is non-zero if successful.  DATA null means just test if
+   CONTENTS looks like an in-memory XBM file.  */
 
 static int
-xbm_read_bitmap_file_data (file, width, height, data)
-     char *file;
+xbm_read_bitmap_data (contents, end, width, height, data)
+     char *contents, *end;
      int *width, *height;
      unsigned char **data;
 {
-  FILE *fp;
+  char *s = contents;
   char buffer[BUFSIZ];
   int padding_p = 0;
   int v10 = 0;
@@ -4676,7 +5503,7 @@ xbm_read_bitmap_file_data (file, width, height, data)
   int LA1;
 
 #define match() \
-     LA1 = xbm_scan (fp, buffer, &value)
+     LA1 = xbm_scan (&s, end, buffer, &value)
 
 #define expect(TOKEN)          \
      if (LA1 != (TOKEN))       \
@@ -4690,13 +5517,10 @@ xbm_read_bitmap_file_data (file, width, height, data)
      else                                                      \
        goto failure
 
-  fp = fopen (file, "r");
-  if (fp == NULL)
-    return 0;
-
   *width = *height = -1;
-  *data = NULL;
-  LA1 = xbm_scan (fp, buffer, &value);
+  if (data)
+    *data = NULL;
+  LA1 = xbm_scan (&s, end, buffer, &value);
 
   /* Parse defines for width, height and hot-spots.  */
   while (LA1 == '#')
@@ -4719,6 +5543,8 @@ xbm_read_bitmap_file_data (file, width, height, data)
 
   if (*width < 0 || *height < 0)
     goto failure;
+  else if (data == NULL)
+    goto success;
 
   /* Parse bits.  Must start with `static'.  */
   expect_ident ("static");
@@ -4756,7 +5582,6 @@ xbm_read_bitmap_file_data (file, width, height, data)
 
   if (v10)
     {
-
       for (i = 0; i < nbytes; i += 2)
        {
          int val = value;
@@ -4788,13 +5613,12 @@ xbm_read_bitmap_file_data (file, width, height, data)
        }
     }
 
-  fclose (fp);
+ success:
   return 1;
 
  failure:
 
-  fclose (fp);
-  if (*data)
+  if (data && *data)
     {
       xfree (*data);
       *data = NULL;
@@ -4807,38 +5631,24 @@ xbm_read_bitmap_file_data (file, width, height, data)
 }
 
 
-/* Load XBM image IMG which will be displayed on frame F from file
-   SPECIFIED_FILE.  Value is non-zero if successful.  */
+/* 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
+   successful.  */
 
 static int
-xbm_load_image_from_file (f, img, specified_file)
+xbm_load_image (f, img, contents, end)
      struct frame *f;
      struct image *img;
-     Lisp_Object specified_file;
+     char *contents, *end;
 {
   int rc;
   unsigned char *data;
   int success_p = 0;
-  Lisp_Object file;
-  struct gcpro gcpro1;
-
-  xassert (STRINGP (specified_file));
-  file = Qnil;
-  GCPRO1 (file);
 
-  file = x_find_image_file (specified_file);
-  if (!STRINGP (file))
-    {
-      image_error ("Cannot find image file `%s'", specified_file, Qnil);
-      UNGCPRO;
-      return 0;
-    }
-
-  rc = xbm_read_bitmap_file_data (SDATA (file), &img->width,
-                                 &img->height, &data);
+  rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
   if (rc)
     {
-      int depth = one_mac_display_info.n_cbits;
+      int depth = one_mac_display_info.n_planes;
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       Lisp_Object value;
@@ -4849,16 +5659,17 @@ xbm_load_image_from_file (f, img, specified_file)
       value = image_spec_value (img->spec, QCforeground, NULL);
       if (!NILP (value))
        foreground = x_alloc_image_color (f, img, value, foreground);
-
       value = image_spec_value (img->spec, QCbackground, NULL);
       if (!NILP (value))
-       background = x_alloc_image_color (f, img, value, background);
+       {
+         background = x_alloc_image_color (f, img, value, background);
+         img->background = background;
+         img->background_valid = 1;
+       }
 
-#if 0 /* MAC_TODO : Port image display to Mac */
-      BLOCK_INPUT;
       img->pixmap
-       = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
-                                      FRAME_W32_WINDOW (f),
+       = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f),
+                                      FRAME_MAC_WINDOW (f),
                                       data,
                                       img->width, img->height,
                                       foreground, background,
@@ -4868,22 +5679,33 @@ xbm_load_image_from_file (f, img, specified_file)
       if (img->pixmap == 0)
        {
          x_clear_image (f, img);
-         image_error ("Unable to create X pixmap for `%s'", file, Qnil);
+         image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
        }
       else
        success_p = 1;
-
-      UNBLOCK_INPUT;
-#endif /* MAC_TODO */
     }
   else
     image_error ("Error loading XBM image `%s'", img->spec, Qnil);
 
-  UNGCPRO;
   return success_p;
 }
 
 
+/* Value is non-zero if DATA looks like an in-memory XBM file.  */
+
+static int
+xbm_file_p (data)
+     Lisp_Object data;
+{
+  int w, h;
+  return (STRINGP (data)
+         && xbm_read_bitmap_data (SDATA (data),
+                                  (SDATA (data)
+                                   + SBYTES (data)),
+                                  &w, &h, NULL));
+}
+
+
 /* Fill image IMG which is used on frame F with pixmap data.  Value is
    non-zero if successful.  */
 
@@ -4900,7 +5722,32 @@ xbm_load (f, img)
   /* If IMG->spec specifies a file name, create a non-file spec from it.  */
   file_name = image_spec_value (img->spec, QCfile, NULL);
   if (STRINGP (file_name))
-    success_p = xbm_load_image_from_file (f, img, file_name);
+    {
+      Lisp_Object file;
+      char *contents;
+      int size;
+      struct gcpro gcpro1;
+
+      file = x_find_image_file (file_name);
+      GCPRO1 (file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", file_name, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+
+      contents = slurp_file (SDATA (file), &size);
+      if (contents == NULL)
+       {
+         image_error ("Error loading XBM image `%s'", img->spec, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+
+      success_p = xbm_load_image (f, img, contents, contents + size);
+      UNGCPRO;
+    }
   else
     {
       struct image_keyword fmt[XBM_LAST];
@@ -4910,75 +5757,80 @@ xbm_load (f, img)
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       char *bits;
       int parsed_p;
+      int in_memory_file_p = 0;
 
-      /* Parse the list specification.  */
+      /* See if data looks like an in-memory XBM file.  */
+      data = image_spec_value (img->spec, QCdata, NULL);
+      in_memory_file_p = xbm_file_p (data);
+
+      /* Parse the image specification.  */
       bcopy (xbm_format, fmt, sizeof fmt);
       parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
       xassert (parsed_p);
 
       /* Get specified width, and height.  */
-      img->width = XFASTINT (fmt[XBM_WIDTH].value);
-      img->height = XFASTINT (fmt[XBM_HEIGHT].value);
-      xassert (img->width > 0 && img->height > 0);
-
-      BLOCK_INPUT;
-
-      if (fmt[XBM_ASCENT].count)
-       img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
+      if (!in_memory_file_p)
+       {
+         img->width = XFASTINT (fmt[XBM_WIDTH].value);
+         img->height = XFASTINT (fmt[XBM_HEIGHT].value);
+         xassert (img->width > 0 && img->height > 0);
+       }
 
       /* Get foreground and background colors, maybe allocate colors.  */
-      if (fmt[XBM_FOREGROUND].count)
+      if (fmt[XBM_FOREGROUND].count
+         && STRINGP (fmt[XBM_FOREGROUND].value))
        foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
                                          foreground);
-      if (fmt[XBM_BACKGROUND].count)
+      if (fmt[XBM_BACKGROUND].count
+         && STRINGP (fmt[XBM_BACKGROUND].value))
        background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
                                          background);
 
-      /* Set bits to the bitmap image data.  */
-      data = fmt[XBM_DATA].value;
-      if (VECTORP (data))
+      if (in_memory_file_p)
+       success_p = xbm_load_image (f, img, SDATA (data),
+                                   (SDATA (data)
+                                    + SBYTES (data)));
+      else
        {
-         int i;
-         char *p;
-         int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+         if (VECTORP (data))
+           {
+             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)
+             p = bits = (char *) alloca (nbytes * img->height);
+             for (i = 0; i < img->height; ++i, p += nbytes)
+               {
+                 Lisp_Object line = XVECTOR (data)->contents[i];
+                 if (STRINGP (line))
+                   bcopy (SDATA (line), p, nbytes);
+                 else
+                   bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+               }
+           }
+         else if (STRINGP (data))
+           bits = SDATA (data);
+         else
+           bits = XBOOL_VECTOR (data)->data;
+
+         /* Create the pixmap.  */
+         depth = one_mac_display_info.n_planes;
+         img->pixmap
+           = XCreatePixmapFromBitmapData (FRAME_MAC_DISPLAY (f),
+                                          FRAME_MAC_WINDOW (f),
+                                          bits,
+                                          img->width, img->height,
+                                          foreground, background,
+                                          depth);
+         if (img->pixmap)
+           success_p = 1;
+         else
            {
-             Lisp_Object line = XVECTOR (data)->contents[i];
-             if (STRINGP (line))
-               bcopy (SDATA (line), p, nbytes);
-             else
-               bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+             image_error ("Unable to create pixmap for XBM image `%s'",
+                          img->spec, Qnil);
+             x_clear_image (f, img);
            }
        }
-      else if (STRINGP (data))
-       bits = SDATA (data);
-      else
-       bits = XBOOL_VECTOR (data)->data;
-
-#if 0 /* MAC_TODO : port Mac display code */
-      /* Create the pixmap.  */
-      depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
-      img->pixmap
-       = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
-                                      FRAME_W32_WINDOW (f),
-                                      bits,
-                                      img->width, img->height,
-                                      foreground, background,
-                                      depth);
-#endif /* MAC_TODO */
-
-      if (img->pixmap)
-       success_p = 1;
-      else
-       {
-         image_error ("Unable to create pixmap for XBM image `%s'",
-                       img->spec, Qnil);
-         x_clear_image (f, img);
-       }
-
-      UNBLOCK_INPUT;
     }
 
   return success_p;
@@ -5014,7 +5866,9 @@ enum xpm_keyword_index
   XPM_RELIEF,
   XPM_ALGORITHM,
   XPM_HEURISTIC_MASK,
+  XPM_MASK,
   XPM_COLOR_SYMBOLS,
+  XPM_BACKGROUND,
   XPM_LAST
 };
 
@@ -5026,12 +5880,14 @@ 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},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":color-symbols",   IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":color-symbols",   IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type XBM.  */
@@ -5082,9 +5938,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)));
 }
 
 
@@ -5096,7 +5950,7 @@ xpm_load (f, img)
      struct frame *f;
      struct image *img;
 {
-  int rc, i;
+  int rc;
   XpmAttributes attrs;
   Lisp_Object specified_file, color_symbols;
 
@@ -5111,10 +5965,10 @@ xpm_load (f, img)
 #ifdef XpmAllocCloseColors
   attrs.alloc_close_colors = 1;
   attrs.valuemask |= XpmAllocCloseColors;
-#else
+#else /* not XpmAllocCloseColors */
   attrs.closeness = 600;
   attrs.valuemask |= XpmCloseness;
-#endif
+#endif /* not XpmAllocCloseColors */
 
   /* If image specification contains symbolic color definitions, add
      these to `attrs'.  */
@@ -5154,7 +6008,7 @@ 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);
   if (STRINGP (specified_file))
     {
@@ -5162,27 +6016,26 @@ xpm_load (f, img)
       if (!STRINGP (file))
        {
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNBLOCK_INPUT;
          return 0;
        }
 
-      rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
+      rc = XpmReadFileToPixmap (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
                                SDATA (file), &img->pixmap, &img->mask,
                                &attrs);
     }
   else
     {
       Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
-      rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
+      rc = XpmCreatePixmapFromBuffer (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
                                      SDATA (buffer),
                                      &img->pixmap, &img->mask,
                                      &attrs);
     }
-  UNBLOCK_INPUT;
 
   if (rc == XpmSuccess)
     {
-      /* Remember allocated colors.  */
+      int i;
+
       img->ncolors = attrs.nalloc_pixels;
       img->colors = (unsigned long *) xmalloc (img->ncolors
                                               * sizeof *img->colors);
@@ -5194,9 +6047,7 @@ 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;
     }
   else
     {
@@ -5262,15 +6113,6 @@ struct ct_color **ct_table;
 
 int ct_colors_allocated;
 
-/* Function prototypes.  */
-
-static void init_color_table P_ ((void));
-static void free_color_table P_ ((void));
-static unsigned long *colors_in_color_table P_ ((int *n));
-static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
-static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
-
-
 /* Initialize the color table.  */
 
 static void
@@ -5419,161 +6261,354 @@ colors_in_color_table (n)
          colors[j++] = p->pixel;
     }
 
-  return colors;
-}
+  return colors;
+}
+
+#else
+static unsigned long
+lookup_rgb_color (f, r, g, b)
+     struct frame *f;
+     int r, g, b;
+{
+  unsigned long pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
+
+  gamma_correct (f, &pixel);
+  return pixel;
+}
+#endif /* MAC_TODO */
+
+\f
+/***********************************************************************
+                             Algorithms
+ ***********************************************************************/
+
+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));
+
+/* Non-zero means draw a cross on images having `:conversion
+   disabled'.  */
+
+int cross_disabled_images;
+
+/* Edge detection matrices for different edge-detection
+   strategies.  */
+
+static int emboss_matrix[9] = {
+   /* x - 1    x       x + 1  */
+        2,     -1,       0,            /* y - 1 */
+       -1,      0,        1,           /* y     */
+        0,      1,       -2            /* y + 1 */
+};
+
+static int laplace_matrix[9] = {
+   /* x - 1    x       x + 1  */
+        1,      0,       0,            /* y - 1 */
+        0,      0,        0,           /* y     */
+        0,      0,       -1            /* y + 1 */
+};
+
+/* Value is the intensity of the color whose red/green/blue values
+   are R, G, and B.  */
+
+#define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
+
+
+/* On frame F, return an array of XColor structures describing image
+   IMG->pixmap.  Each XColor structure has its pixel color set.  RGB_P
+   non-zero means also fill the red/green/blue members of the XColor
+   structures.  Value is a pointer to the array of XColors structures,
+   allocated with xmalloc; it must be freed by the caller.  */
+
+static XColor *
+x_to_xcolors (f, img, rgb_p)
+     struct frame *f;
+     struct image *img;
+     int rgb_p;
+{
+  int x, y;
+  XColor *colors, *p;
+  XImagePtr ximg;
+
+  colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
+
+  /* Get the X image IMG->pixmap.  */
+  ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
+                   0, 0, img->width, img->height, ~0, ZPixmap);
+
+  /* Fill the `pixel' members of the XColor array.  I wished there
+     were an easy and portable way to circumvent XGetPixel.  */
+  p = colors;
+  for (y = 0; y < img->height; ++y)
+    {
+      XColor *row = p;
+
+      for (x = 0; x < img->width; ++x, ++p)
+       {
+         p->pixel = XGetPixel (ximg, x, y);
+
+         if (rgb_p)
+           {
+             p->red = RED16_FROM_ULONG (p->pixel);
+             p->green = GREEN16_FROM_ULONG (p->pixel);
+             p->blue = BLUE16_FROM_ULONG (p->pixel);
+           }
+       }
+    }
+
+  XDestroyImage (ximg);
+  return colors;
+}
+
+
+/* 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.  */
+
+static void
+x_from_xcolors (f, img, colors)
+     struct frame *f;
+     struct image *img;
+     XColor *colors;
+{
+  int x, y;
+  XImagePtr 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;
+  for (y = 0; y < img->height; ++y)
+    for (x = 0; x < img->width; ++x, ++p)
+      {
+       unsigned long pixel;
+       pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
+       XPutPixel (oimg, x, y, pixel);
+      }
+
+  xfree (colors);
+  x_clear_image_1 (f, img, 1, 0, 1);
+
+  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
+}
+
+
+/* On frame F, perform edge-detection on image IMG.
+
+   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.  */
+
+static void
+x_detect_edges (f, img, matrix, color_adjust)
+     struct frame *f;
+     struct image *img;
+     int matrix[9], color_adjust;
+{
+  XColor *colors = x_to_xcolors (f, img, 1);
+  XColor *new, *p;
+  int x, y, i, sum;
+
+  for (i = sum = 0; i < 9; ++i)
+    sum += abs (matrix[i]);
+
+#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
+
+  new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
+
+  for (y = 0; y < img->height; ++y)
+    {
+      p = COLOR (new, 0, y);
+      p->red = p->green = p->blue = 0xffff/2;
+      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);
+      p->red = p->green = p->blue = 0xffff/2;
+      p = COLOR (new, x, img->height - 1);
+      p->red = p->green = p->blue = 0xffff/2;
+    }
+
+  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;
+
+         r = g = b = i = 0;
+         for (y1 = y - 1; y1 < y + 2; ++y1)
+           for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
+             if (matrix[i])
+               {
+                 XColor *t = COLOR (colors, x1, y1);
+                 r += matrix[i] * t->red;
+                 g += matrix[i] * t->green;
+                 b += matrix[i] * t->blue;
+               }
 
-#endif /* MAC_TODO */
+         r = (r / sum + color_adjust) & 0xffff;
+         g = (g / sum + color_adjust) & 0xffff;
+         b = (b / sum + color_adjust) & 0xffff;
+         p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
+       }
+    }
 
-\f
-/***********************************************************************
-                             Algorithms
- ***********************************************************************/
+  xfree (colors);
+  x_from_xcolors (f, img, new);
 
-#if 0 /* MAC_TODO : Mac versions of low level algorithms */
-static void x_laplace_write_row P_ ((struct frame *, long *,
-                                    int, XImage *, int));
-static void x_laplace_read_row P_ ((struct frame *, Colormap,
-                                   XColor *, int, XImage *, int));
+#undef COLOR
+}
 
 
-/* Fill COLORS with RGB colors from row Y of image XIMG.  F is the
-   frame we operate on, CMAP is the color-map in effect, and WIDTH is
-   the width of one row in the image.  */
+/* Perform the pre-defined `emboss' edge-detection on image IMG
+   on frame F.  */
 
 static void
-x_laplace_read_row (f, cmap, colors, width, ximg, y)
+x_emboss (f, img)
      struct frame *f;
-     Colormap cmap;
-     XColor *colors;
-     int width;
-     XImage *ximg;
-     int y;
+     struct image *img;
 {
-  int x;
-
-  for (x = 0; x < width; ++x)
-    colors[x].pixel = XGetPixel (ximg, x, y);
-
-  XQueryColors (NULL, cmap, colors, width);
+  x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
 }
 
 
-/* Write row Y of image XIMG.  PIXELS is an array of WIDTH longs
-   containing the pixel colors to write.  F is the frame we are
-   working on.  */
+/* Perform the pre-defined `laplace' edge-detection on image IMG
+   on frame F.  */
 
 static void
-x_laplace_write_row (f, pixels, width, ximg, y)
+x_laplace (f, img)
      struct frame *f;
-     long *pixels;
-     int width;
-     XImage *ximg;
-     int y;
+     struct image *img;
 {
-  int x;
-
-  for (x = 0; x < width; ++x)
-    XPutPixel (ximg, x, y, pixels[x]);
+  x_detect_edges (f, img, laplace_matrix, 45000);
 }
-#endif /* MAC_TODO */
 
-/* Transform image IMG which is used on frame F with a Laplace
-   edge-detection algorithm.  The result is an image that can be used
-   to draw disabled buttons, for example.  */
+
+/* Perform edge-detection on image IMG on frame F, with specified
+   transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
+
+   MATRIX must be either
+
+   - a list of at least 9 numbers in row-major form
+   - a vector of at least 9 numbers
+
+   COLOR_ADJUST nil means use a default; otherwise it must be a
+   number.  */
 
 static void
-x_laplace (f, img)
+x_edge_detection (f, img, matrix, color_adjust)
      struct frame *f;
      struct image *img;
+     Lisp_Object matrix, color_adjust;
 {
-#if 0 /* MAC_TODO : Mac version */
-  Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-  XImage *ximg, *oimg;
-  XColor *in[3];
-  long *out;
-  Pixmap pixmap;
-  int x, y, i;
-  long pixel;
-  int in_y, out_y, rc;
-  int mv2 = 45000;
+  int i = 0;
+  int trans[9];
 
-  BLOCK_INPUT;
+  if (CONSP (matrix))
+    {
+      for (i = 0;
+          i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
+          ++i, matrix = XCDR (matrix))
+       trans[i] = XFLOATINT (XCAR (matrix));
+    }
+  else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
+    {
+      for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
+       trans[i] = XFLOATINT (AREF (matrix, i));
+    }
 
-  /* Get the X image IMG->pixmap.  */
-  ximg = XGetImage (NULL, img->pixmap,
-                   0, 0, img->width, img->height, ~0, ZPixmap);
+  if (NILP (color_adjust))
+    color_adjust = make_number (0xffff / 2);
 
-  /* Allocate 3 input rows, and one output row of colors.  */
-  for (i = 0; i < 3; ++i)
-    in[i] = (XColor *) alloca (img->width * sizeof (XColor));
-  out = (long *) alloca (img->width * sizeof (long));
+  if (i == 9 && NUMBERP (color_adjust))
+    x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
+}
 
-  /* Create an X image for output.  */
-  rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
-                                   &oimg, &pixmap);
 
-  /* Fill first two rows.  */
-  x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
-  x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
-  in_y = 2;
+/* Transform image IMG on frame F so that it looks disabled.  */
 
-  /* Write first row, all zeros.  */
-  init_color_table ();
-  pixel = lookup_rgb_color (f, 0, 0, 0);
-  for (x = 0; x < img->width; ++x)
-    out[x] = pixel;
-  x_laplace_write_row (f, out, img->width, oimg, 0);
-  out_y = 1;
+static void
+x_disable_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
 
-  for (y = 2; y < img->height; ++y)
+  if (dpyinfo->n_planes >= 2)
     {
-      int rowa = y % 3;
-      int rowb = (y + 2) % 3;
+      /* Color (or grayscale).  Convert to gray, and equalize.  Just
+        drawing such images with a stipple can look very odd, so
+        we're using this method instead.  */
+      XColor *colors = x_to_xcolors (f, img, 1);
+      XColor *p, *end;
+      const int h = 15000;
+      const int l = 30000;
 
-      x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
-
-      for (x = 0; x < img->width - 2; ++x)
+      for (p = colors, end = colors + img->width * img->height;
+          p < end;
+          ++p)
        {
-         int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
-         int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
-         int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
-
-         out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
-                                        b & 0xffff);
+         int i = COLOR_INTENSITY (p->red, p->green, p->blue);
+         int i2 = (0xffff - h - l) * i / 0xffff + l;
+         p->red = p->green = p->blue = i2;
        }
 
-      x_laplace_write_row (f, out, img->width, oimg, out_y++);
+      x_from_xcolors (f, img, colors);
     }
 
-  /* Write last line, all zeros.  */
-  for (x = 0; x < img->width; ++x)
-    out[x] = pixel;
-  x_laplace_write_row (f, out, img->width, oimg, out_y);
-
-  /* Free the input image, and free resources of IMG.  */
-  XDestroyImage (ximg);
-  x_clear_image (f, img);
-
-  /* Put the output image into pixmap, and destroy it.  */
-  x_put_x_image (f, oimg, pixmap, img->width, img->height);
-  x_destroy_x_image (oimg);
+  /* Draw a cross over the disabled image, if we must or if we
+     should.  */
+  if (dpyinfo->n_planes < 2 || cross_disabled_images)
+    {
+      Display *dpy = FRAME_MAC_DISPLAY (f);
+      GC gc;
 
-  /* Remember new pixmap and colors in IMG.  */
-  img->pixmap = pixmap;
-  img->colors = colors_in_color_table (&img->ncolors);
-  free_color_table ();
+      gc = XCreateGC (dpy, NULL /*img->pixmap*/, 0, NULL);
+      XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
+      mac_draw_line_to_pixmap (dpy, img->pixmap, gc, 0, 0,
+                              img->width - 1, img->height - 1);
+      mac_draw_line_to_pixmap (dpy, img->pixmap, gc, 0, img->height - 1,
+                              img->width - 1, 0);
+      XFreeGC (dpy, gc);
 
-  UNBLOCK_INPUT;
-#endif /* MAC_TODO */
+      if (img->mask)
+       {
+         gc = XCreateGC (dpy, NULL /*img->mask*/, 0, NULL);
+         XSetForeground (dpy, gc, PIX_MASK_DRAW (f));
+         mac_draw_line_to_pixmap (dpy, img->mask, gc, 0, 0,
+                                  img->width - 1, img->height - 1);
+         mac_draw_line_to_pixmap (dpy, img->mask, gc, 0, img->height - 1,
+                                  img->width - 1, 0);
+         XFreeGC (dpy, gc);
+       }
+    }
 }
 
 
-/* Build a mask for image IMG which is used on frame F. FILE is the
-   name of an image file, for error messages. HOW determines how to
-   determine the background color of IMG. If it is a list '(R G B)',
+/* Build a mask for image IMG which is used on frame F.  FILE is the
+   name of an image file, for error messages.  HOW determines how to
+   determine the background color of IMG.  If it is a list '(R G B)',
    with R, G, and B being integers >= 0, take that as the color of the
-   background. Otherwise, determine the background color of IMG
-   heuristically. Value is non-zero if successful. */
+   background.  Otherwise, determine the background color of IMG
+   heuristically.  Value is non-zero if successful. */
 
 static int
 x_build_heuristic_mask (f, img, how)
@@ -5581,39 +6616,37 @@ x_build_heuristic_mask (f, img, how)
      struct image *img;
      Lisp_Object how;
 {
-#if 0 /* MAC_TODO : Mac version */
-  Display *dpy = FRAME_W32_DISPLAY (f);
-  XImage *ximg, *mask_img;
-  int x, y, rc, look_at_corners_p;
-  unsigned long bg;
+  Display *dpy = FRAME_X_DISPLAY (f);
+  XImagePtr ximg, mask_img;
+  int x, y, rc, use_img_background;
+  unsigned long bg = 0;
 
-  BLOCK_INPUT;
+  if (img->mask)
+    {
+      XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+      img->mask = 0;
+      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)
-    {
-      UNBLOCK_INPUT;
-      return 0;
-    }
+    return 0;
 
   /* Get the X image of IMG->pixmap.  */
   ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
                    ~0, ZPixmap);
 
   /* Determine the background color of ximg.  If HOW is `(R G B)'
-     take that as color.  Otherwise, try to determine the color
-     heuristically. */
-  look_at_corners_p = 1;
+     take that as color.  Otherwise, use the image's background color. */
+  use_img_background = 1;
 
   if (CONSP (how))
     {
-      int rgb[3], i = 0;
+      int rgb[3], i;
 
-      while (i < 3
-            && CONSP (how)
-            && NATNUMP (XCAR (how)))
+      for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
        {
          rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
          how = XCDR (how);
@@ -5622,59 +6655,29 @@ x_build_heuristic_mask (f, img, how)
       if (i == 3 && NILP (how))
        {
          char color_name[30];
-         XColor exact, color;
-         Colormap cmap;
-
          sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
-
-         cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-         if (XLookupColor (dpy, cmap, color_name, &exact, &color))
-           {
-             bg = color.pixel;
-             look_at_corners_p = 0;
-           }
+         bg = x_alloc_image_color (f, img, build_string (color_name), 0);
+         use_img_background = 0;
        }
     }
 
-  if (look_at_corners_p)
-    {
-      unsigned long corners[4];
-      int i, best_count;
-
-      /* Get the colors at the corners of ximg.  */
-      corners[0] = XGetPixel (ximg, 0, 0);
-      corners[1] = XGetPixel (ximg, img->width - 1, 0);
-      corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
-      corners[3] = XGetPixel (ximg, 0, img->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;
-
-         if (n > best_count)
-           bg = corners[i], best_count = n;
-       }
-    }
+  if (use_img_background)
+    bg = four_corners_best (ximg, 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);
+      XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
+
+  /* Fill in the background_transparent field while we have the mask handy. */
+  image_background_transparent (img, f, mask_img);
 
   /* 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);
 
-  UNBLOCK_INPUT;
-#endif /* MAC_TODO */
-
   return 1;
 }
 
@@ -5683,7 +6686,6 @@ x_build_heuristic_mask (f, img, how)
 /***********************************************************************
                       PBM (mono, gray, color)
  ***********************************************************************/
-#ifdef HAVE_PBM
 
 static int pbm_image_p P_ ((Lisp_Object object));
 static int pbm_load P_ ((struct frame *f, struct image *img));
@@ -5705,6 +6707,9 @@ enum pbm_keyword_index
   PBM_RELIEF,
   PBM_ALGORITHM,
   PBM_HEURISTIC_MASK,
+  PBM_MASK,
+  PBM_FOREGROUND,
+  PBM_BACKGROUND,
   PBM_LAST
 };
 
@@ -5716,11 +6721,14 @@ 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},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":foreground",      IMAGE_STRING_OR_NIL_VALUE,              0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `pbm'.  */
@@ -5745,9 +6753,7 @@ pbm_image_p (object)
 
   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.  */
@@ -5763,7 +6769,7 @@ static int
 pbm_scan_number (s, end)
      unsigned char **s, *end;
 {
-  int c, val = -1;
+  int c = 0, val = -1;
 
   while (*s < end)
     {
@@ -5793,42 +6799,6 @@ pbm_scan_number (s, end)
 }
 
 
-/* Read FILE into memory.  Value is a pointer to a buffer allocated
-   with xmalloc holding FILE's contents.  Value is null if an error
-   occurred.  *SIZE is set to the size of the file.  */
-
-static char *
-pbm_read_file (file, size)
-     Lisp_Object file;
-     int *size;
-{
-  FILE *fp = NULL;
-  char *buf = NULL;
-  struct stat st;
-
-  if (stat (SDATA (file), &st) == 0
-      && (fp = fopen (SDATA (file), "r")) != NULL
-      && (buf = (char *) xmalloc (st.st_size),
-         fread (buf, 1, st.st_size, fp) == st.st_size))
-    {
-      *size = st.st_size;
-      fclose (fp);
-    }
-  else
-    {
-      if (fp)
-       fclose (fp);
-      if (buf)
-       {
-         xfree (buf);
-         buf = NULL;
-       }
-    }
-
-  return buf;
-}
-
-
 /* Load PBM image IMG for use on frame F.  */
 
 static int
@@ -5838,7 +6808,7 @@ pbm_load (f, img)
 {
   int raw_p, x, y;
   int width, height, max_color_idx = 0;
-  XImage *ximg;
+  XImagePtr ximg;
   Lisp_Object file, specified_file;
   enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
   struct gcpro gcpro1;
@@ -5854,13 +6824,13 @@ pbm_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;
+       }
 
-      contents = pbm_read_file (file, &size);
+      contents = slurp_file (SDATA (file), &size);
       if (contents == NULL)
        {
          image_error ("Error reading `%s'", file, Qnil);
@@ -5937,20 +6907,37 @@ pbm_load (f, img)
       || (type != PBM_MONO && max_color_idx < 0))
     goto error;
 
-  BLOCK_INPUT;
   if (!x_create_x_image_and_pixmap (f, width, height, 0,
                                    &ximg, &img->pixmap))
-    {
-      UNBLOCK_INPUT;
-      goto error;
-    }
+    goto error;
 
+#if 0  /* TODO: color tables.  */
   /* Initialize the color hash table.  */
   init_color_table ();
+#endif
 
   if (type == PBM_MONO)
     {
       int c = 0, g;
+      struct image_keyword fmt[PBM_LAST];
+      unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
+      unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
+
+      /* 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))
+       fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
+      if (fmt[PBM_BACKGROUND].count
+         && STRINGP (fmt[PBM_BACKGROUND].value))
+       {
+         bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
+         img->background = bg;
+         img->background_valid = 1;
+       }
 
       for (y = 0; y < height; ++y)
        for (x = 0; x < width; ++x)
@@ -5965,9 +6952,7 @@ pbm_load (f, img)
            else
              g = pbm_scan_number (&p, end);
 
-           XPutPixel (ximg, x, y, (g
-                                   ? FRAME_FOREGROUND_PIXEL (f)
-                                   : FRAME_BACKGROUND_PIXEL (f)));
+           XPutPixel (ximg, x, y, g ? fg : bg);
          }
     }
   else
@@ -5994,13 +6979,10 @@ pbm_load (f, img)
 
            if (r < 0 || g < 0 || b < 0)
              {
-               xfree (ximg->data);
-               ximg->data = NULL;
-               XDestroyImage (ximg);
-               UNBLOCK_INPUT;
+               x_destroy_x_image (ximg);
                image_error ("Invalid pixel value in image `%s'",
                             img->spec, Qnil);
-                goto error;
+               goto error;
              }
 
            /* RGB values are now in the range 0..max_color_idx.
@@ -6012,33 +6994,35 @@ pbm_load (f, img)
          }
     }
 
+#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
+
+  img->width = width;
+  img->height = height;
+
+  /* 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);
-  UNBLOCK_INPUT;
-
-  img->width = width;
-  img->height = height;
 
   UNGCPRO;
   xfree (contents);
   return 1;
 }
-#endif /* HAVE_PBM */
+
 
 \f
 /***********************************************************************
                                 PNG
  ***********************************************************************/
 
-#if HAVE_PNG
-
-#include <png.h>
 
 /* Function prototypes.  */
 
@@ -6061,6 +7045,8 @@ enum png_keyword_index
   PNG_RELIEF,
   PNG_ALGORITHM,
   PNG_HEURISTIC_MASK,
+  PNG_MASK,
+  PNG_BACKGROUND,
   PNG_LAST
 };
 
@@ -6072,11 +7058,13 @@ 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},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `png'.  */
@@ -6100,9 +7088,7 @@ 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.  */
@@ -6110,6 +7096,27 @@ png_image_p (object)
 }
 
 
+#ifndef HAVE_PNG
+static int
+png_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+#ifdef MAC_OSX
+  if (MyCGImageCreateWithPNGDataProvider)
+    return image_load_quartz2d (f, img, 1);
+  else
+#endif
+    return image_load_quicktime (f, img, kQTFileTypePNG);
+}
+#else
+
+#if defined HAVE_LIBPNG_PNG_H
+# include <libpng/png.h>
+#else
+# include <png.h>
+#endif
+
 /* Error and warning handlers installed when the PNG library
    is initialized.  */
 
@@ -6174,22 +7181,20 @@ png_load (f, img)
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
   int x, y, i;
-  XImage *ximg, *mask_img = NULL;
+  XImagePtr ximg, mask_img = NULL;
   struct gcpro gcpro1;
   png_struct *png_ptr = NULL;
   png_info *info_ptr = NULL, *end_info = NULL;
-  FILE *fp = NULL;
+  FILE *volatile fp = NULL;
   png_byte sig[8];
-  png_byte *pixels = NULL;
-  png_byte **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;
+  double screen_gamma;
   struct png_memory_storage tbr;  /* Data to be read */
 
   /* Find out what file to load.  */
@@ -6202,31 +7207,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;
-        }
+         || !png_check_sig (sig, sizeof sig))
+       {
+         image_error ("Not a PNG file: `%s'", file, Qnil);
+         UNGCPRO;
+         fclose (fp);
+         return 0;
+       }
     }
   else
     {
@@ -6325,56 +7330,76 @@ png_load (f, img)
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
     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;
-
-  /* Tell the PNG lib to handle gamma correction for us.  */
+  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.  */
+    int intent;
+    double image_gamma;
 #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);
-  else
+    if (png_get_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);
+      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 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.  */
+       {
+         XColor color;
+         if (mac_defined_color (f, SDATA (specified_bg), &color, 0))
+           {
+             png_color_16 user_bg;
 
-      if (png_get_bKGD (png_ptr, info_ptr, &image_background))
+             bzero (&user_bg, sizeof user_bg);
+             user_bg.red = color.red >> 8;
+             user_bg.green = color.green >> 8;
+             user_bg.blue = color.blue >> 8;
+
+             png_set_background (png_ptr, &user_bg,
+                                 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+           }
+       }
+      else if (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_set_background (png_ptr, image_bg,
                            PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
       else
        {
          /* Image does not contain a background color with which
             to combine the image data via an alpha channel.  Use
             the frame's background instead.  */
-         XColor color;
-         Colormap cmap;
+         unsigned long color;
          png_color_16 frame_background;
+         color = FRAME_BACKGROUND_PIXEL (f);
+#if 0 /* TODO : Colormap support.  */
+         Colormap cmap;
 
-         BLOCK_INPUT;
-         cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-         color.pixel = FRAME_BACKGROUND_PIXEL (f);
-         XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
-         UNBLOCK_INPUT;
-
+         cmap = FRAME_X_COLORMAP (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 = RED_FROM_ULONG (color);
+         frame_background.green = GREEN_FROM_ULONG (color);
+         frame_background.blue = BLUE_FROM_ULONG (color);
 
          png_set_background (png_ptr, &frame_background,
                              PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
@@ -6410,15 +7435,10 @@ png_load (f, img)
       fp = NULL;
     }
 
-  BLOCK_INPUT;
-
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
                                    &img->pixmap))
-    {
-      UNBLOCK_INPUT;
-      goto error;
-    }
+    goto error;
 
   /* Create an image and pixmap serving as mask if the PNG image
      contains an alpha channel.  */
@@ -6428,14 +7448,15 @@ png_load (f, img)
                                       &mask_img, &img->mask))
     {
       x_destroy_x_image (ximg);
-      XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
-      img->pixmap = 0;
-      UNBLOCK_INPUT;
+      XFreePixmap (FRAME_MAC_DISPLAY (f), img->pixmap);
+      img->pixmap = NULL;
       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)
     {
@@ -6469,15 +7490,29 @@ png_load (f, img)
          if (channels == 4)
            {
              if (mask_img)
-               XPutPixel (mask_img, x, y, *p > 0);
+               XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
              ++p;
            }
        }
     }
 
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    /* Set IMG's background color from the PNG image, unless the user
+       overrode it.  */
+    {
+      png_color_16 *bg;
+      if (png_get_bKGD (png_ptr, info_ptr, &bg))
+       {
+         img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
+         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);
@@ -6487,6 +7522,9 @@ png_load (f, img)
   img->width = width;
   img->height = height;
 
+  /* Maybe fill in the background field while we have ximg handy. */
+  IMAGE_BACKGROUND (img, f, ximg);
+
   /* 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);
@@ -6494,16 +7532,19 @@ png_load (f, img)
   /* Same for the mask.  */
   if (mask_img)
     {
+      /* Fill in the background_transparent field while we have the mask
+        handy. */
+      image_background_transparent (img, f, mask_img);
+
       x_put_x_image (f, mask_img, img->mask, img->width, img->height);
       x_destroy_x_image (mask_img);
     }
 
-  UNBLOCK_INPUT;
   UNGCPRO;
   return 1;
 }
 
-#endif /* HAVE_PNG != 0 */
+#endif /* HAVE_PNG */
 
 
 \f
@@ -6511,23 +7552,6 @@ png_load (f, img)
                                 JPEG
  ***********************************************************************/
 
-#if HAVE_JPEG
-
-/* Work around a warning about HAVE_STDLIB_H being redefined in
-   jconfig.h.  */
-#ifdef HAVE_STDLIB_H
-#define HAVE_STDLIB_H_1
-#undef HAVE_STDLIB_H
-#endif /* HAVE_STLIB_H */
-
-#include <jpeglib.h>
-#include <jerror.h>
-#include <setjmp.h>
-
-#ifdef HAVE_STLIB_H_1
-#define HAVE_STDLIB_H 1
-#endif
-
 static int jpeg_image_p P_ ((Lisp_Object object));
 static int jpeg_load P_ ((struct frame *f, struct image *img));
 
@@ -6547,6 +7571,8 @@ enum jpeg_keyword_index
   JPEG_RELIEF,
   JPEG_ALGORITHM,
   JPEG_HEURISTIC_MASK,
+  JPEG_MASK,
+  JPEG_BACKGROUND,
   JPEG_LAST
 };
 
@@ -6558,11 +7584,13 @@ 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},
-  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `jpeg'.  */
@@ -6583,19 +7611,46 @@ static int
 jpeg_image_p (object)
      Lisp_Object object;
 {
-  struct image_keyword fmt[JPEG_LAST];
-
-  bcopy (jpeg_format, fmt, sizeof fmt);
+  struct image_keyword fmt[JPEG_LAST];
+
+  bcopy (jpeg_format, fmt, sizeof fmt);
+
+  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
+    return 0;
+
+  /* Must specify either the :data or :file keyword.  */
+  return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
+}
+
+
+#ifndef HAVE_JPEG
+static int
+jpeg_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+#ifdef MAC_OSX
+  return image_load_quartz2d (f, img, 0);
+#else
+  return image_load_quicktime (f, img, kQTFileTypeJPEG);
+#endif
+}
+#else
 
-  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
-      || (fmt[JPEG_ASCENT].count
-         && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
-    return 0;
+/* Work around a warning about HAVE_STDLIB_H being redefined in
+   jconfig.h.  */
+#ifdef HAVE_STDLIB_H
+#define HAVE_STDLIB_H_1
+#undef HAVE_STDLIB_H
+#endif /* HAVE_STLIB_H */
 
-  /* Must specify either the :data or :file keyword.  */
-  return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
-}
+#include <jpeglib.h>
+#include <jerror.h>
+#include <setjmp.h>
 
+#ifdef HAVE_STLIB_H_1
+#define HAVE_STDLIB_H 1
+#endif
 
 struct my_jpeg_error_mgr
 {
@@ -6603,6 +7658,7 @@ struct my_jpeg_error_mgr
   jmp_buf setjmp_buffer;
 };
 
+
 static void
 my_error_exit (cinfo)
      j_common_ptr cinfo;
@@ -6611,6 +7667,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.  */
@@ -6719,10 +7776,10 @@ jpeg_load (f, img)
   struct my_jpeg_error_mgr mgr;
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
-  FILE *fp = NULL;
+  FILE * volatile fp = NULL;
   JSAMPARRAY buffer;
   int row_stride, x, y;
-  XImage *ximg = NULL;
+  XImagePtr ximg = NULL;
   int rc;
   unsigned long *colors;
   int width, height;
@@ -6738,25 +7795,25 @@ 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. */
-  mgr.pub.error_exit = my_error_exit;
+     error is detected.  This function will perform a longjmp.  */
   cinfo.err = jpeg_std_error (&mgr.pub);
+  mgr.pub.error_exit = my_error_exit;
 
   if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
     {
@@ -6771,28 +7828,25 @@ jpeg_load (f, img)
 
       /* Close the input file and destroy the JPEG object.  */
       if (fp)
-        fclose (fp);
+       fclose ((FILE *) fp);
       jpeg_destroy_decompress (&cinfo);
 
-      BLOCK_INPUT;
-
       /* If we already have an XImage, free that.  */
       x_destroy_x_image (ximg);
 
       /* Free pixmap and colors.  */
       x_clear_image (f, img);
 
-      UNBLOCK_INPUT;
       UNGCPRO;
       return 0;
     }
 
   /* Create the JPEG decompression object.  Let it read from fp.
-     Read the JPEG image header.  */
+        Read the JPEG image header.  */
   jpeg_create_decompress (&cinfo);
 
   if (NILP (specified_data))
-    jpeg_stdio_src (&cinfo, fp);
+    jpeg_stdio_src (&cinfo, (FILE *) fp);
   else
     jpeg_memory_src (&cinfo, SDATA (specified_data),
                     SBYTES (specified_data));
@@ -6800,21 +7854,15 @@ jpeg_load (f, img)
   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);
   width = img->width = cinfo.output_width;
   height = img->height = cinfo.output_height;
 
-  BLOCK_INPUT;
-
   /* Create X image and pixmap.  */
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
-                                   &img->pixmap))
-    {
-      UNBLOCK_INPUT;
-      longjmp (mgr.setjmp_buffer, 2);
-    }
+  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,
      cinfo.actual_number_of_colors has been set with the number of
@@ -6831,11 +7879,13 @@ 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);
 
@@ -6849,9 +7899,11 @@ jpeg_load (f, img)
        colors[i] = lookup_rgb_color (f, r, g, b);
       }
 
+#if 0 /* TODO: Color tables.  */
     /* Remember those colors actually allocated.  */
     img->colors = colors_in_color_table (&img->ncolors);
     free_color_table ();
+#endif
   }
 
   /* Read pixels.  */
@@ -6869,12 +7921,15 @@ jpeg_load (f, img)
   jpeg_finish_decompress (&cinfo);
   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;
 }
@@ -6887,10 +7942,6 @@ jpeg_load (f, img)
                                 TIFF
  ***********************************************************************/
 
-#if HAVE_TIFF
-
-#include <tiffio.h>
-
 static int tiff_image_p P_ ((Lisp_Object object));
 static int tiff_load P_ ((struct frame *f, struct image *img));
 
@@ -6910,6 +7961,8 @@ enum tiff_keyword_index
   TIFF_RELIEF,
   TIFF_ALGORITHM,
   TIFF_HEURISTIC_MASK,
+  TIFF_MASK,
+  TIFF_BACKGROUND,
   TIFF_LAST
 };
 
@@ -6921,11 +7974,13 @@ 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},
-  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `tiff'.  */
@@ -6949,15 +8004,26 @@ 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;
 }
 
+#ifndef HAVE_TIFF
+
+static int
+tiff_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  return image_load_quicktime (f, img, kQTFileTypeTIFF);
+}
+
+#else
+
+#include <tiffio.h>
 
 /* Reading from a memory buffer for TIFF images Based on the PNG
    memory source, but we have to provide a lot of extra functions.
@@ -6976,6 +8042,7 @@ typedef struct
 }
 tiff_memory_source;
 
+
 static size_t
 tiff_read_from_memory (data, buf, size)
      thandle_t data;
@@ -6991,6 +8058,7 @@ tiff_read_from_memory (data, buf, size)
   return size;
 }
 
+
 static size_t
 tiff_write_from_memory (data, buf, size)
      thandle_t data;
@@ -7000,6 +8068,7 @@ tiff_write_from_memory (data, buf, size)
   return (size_t) -1;
 }
 
+
 static toff_t
 tiff_seek_in_memory (data, off, whence)
      thandle_t data;
@@ -7023,7 +8092,7 @@ tiff_seek_in_memory (data, off, whence)
       idx = src->index + off;
       break;
 
-    default:                   /* Invalid `whence'.  */
+    default:                   /* Invalid `whence'.   */
       return -1;
     }
 
@@ -7034,6 +8103,7 @@ tiff_seek_in_memory (data, off, whence)
   return src->index;
 }
 
+
 static int
 tiff_close_memory (data)
      thandle_t data;
@@ -7042,6 +8112,7 @@ tiff_close_memory (data)
   return 0;
 }
 
+
 static int
 tiff_mmap_memory (data, pbase, psize)
      thandle_t data;
@@ -7052,6 +8123,7 @@ tiff_mmap_memory (data, pbase, psize)
   return 0;
 }
 
+
 static void
 tiff_unmap_memory (data, base, size)
      thandle_t data;
@@ -7061,6 +8133,7 @@ tiff_unmap_memory (data, base, size)
   /* We don't need to do this. */
 }
 
+
 static toff_t
 tiff_size_of_memory (data)
      thandle_t data;
@@ -7068,6 +8141,35 @@ tiff_size_of_memory (data)
   return ((tiff_memory_source *) data)->len;
 }
 
+
+static void
+tiff_error_handler (title, format, ap)
+     const char *title, *format;
+     va_list ap;
+{
+  char buf[512];
+  int len;
+
+  len = sprintf (buf, "TIFF error: %s ", title);
+  vsprintf (buf + len, format, ap);
+  add_to_log (buf, Qnil, Qnil);
+}
+
+
+static void
+tiff_warning_handler (title, format, ap)
+     const char *title, *format;
+     va_list ap;
+{
+  char buf[512];
+  int len;
+
+  len = sprintf (buf, "TIFF warning: %s ", title);
+  vsprintf (buf + len, format, ap);
+  add_to_log (buf, Qnil, Qnil);
+}
+
+
 /* Load TIFF image IMG for use on frame F.  Value is non-zero if
    successful.  */
 
@@ -7082,7 +8184,7 @@ tiff_load (f, img)
   int width, height, x, y;
   uint32 *buf;
   int rc;
-  XImage *ximg;
+  XImagePtr ximg;
   struct gcpro gcpro1;
   tiff_memory_source memsrc;
 
@@ -7091,25 +8193,28 @@ tiff_load (f, img)
   file = Qnil;
   GCPRO1 (file);
 
+  TIFFSetErrorHandler (tiff_error_handler);
+  TIFFSetWarningHandler (tiff_warning_handler);
+
   if (NILP (specified_data))
     {
       /* Read from a file */
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
 
       /* Try to open the image file.  */
       tiff = TIFFOpen (SDATA (file), "r");
       if (tiff == NULL)
-        {
-          image_error ("Cannot open `%s'", file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+       {
+         image_error ("Cannot open `%s'", file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
     }
   else
     {
@@ -7151,19 +8256,18 @@ tiff_load (f, img)
       return 0;
     }
 
-  BLOCK_INPUT;
-
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
-      UNBLOCK_INPUT;
       xfree (buf);
       UNGCPRO;
       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)
@@ -7180,24 +8284,29 @@ tiff_load (f, img)
        }
     }
 
+#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;
+
+  /* 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, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
   xfree (buf);
-  UNBLOCK_INPUT;
-
-  img->width = width;
-  img->height = height;
 
   UNGCPRO;
   return 1;
 }
 
-#endif /* HAVE_TIFF != 0 */
+#endif /* HAVE_TIFF */
 
 
 \f
@@ -7205,10 +8314,6 @@ tiff_load (f, img)
                                 GIF
  ***********************************************************************/
 
-#if HAVE_GIF
-
-#include <gif_lib.h>
-
 static int gif_image_p P_ ((Lisp_Object object));
 static int gif_load P_ ((struct frame *f, struct image *img));
 
@@ -7228,7 +8333,9 @@ enum gif_keyword_index
   GIF_RELIEF,
   GIF_ALGORITHM,
   GIF_HEURISTIC_MASK,
+  GIF_MASK,
   GIF_IMAGE,
+  GIF_BACKGROUND,
   GIF_LAST
 };
 
@@ -7240,12 +8347,14 @@ 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},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":image",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0}
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":image",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `gif'.  */
@@ -7259,6 +8368,7 @@ static struct image_type gif_type =
   NULL
 };
 
+
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
@@ -7268,15 +8378,200 @@ 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;
 }
 
+#ifndef HAVE_GIF
+
+static int
+gif_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  Lisp_Object specified_file, file;
+  Lisp_Object specified_data;
+  OSErr err;
+  Boolean graphic_p, movie_p, prefer_graphic_p;
+  Handle dh = NULL;
+  Movie movie = NULL;
+  Lisp_Object image;
+  Track track = NULL;
+  Media media = NULL;
+  long nsamples;
+  Rect rect;
+  Lisp_Object specified_bg;
+  XColor color;
+  RGBColor bg_color;
+  int width, height;
+  XImagePtr ximg;
+  TimeValue time;
+  struct gcpro gcpro1;
+  int ino;
+
+  specified_file = image_spec_value (img->spec, QCfile, NULL);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+
+  if (NILP (specified_data))
+    {
+      /* Read from a file */
+      FSSpec fss;
+      short refnum;
+
+      err = find_image_fsspec (specified_file, &file, &fss);
+      if (err != noErr)
+       {
+         if (err == fnfErr)
+           image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         else
+           goto open_error;
+       }
+
+      err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
+                                 &graphic_p, &movie_p, &prefer_graphic_p, 0);
+      if (err != noErr)
+       goto open_error;
+
+      if (!graphic_p && !movie_p)
+       goto open_error;
+      if (prefer_graphic_p)
+       return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
+      err = OpenMovieFile (&fss, &refnum, fsRdPerm);
+      if (err != noErr)
+       goto open_error;
+      err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
+      CloseMovieFile (refnum);
+      if (err != noErr)
+       {
+         image_error ("Error reading `%s'", file, Qnil);
+         return 0;
+       }
+    }
+  else
+    {
+      /* Memory source! */
+      Handle dref = NULL;
+      long file_type_atom[3];
+
+      err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
+      if (err != noErr)
+       {
+         image_error ("Cannot allocate data handle for `%s'",
+                      img->spec, Qnil);
+         goto error;
+       }
+
+      file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
+      file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
+      file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
+      err = PtrToHand (&dh, &dref, sizeof (Handle));
+      if (err == noErr)
+       /* no file name */
+       err = PtrAndHand ("\p", dref, 1);
+      if (err == noErr)
+       err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
+      if (err != noErr)
+       {
+         image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
+         goto error;
+       }
+      err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
+                                    &movie_p, &prefer_graphic_p, 0);
+      if (err != noErr)
+       goto open_error;
+
+      if (!graphic_p && !movie_p)
+       goto open_error;
+      if (prefer_graphic_p)
+       {
+         int success_p;
+
+         DisposeHandle (dref);
+         success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
+         DisposeHandle (dh);
+         return success_p;
+       }
+      err = NewMovieFromDataRef (&movie, 0, NULL, dref,
+                                HandleDataHandlerSubType);
+      DisposeHandle (dref);
+      if (err != noErr)
+       goto open_error;
+    }
+
+  image = image_spec_value (img->spec, QCindex, NULL);
+  ino = INTEGERP (image) ? XFASTINT (image) : 0;
+  track = GetMovieIndTrack (movie, 1);
+  media = GetTrackMedia (track);
+  nsamples = GetMediaSampleCount (media);
+  if (ino >= nsamples)
+    {
+      image_error ("Invalid image number `%s' in image `%s'",
+                  image, img->spec);
+      goto error;
+    }
+
+  specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+  if (!STRINGP (specified_bg) ||
+      !mac_defined_color (f, SDATA (specified_bg), &color, 0))
+    {
+      color.pixel = FRAME_BACKGROUND_PIXEL (f);
+      color.red = RED16_FROM_ULONG (color.pixel);
+      color.green = GREEN16_FROM_ULONG (color.pixel);
+      color.blue = BLUE16_FROM_ULONG (color.pixel);
+    }
+  GetMovieBox (movie, &rect);
+  width = img->width = rect.right - rect.left;
+  height = img->height = rect.bottom - rect.top;
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    goto error;
+
+  SetGWorld (ximg, NULL);
+  bg_color.red = color.red;
+  bg_color.green = color.green;
+  bg_color.blue = color.blue;
+  RGBBackColor (&bg_color);
+  SetMovieActive (movie, TRUE);
+  SetMovieGWorld (movie, ximg, NULL);
+  SampleNumToMediaTime (media, ino + 1, &time, NULL);
+  SetMovieTimeValue (movie, time);
+  MoviesTask (movie, 0L);
+  DisposeTrackMedia (media);
+  DisposeMovieTrack (track);
+  DisposeMovie (movie);
+  if (dh)
+    DisposeHandle (dh);
+  /* 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);
+  return 1;
+
+ open_error:
+  image_error ("Cannot open `%s'", file, Qnil);
+ error:
+  if (media)
+    DisposeTrackMedia (media);
+  if (track)
+    DisposeMovieTrack (track);
+  if (movie)
+    DisposeMovie (movie);
+  if (dh)
+    DisposeHandle (dh);
+  return 0;
+}
+
+#else
+
+#define DrawText gif_DrawText  /* avoid conflict with QuickdrawText.h */
+#include <gif_lib.h>
+#undef DrawText
+
 /* Reading a GIF image from memory
    Based on the PNG memory stuff to a certain extent. */
 
@@ -7288,6 +8583,7 @@ typedef struct
 }
 gif_memory_source;
 
+
 /* Make the current memory source available to gif_read_from_memory.
    It's done this way because not all versions of libungif support
    a UserData field in the GifFileType structure.  */
@@ -7321,7 +8617,7 @@ gif_load (f, img)
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
   int rc, width, height, x, y, i;
-  XImage *ximg;
+  XImagePtr ximg;
   ColorMapObject *gif_color_map;
   unsigned long pixel_colors[256];
   GifFileType *gif;
@@ -7340,20 +8636,20 @@ gif_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 GIF file.  */
       gif = DGifOpenFileName (SDATA (file));
       if (gif == NULL)
-        {
-          image_error ("Cannot open `%s'", file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+       {
+         image_error ("Cannot open `%s'", file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
     }
   else
     {
@@ -7363,7 +8659,7 @@ gif_load (f, img)
       memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
-      gif = DGifOpen(&memsrc, gif_read_from_memory);
+      gif = DGifOpen (&memsrc, gif_read_from_memory);
       if (!gif)
        {
          image_error ("Cannot open memory source `%s'", img->spec, Qnil);
@@ -7387,21 +8683,18 @@ gif_load (f, img)
   if (ino >= gif->ImageCount)
     {
       image_error ("Invalid image number `%s' in image `%s'",
-                   image, img->spec);
+                  image, img->spec);
       DGifCloseFile (gif);
       UNGCPRO;
       return 0;
     }
 
-  width = img->width = gif->SWidth;
-  height = img->height = gif->SHeight;
-
-  BLOCK_INPUT;
+  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))
     {
-      UNBLOCK_INPUT;
       DGifCloseFile (gif);
       UNGCPRO;
       return 0;
@@ -7411,7 +8704,9 @@ gif_load (f, img)
   gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
   if (!gif_color_map)
     gif_color_map = gif->SColorMap;
+#if 0 /* TODO: Color tables */
   init_color_table ();
+#endif
   bzero (pixel_colors, sizeof pixel_colors);
 
   for (i = 0; i < gif_color_map->ColorCount; ++i)
@@ -7422,8 +8717,10 @@ gif_load (f, img)
       pixel_colors[i] = lookup_rgb_color (f, r, g, b);
     }
 
+#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
@@ -7460,7 +8757,7 @@ gif_load (f, img)
     {
       static int interlace_start[] = {0, 4, 2, 1};
       static int interlace_increment[] = {8, 8, 4, 2};
-      int pass, inc;
+      int pass;
       int row = interlace_start[0];
 
       pass = 0;
@@ -7489,23 +8786,25 @@ gif_load (f, img)
       for (y = 0; y < image_height; ++y)
        for (x = 0; x < image_width; ++x)
          {
-           int i = raster[y* image_width + x];
+           int i = raster[y * image_width + x];
            XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
          }
     }
 
   DGifCloseFile (gif);
 
+  /* 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, then free the X image and its buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
-  UNBLOCK_INPUT;
 
   UNGCPRO;
   return 1;
 }
-
-#endif /* HAVE_GIF != 0 */
+#endif /* HAVE_GIF */
 
 
 \f
@@ -7513,11 +8812,6 @@ gif_load (f, img)
                                Ghostscript
  ***********************************************************************/
 
-#ifdef HAVE_GHOSTSCRIPT
-static int gs_image_p P_ ((Lisp_Object object));
-static int gs_load P_ ((struct frame *f, struct image *img));
-static void gs_clear_image P_ ((struct frame *f, struct image *img));
-
 /* The symbol `postscript' identifying images of this type.  */
 
 Lisp_Object Qpostscript;
@@ -7526,6 +8820,11 @@ Lisp_Object Qpostscript;
 
 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));
+static void gs_clear_image P_ ((struct frame *f, struct image *img));
+
 /* Indices of image specification fields in gs_format, below.  */
 
 enum gs_keyword_index
@@ -7541,6 +8840,8 @@ enum gs_keyword_index
   GS_RELIEF,
   GS_ALGORITHM,
   GS_HEURISTIC_MASK,
+  GS_MASK,
+  GS_BACKGROUND,
   GS_LAST
 };
 
@@ -7555,11 +8856,13 @@ 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},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
 /* Structure describing the image type `ghostscript'.  */
@@ -7600,9 +8903,7 @@ gs_image_p (object)
 
   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.  */
@@ -7651,18 +8952,16 @@ gs_load (f, img)
      info.  */
   pt_width = image_spec_value (img->spec, QCpt_width, NULL);
   in_width = XFASTINT (pt_width) / 72.0;
-  img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
+  img->width = in_width * FRAME_MAC_DISPLAY_INFO (f)->resx;
   pt_height = image_spec_value (img->spec, QCpt_height, NULL);
   in_height = XFASTINT (pt_height) / 72.0;
-  img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
+  img->height = in_height * FRAME_MAC_DISPLAY_INFO (f)->resy;
 
   /* Create the pixmap.  */
-  BLOCK_INPUT;
-  xassert (img->pixmap == 0);
-  img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
+  xassert (img->pixmap == NULL);
+  img->pixmap = XCreatePixmap (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
                               img->width, img->height,
-                              DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
-  UNBLOCK_INPUT;
+                              one_mac_display_info.n_planes);
 
   if (!img->pixmap)
     {
@@ -7677,7 +8976,7 @@ gs_load (f, img)
   GCPRO2 (window_and_pixmap_id, pixel_colors);
 
   sprintf (buffer, "%lu %lu",
-          (unsigned long) FRAME_W32_WINDOW (f),
+          (unsigned long) FRAME_MAC_WINDOW (f),
           (unsigned long) img->pixmap);
   window_and_pixmap_id = build_string (buffer);
 
@@ -7719,26 +9018,31 @@ x_kill_gs_process (pixmap, f)
     if (c->images[i]->pixmap == pixmap)
       break;
 
+  /* Should someone in between have cleared the image cache, for
+     instance, give up.  */
+  if (i == c->used)
+    return;
+
   /* Kill the GS process.  We should have found PIXMAP in the image
      cache and its image should contain a process object.  */
-  xassert (i < c->used);
   img = c->images[i];
   xassert (PROCESSP (img->data.lisp_val));
   Fkill_process (img->data.lisp_val, Qnil);
   img->data.lisp_val = Qnil;
 
+#if 0
   /* On displays with a mutable colormap, figure out the colors
      allocated for the image by looking at the pixels of an XImage for
      img->pixmap.  */
-  class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
+  class = FRAME_MAC_DISPLAY_INFO (f)->visual->class;
   if (class != StaticColor && class != StaticGray && class != TrueColor)
     {
-      XImage *ximg;
+      XImagePtr ximg;
 
       BLOCK_INPUT;
 
       /* Try to get an XImage for img->pixmep.  */
-      ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
+      ximg = XGetImage (FRAME_MAC_DISPLAY (f), img->pixmap,
                        0, 0, img->width, img->height, ~0, ZPixmap);
       if (ximg)
        {
@@ -7769,11 +9073,7 @@ x_kill_gs_process (pixmap, f)
             allocated colors on behalf of us.  So, to get the
             reference counts right, free them once.  */
          if (img->ncolors)
-           {
-             Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-             XFreeColors (FRAME_W32_DISPLAY (f), cmap,
-                          img->colors, img->ncolors, 0);
-           }
+           x_free_colors (f, img->colors, img->ncolors);
 #endif
        }
       else
@@ -7782,6 +9082,13 @@ x_kill_gs_process (pixmap, f)
 
       UNBLOCK_INPUT;
     }
+#endif
+
+  /* Now that we have the pixmap, compute mask and transform the
+     image if requested.  */
+  BLOCK_INPUT;
+  postprocess_image (f, img);
+  UNBLOCK_INPUT;
 }
 
 #endif /* HAVE_GHOSTSCRIPT */
@@ -8806,6 +10113,18 @@ syms_of_macfns ()
 
   Qlaplace = intern ("laplace");
   staticpro (&Qlaplace);
+  Qemboss = intern ("emboss");
+  staticpro (&Qemboss);
+  Qedge_detection = intern ("edge-detection");
+  staticpro (&Qedge_detection);
+  Qheuristic = intern ("heuristic");
+  staticpro (&Qheuristic);
+  QCmatrix = intern (":matrix");
+  staticpro (&QCmatrix);
+  QCcolor_adjustment = intern (":color-adjustment");
+  staticpro (&QCcolor_adjustment);
+  QCmask = intern (":mask");
+  staticpro (&QCmask);
 
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
@@ -8815,6 +10134,12 @@ syms_of_macfns ()
   Fput (Qundefined_color, Qerror_message,
        build_string ("Undefined color"));
 
+  DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
+    doc: /* Non-nil means always draw a cross over disabled images.
+Disabled images are those having an `:conversion disabled' property.
+A cross is always drawn on black & white displays.  */);
+  cross_disabled_images = 0;
+
   DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
               doc: /* List of directories to search for window system bitmap files.  */);
   Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
@@ -8880,9 +10205,11 @@ from the image cache.  Value must be an integer or nil with nil
 meaning don't clear the cache.  */);
   Vimage_cache_eviction_delay = make_number (30 * 60);
 
+  /* X window properties.  */
   defsubr (&Sx_change_window_property);
   defsubr (&Sx_delete_window_property);
   defsubr (&Sx_window_property);
+
   defsubr (&Sxw_display_color_p);
   defsubr (&Sx_display_grayscale_p);
   defsubr (&Sxw_color_defined_p);
@@ -8919,15 +10246,12 @@ meaning don't clear the cache.  */);
   load_font_func = x_load_font;
   find_ccl_program_func = x_find_ccl_program;
   query_font_func = x_query_font;
-
   set_frame_fontset_func = x_set_font;
   check_window_system_func = check_mac;
 
-#if 0 /* MAC_TODO: Image support for Mac Images.  */
+  /* Images.  */
   Qxbm = intern ("xbm");
   staticpro (&Qxbm);
-  QCtype = intern (":type");
-  staticpro (&QCtype);
   QCconversion = intern (":conversion");
   staticpro (&QCconversion);
   QCheuristic_mask = intern (":heuristic-mask");
@@ -8960,41 +10284,36 @@ meaning don't clear the cache.  */);
   staticpro (&Qxpm);
 #endif
 
-#if HAVE_JPEG
   Qjpeg = intern ("jpeg");
   staticpro (&Qjpeg);
-#endif
 
-#if HAVE_TIFF
   Qtiff = intern ("tiff");
   staticpro (&Qtiff);
-#endif
 
-#if HAVE_GIF
   Qgif = intern ("gif");
   staticpro (&Qgif);
-#endif
 
-#if HAVE_PNG
   Qpng = intern ("png");
   staticpro (&Qpng);
-#endif
 
   defsubr (&Sclear_image_cache);
+  defsubr (&Simage_size);
+  defsubr (&Simage_mask_p);
 
 #if GLYPH_DEBUG
   defsubr (&Simagep);
   defsubr (&Slookup_image);
 #endif
-#endif /* MAC_TODO */
 
   hourglass_atimer = NULL;
   hourglass_shown_p = 0;
 
   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);
-  staticpro (&tip_timer);
   tip_timer = Qnil;
+  staticpro (&tip_timer);
+  tip_frame = Qnil;
+  staticpro (&tip_frame);
 
 #if 0 /* MAC_TODO */
   defsubr (&Sx_file_dialog);
@@ -9009,30 +10328,26 @@ init_xfns ()
   Vimage_types = Qnil;
 
   define_image_type (&xbm_type);
-#if 0 /* NTEMACS_TODO : Image support for W32 */
+#if HAVE_GHOSTSCRIPT
   define_image_type (&gs_type);
+#endif
   define_image_type (&pbm_type);
 
 #if HAVE_XPM
   define_image_type (&xpm_type);
 #endif
 
-#if HAVE_JPEG
   define_image_type (&jpeg_type);
-#endif
-
-#if HAVE_TIFF
   define_image_type (&tiff_type);
-#endif
-
-#if HAVE_GIF
   define_image_type (&gif_type);
-#endif
-
-#if HAVE_PNG
   define_image_type (&png_type);
+
+  /* Animated gifs use QuickTime Movie Toolbox.  So initialize it
+     here. */
+  EnterMovies ();
+#ifdef MAC_OSX
+  init_image_func_pointer ();
 #endif
-#endif /* NTEMACS_TODO */
 }
 
 /* arch-tag: d7591289-f374-4377-b245-12f5dbbb8edc
index 34f5913d5dfd7b167eceb6017054fcf72599492b..2bb346e9d30eb9bdaca8469dde8d516fe26eb0cc 100644 (file)
@@ -23,9 +23,6 @@ Boston, MA 02111-1307, USA.  */
 #ifndef EMACS_MACGUI_H
 #define EMACS_MACGUI_H
 
-typedef int Pixmap;
-typedef int Bitmap;
-
 typedef int Display;  /* fix later */
 
 typedef char * XrmDatabase;  /* fix later */
@@ -33,12 +30,43 @@ typedef char * XrmDatabase;  /* fix later */
 typedef unsigned long Time;
 
 #if MAC_OSX
+#undef mktime
+#undef DEBUG
+#undef Z
+#undef free
+#undef malloc
+#undef realloc
+/* Macros max and min defined in lisp.h conflict with those in
+   precompiled header Carbon.h.  */
+#undef max
+#undef min
+#undef init_process
+#include <Carbon/Carbon.h>
+#undef Z
+#define Z (current_buffer->text->z)
+#undef free
+#define free unexec_free
+#undef malloc
+#define malloc unexec_malloc
+#undef realloc
+#define realloc unexec_realloc
+#undef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#undef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#undef init_process
+#define init_process emacs_init_process
+#undef INFINITY
 typedef struct OpaqueWindowPtr* Window;
 #else
-#include <QuickDraw.h>
+#include <QuickDraw.h>         /* for WindowPtr */
+#include <QDOffscreen.h>       /* for GWorldPtr */
+#include <Controls.h>          /* for ControlHandle in xdisp.c */
 typedef WindowPtr Window;
 #endif
 
+typedef GWorldPtr Pixmap;
+
 #define FACE_DEFAULT (~0)
 
 
index 0a6747896b6643b496a126eb1954091665094967..06b1b16cf419ad26d39ecfd7f524f3922f03bc98 100644 (file)
@@ -35,34 +35,7 @@ Boston, MA 02111-1307, USA.  */
 #include "charset.h"
 #include "coding.h"
 
-#ifdef MAC_OSX
-#undef mktime
-#undef DEBUG
-#undef Z
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef Z
-#define Z (current_buffer->text->z)
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
-#else /* not MAC_OSX */
+#ifndef MAC_OSX
 #include <MacTypes.h>
 #include <Menus.h>
 #include <QuickDraw.h>
index f6e5414c29956224ab6efeb33bcd2e3b3be932d8..a22a1cfafe864512d563e177d4c129242189113b 100644 (file)
@@ -35,29 +35,6 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 #ifdef MAC_OSX
-#undef mktime
-#undef DEBUG
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
    obtain events from the event queue.  If set to 0, WaitNextEvent is
    used instead.  */
@@ -303,7 +280,9 @@ static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
+                                  enum text_cursor_kinds));
+
 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
@@ -327,15 +306,12 @@ extern void set_frame_menubar (FRAME_PTR, int, int);
 
 /* X display function emulation */
 
-static void
+void
 XFreePixmap (display, pixmap)
-     Display *display;
+     Display *display;         /* not used */
      Pixmap pixmap;
 {
-  PixMap *p = (PixMap *) pixmap;
-
-  xfree (p->baseAddr);
-  xfree (p);
+  DisposeGWorld (pixmap); 
 }
 
 
@@ -347,9 +323,9 @@ mac_set_forecolor (unsigned long color)
 {
   RGBColor fg_color;
 
-  fg_color.red = RED_FROM_ULONG (color) * 256;
-  fg_color.green = GREEN_FROM_ULONG (color) * 256;
-  fg_color.blue = BLUE_FROM_ULONG (color) * 256;
+  fg_color.red = RED16_FROM_ULONG (color);
+  fg_color.green = GREEN16_FROM_ULONG (color);
+  fg_color.blue = BLUE16_FROM_ULONG (color);
 
   RGBForeColor (&fg_color);
 }
@@ -363,9 +339,9 @@ mac_set_backcolor (unsigned long color)
 {
   RGBColor bg_color;
 
-  bg_color.red = RED_FROM_ULONG (color) * 256;
-  bg_color.green = GREEN_FROM_ULONG (color) * 256;
-  bg_color.blue = BLUE_FROM_ULONG (color) * 256;
+  bg_color.red = RED16_FROM_ULONG (color);
+  bg_color.green = GREEN16_FROM_ULONG (color);
+  bg_color.blue = BLUE16_FROM_ULONG (color);
 
   RGBBackColor (&bg_color);
 }
@@ -401,6 +377,23 @@ XDrawLine (display, w, gc, x1, y1, x2, y2)
   LineTo (x2, y2);
 }
 
+void
+mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
+     Display *display;
+     Pixmap p;
+     GC gc;
+     int x1, y1, x2, y2;
+{
+  SetGWorld (p, NULL);
+
+  mac_set_colors (gc);
+
+  LockPixels (GetGWorldPixMap (p));
+  MoveTo (x1, y1);
+  LineTo (x2, y2);
+  UnlockPixels (GetGWorldPixMap (p));
+}
+
 /* Mac version of XClearArea.  */
 
 void
@@ -479,7 +472,7 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
   Rect r;
 
   bitmap.rowBytes = sizeof(unsigned short);
-  bitmap.baseAddr = bits;
+  bitmap.baseAddr = (char *)bits;
   SetRect (&(bitmap.bounds), 0, 0, width, height);
 
 #if TARGET_API_MAC_CARBON
@@ -489,18 +482,13 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
 #endif
 
   mac_set_colors (gc);
-  SetRect (&r, x, y, x + bitmap.bounds.right, y + bitmap.bounds.bottom);
+  SetRect (&r, x, y, x + width, y + height);
 
 #if TARGET_API_MAC_CARBON
-  {
-    PixMapHandle pmh;
-
-    LockPortBits (GetWindowPort (w));
-    pmh = GetPortPixMap (GetWindowPort (w));
-    CopyBits (&bitmap, (BitMap *) *pmh, &(bitmap.bounds), &r,
-             overlay_p ? srcOr : srcCopy, 0);
-    UnlockPortBits (GetWindowPort (w));
-  }
+  LockPortBits (GetWindowPort (w));
+  CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
+           &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
+  UnlockPortBits (GetWindowPort (w));
 #else /* not TARGET_API_MAC_CARBON */
   CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
            overlay_p ? srcOr : srcCopy, 0);
@@ -546,6 +534,23 @@ mac_reset_clipping (display, w)
 }
 
 
+/* XBM bits seem to be backward within bytes compared with how
+   Mac does things.  */
+static unsigned char
+reflect_byte (orig)
+     unsigned char orig;
+{
+  int i;
+  unsigned char reflected = 0x00;
+  for (i = 0; i < 8; i++)
+    {
+      if (orig & (0x01 << i))
+       reflected |= 0x80 >> i;
+    }
+  return reflected;
+}
+
+
 /* Mac replacement for XCreateBitmapFromBitmapData.  */
 
 static void
@@ -554,18 +559,19 @@ mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
      char *bits;
      int w, h;
 {
-  int bytes_per_row, i, j;
+  int i, j, w1;
+  char *p;
 
-  bitmap->rowBytes = (w + 15) / 16 * 2;  /* must be on word boundary */
+  w1 = (w + 7) / 8;         /* nb of 8bits elt in X bitmap */
+  bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
   bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
-  if (!bitmap->baseAddr)
-    abort ();
-
   bzero (bitmap->baseAddr, bitmap->rowBytes * h);
   for (i = 0; i < h; i++)
-    for (j = 0; j < w; j++)
-      if (BitTst (bits, i * w + j))
-        BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
+    {
+      p = bitmap->baseAddr + i * bitmap->rowBytes;
+      for (j = 0; j < w1; j++)
+        *p++ = reflect_byte (*bits++);
+    }
 
   SetRect (&(bitmap->bounds), 0, 0, w, h);
 }
@@ -578,6 +584,67 @@ mac_free_bitmap (bitmap)
   xfree (bitmap->baseAddr);
 }
 
+
+Pixmap
+XCreatePixmap (display, w, width, height, depth)
+     Display *display;         /* not used */
+     WindowPtr w;
+     unsigned int width, height;
+     unsigned int depth;       /* not used */
+{
+  Pixmap pixmap;
+  Rect r;
+  QDErr err;
+
+#if TARGET_API_MAC_CARBON
+  SetPort (GetWindowPort (w));
+#else
+  SetPort (w);
+#endif
+
+  SetRect (&r, 0, 0, width, height);
+  err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
+  if (err != noErr)
+    return NULL;
+  return pixmap;
+}
+
+
+Pixmap
+XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
+     Display *display;         /* not used */
+     WindowPtr w;
+     char *data;
+     unsigned int width, height;
+     unsigned long fg, bg;
+     unsigned int depth;       /* not used */
+{
+  Pixmap pixmap;
+  BitMap bitmap;
+
+  pixmap = XCreatePixmap (display, w, width, height, depth);
+  if (pixmap == NULL)
+    return NULL;
+
+  SetGWorld (pixmap, NULL);
+  mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
+  mac_set_forecolor (fg);
+  mac_set_backcolor (bg);
+  LockPixels (GetGWorldPixMap (pixmap));
+#if TARGET_API_MAC_CARBON
+  CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
+           &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
+           &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (pixmap));
+  mac_free_bitmap (&bitmap);
+
+  return pixmap;
+}
+
+
 /* Mac replacement for XFillRectangle.  */
 
 static void
@@ -603,6 +670,26 @@ XFillRectangle (display, w, gc, x, y, width, height)
 }
 
 
+static void
+mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
+     Display *display;
+     Pixmap p;
+     GC gc;
+     int x, y;
+     unsigned int width, height;
+{
+  Rect r;
+
+  SetGWorld (p, NULL);
+  mac_set_colors (gc);
+  SetRect (&r, x, y, x + width, y + height);
+
+  LockPixels (GetGWorldPixMap (p));
+  PaintRect (&r); /* using foreground color of gc */
+  UnlockPixels (GetGWorldPixMap (p));
+}
+
+
 /* Mac replacement for XDrawRectangle: dest is a window.  */
 
 static void
@@ -638,20 +725,15 @@ mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
-#if 0 /* MAC_TODO: draw a rectangle in a PixMap */
   Rect r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
-
+  SetGWorld (p, NULL);
   mac_set_colors (gc);
-  SetRect (&r, x, y, x + width, y + height);
+  SetRect (&r, x, y, x + width + 1, y + height + 1);
 
+  LockPixels (GetGWorldPixMap (p));
   FrameRect (&r); /* using foreground color of gc */
-#endif /* 0 */
+  UnlockPixels (GetGWorldPixMap (p));
 }
 
 
@@ -766,23 +848,66 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
   SetPort (dest);
 #endif
 
-  mac_set_colors (gc);
-
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
 
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  LockPixels (GetGWorldPixMap (src));
 #if TARGET_API_MAC_CARBON
-  {
-    PixMapHandle pmh;
+  LockPortBits (GetWindowPort (dest));
+  CopyBits (GetPortBitMapForCopyBits (src),
+           GetPortBitMapForCopyBits (GetWindowPort (dest)),
+           &src_r, &dest_r, srcCopy, 0);
+  UnlockPortBits (GetWindowPort (dest));
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
+           &src_r, &dest_r, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (src));
+}
 
-    LockPortBits (GetWindowPort (dest));
-    pmh = GetPortPixMap (GetWindowPort (dest));
-    CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
-    UnlockPortBits (GetWindowPort (dest));
-  }
+
+static void
+mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
+                        width, height, dest_x, dest_y)
+     Display *display;
+     Pixmap src, mask;
+     WindowPtr dest;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y;
+{
+  Rect src_r, dest_r;
+
+#if TARGET_API_MAC_CARBON
+  SetPort (GetWindowPort (dest));
+#else
+  SetPort (dest);
+#endif
+
+  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (mask));
+#if TARGET_API_MAC_CARBON
+  LockPortBits (GetWindowPort (dest));
+  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
+           GetPortBitMapForCopyBits (GetWindowPort (dest)),
+           &src_r, &src_r, &dest_r);
+  UnlockPortBits (GetWindowPort (dest));
 #else /* not TARGET_API_MAC_CARBON */
-  CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
+  CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
+           &(dest->portBits), &src_r, &src_r, &dest_r);
 #endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (mask));
+  UnlockPixels (GetGWorldPixMap (src));
 }
 
 
@@ -817,7 +942,6 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
 {
 #if TARGET_API_MAC_CARBON
   Rect gw_r, src_r, dest_r;
-  PixMapHandle pmh;
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -828,8 +952,10 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
   BackColor (whiteColor);
 
   LockPortBits (GetWindowPort (w));
-  pmh = GetPortPixMap (GetWindowPort (w));
-  CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
+  {
+    const BitMap *bitmap = GetPortBitMapForCopyBits (GetWindowPort (w));
+    CopyBits (bitmap, bitmap, &src_r, &dest_r, srcCopy, 0);
+  }
   UnlockPortBits (GetWindowPort (w));
 
   mac_set_colors (gc);
@@ -872,25 +998,67 @@ static void
 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
                      dest_x, dest_y)
      Display *display;
-     Pixmap src;
-     Pixmap dest;
+     Pixmap src, dest;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
      int dest_x, dest_y;
 {
   Rect src_r, dest_r;
-  int src_right = ((PixMap *) src)->bounds.right;
-  int src_bottom = ((PixMap *) src)->bounds.bottom;
-  int w = src_right - src_x;
-  int h = src_bottom - src_y;
 
-  mac_set_colors (gc);
+  SetGWorld (dest, NULL);
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (dest));
+#if TARGET_API_MAC_CARBON
+  CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
+           &src_r, &dest_r, srcCopy, 0);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
+           &src_r, &dest_r, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (dest));
+  UnlockPixels (GetGWorldPixMap (src));
+}
+
+
+static void
+mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
+                                  width, height, dest_x, dest_y)
+     Display *display;
+     Pixmap src, mask, dest;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y;
+{
+  Rect src_r, dest_r;
+
+  SetGWorld (dest, NULL);
+  ForeColor (blackColor);
+  BackColor (whiteColor);
 
-  SetRect (&src_r, src_x, src_y, src_right, src_bottom);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
+  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
 
-  CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (mask));
+  LockPixels (GetGWorldPixMap (dest));
+#if TARGET_API_MAC_CARBON
+  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
+           GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
+           &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (dest));
+  UnlockPixels (GetGWorldPixMap (mask));
+  UnlockPixels (GetGWorldPixMap (src));
 }
 
 
@@ -947,7 +1115,7 @@ XGetGCValues (void* ignore, XGCValues *gc,
 
 /* Mac replacement for XSetForeground.  */
 
-static void
+void
 XSetForeground (display, gc, color)
      Display *display;
      GC gc;
@@ -2139,6 +2307,21 @@ x_copy_dpy_color (dpy, cmap, pixel)
 
 #endif /* MAC_TODO */
 
+
+/* Brightness beyond which a color won't have its highlight brightness
+   boosted.
+
+   Nominally, highlight colors for `3d' faces are calculated by
+   brightening an object's color by a constant scale factor, but this
+   doesn't yield good results for dark colors, so for colors who's
+   brightness is less than this value (on a scale of 0-255) have to
+   use an additional additive factor.
+
+   The value here is set so that the default menu-bar/mode-line color
+   (grey75) will not have its highlights changed at all.  */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
+
+
 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
    or DELTA.  Try a color with RGB values multiplied by FACTOR first.
    If this produces the same color as COLOR, try a color where all RGB
@@ -2154,12 +2337,42 @@ mac_alloc_lighter_color (f, color, factor, delta)
      int delta;
 {
   unsigned long new;
+  long bright;
+
+  /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
+  delta /= 256;
 
   /* Change RGB values by specified FACTOR.  Avoid overflow!  */
   xassert (factor >= 0);
   new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
                     min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
                     min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
+
+  /* Calculate brightness of COLOR.  */
+  bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
+            + BLUE_FROM_ULONG (*color)) / 6;
+
+  /* We only boost colors that are darker than
+     HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
+  if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+    /* Make an additive adjustment to NEW, because it's dark enough so
+       that scaling by FACTOR alone isn't enough.  */
+    {
+      /* How far below the limit this color is (0 - 1, 1 being darker).  */
+      double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+      /* The additive adjustment.  */
+      int min_delta = delta * dimness * factor / 2;
+
+      if (factor < 1)
+        new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
+                           max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
+                           max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
+      else
+        new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
+                           max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
+                           max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
+    }
+
   if (new == *color)
     new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
                       max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
@@ -2204,7 +2417,8 @@ x_setup_relief_color (f, relief, factor, delta, default_pixel)
   /* Allocate new color.  */
   xgcv.foreground = default_pixel;
   pixel = background;
-  if (mac_alloc_lighter_color (f, &pixel, factor, delta))
+  if (dpyinfo->n_planes != 1
+      && mac_alloc_lighter_color (f, &pixel, factor, delta))
     {
       relief->allocated_p = 1;
       xgcv.foreground = relief->pixel = pixel;
@@ -2234,6 +2448,10 @@ x_setup_relief_colors (s)
 
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
+  else if (s->first_glyph->type == IMAGE_GLYPH
+          && s->img->pixmap
+          && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+    color = IMAGE_BACKGROUND (s->img, s->f, 0);
   else
     {
       XGCValues xgcv;
@@ -2267,9 +2485,11 @@ static void
 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
                    raised_p, left_p, right_p, clip_rect)
      struct frame *f;
-     int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
+     int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
      Rect *clip_rect;
 {
+  Display *dpy = FRAME_MAC_DISPLAY (f);
+  Window window = FRAME_MAC_WINDOW (f);
   int i;
   GC gc;
 
@@ -2277,41 +2497,41 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
     gc = f->output_data.mac->white_relief.gc;
   else
     gc = f->output_data.mac->black_relief.gc;
-  mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
+  mac_set_clip_rectangle (dpy, window, clip_rect);
 
   /* Top.  */
   for (i = 0; i < width; ++i)
-    XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+    XDrawLine (dpy, window, gc,
               left_x + i * left_p, top_y + i,
-              right_x + 1 - i * right_p, top_y + i);
+              right_x - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+      XDrawLine (dpy, window, gc,
                 left_x + i, top_y + i, left_x + i, bottom_y - i);
 
-  mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+  mac_reset_clipping (dpy, window);
   if (raised_p)
     gc = f->output_data.mac->black_relief.gc;
   else
     gc = f->output_data.mac->white_relief.gc;
-  mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+  mac_set_clip_rectangle (dpy, window,
                          clip_rect);
 
   /* Bottom.  */
   for (i = 0; i < width; ++i)
-    XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+    XDrawLine (dpy, window, gc,
               left_x + i * left_p, bottom_y - i,
-              right_x + 1 - i * right_p, bottom_y - i);
+              right_x - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
-                right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
+      XDrawLine (dpy, window, gc,
+                right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
 
-  mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+  mac_reset_clipping (dpy, window);
 }
 
 
@@ -2326,7 +2546,7 @@ static void
 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
                 left_p, right_p, clip_rect)
      struct glyph_string *s;
-     int left_x, top_y, right_x, bottom_y, left_p, right_p;
+     int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
      Rect *clip_rect;
 {
   XGCValues xgcv;
@@ -2336,21 +2556,21 @@ x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
 
   /* Top.  */
   XFillRectangle (s->display, s->window, &xgcv,
-                 left_x, top_y, right_x - left_x, width);
+                 left_x, top_y, right_x - left_x + 1, width);
 
   /* Left.  */
   if (left_p)
     XFillRectangle (s->display, s->window, &xgcv,
-                   left_x, top_y, width, bottom_y - top_y);
+                   left_x, top_y, width, bottom_y - top_y + 1);
 
   /* Bottom.  */
   XFillRectangle (s->display, s->window, &xgcv,
-                 left_x, bottom_y - width, right_x - left_x, width);
+                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
 
   /* Right.  */
   if (right_p)
     XFillRectangle (s->display, s->window, &xgcv,
-                   right_x - width, top_y, width, bottom_y - top_y);
+                   right_x - width + 1, top_y, width, bottom_y - top_y + 1);
 
   mac_reset_clipping (s->display, s->window);
 }
@@ -2385,9 +2605,9 @@ x_draw_glyph_string_box (s)
   width = abs (s->face->box_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
-  right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
-             ? last_x - 1
-             : min (last_x, s->x + s->background_width) - 1));
+  right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
+            ? last_x - 1
+            : min (last_x, s->x + s->background_width) - 1);
   top_y = s->y;
   bottom_y = top_y + s->height - 1;
 
@@ -2438,39 +2658,36 @@ x_draw_image_foreground (s)
 
   if (s->img->pixmap)
     {
-#if 0 /* MAC_TODO: image mask */
       if (s->img->mask)
        {
-         /* We can't set both a clip mask and use XSetClipRectangles
-            because the latter also sets a clip mask.  We also can't
-            trust on the shape extension to be available
-            (XShapeCombineRegion).  So, compute the rectangle to draw
-            manually.  */
-         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-                               | GCFunction);
-         XGCValues xgcv;
+         Rect nr;
          XRectangle clip_rect, image_rect, r;
 
-         xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
-         xgcv.function = GXcopy;
-         XChangeGC (s->display, s->gc, mask, &xgcv);
-
-         get_glyph_string_clip_rect (s, &clip_rect);
+         get_glyph_string_clip_rect (s, &nr);
+         CONVERT_TO_XRECT (clip_rect, nr);
          image_rect.x = x;
          image_rect.y = y;
          image_rect.width = s->img->width;
          image_rect.height = s->img->height;
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+           mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
+                                    s->window, s->gc, r.x - x, r.y - y,
+                                    r.width, r.height, r.x, r.y);
        }
       else
-#endif /* MAC_TODO */
        {
-         mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
-                      0, 0, s->img->width, s->img->height, x, y);
+         Rect nr;
+         XRectangle clip_rect, image_rect, r;
+
+         get_glyph_string_clip_rect (s, &nr);
+         CONVERT_TO_XRECT (clip_rect, nr);
+         image_rect.x = x;
+         image_rect.y = y;
+         image_rect.width = s->img->width;
+         image_rect.height = s->img->height;
+         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
+           mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
+                          r.x - x, r.y - y, r.width, r.height, r.x, r.y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2494,7 +2711,6 @@ x_draw_image_foreground (s)
 }
 
 
-
 /* Draw a relief around the image glyph string S.  */
 
 static void
@@ -2567,30 +2783,12 @@ x_draw_image_foreground_1 (s, pixmap)
 
   if (s->img->pixmap)
     {
-#if 0 /* MAC_TODO: image mask */
       if (s->img->mask)
-       {
-         /* We can't set both a clip mask and use XSetClipRectangles
-            because the latter also sets a clip mask.  We also can't
-            trust on the shape extension to be available
-            (XShapeCombineRegion).  So, compute the rectangle to draw
-            manually.  */
-         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-                               | GCFunction);
-         XGCValues xgcv;
-
-         xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
-         xgcv.function = GXcopy;
-         XChangeGC (s->display, s->gc, mask, &xgcv);
-
-         XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
-         XSetClipMask (s->display, s->gc, None);
-       }
+       mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
+                                          s->img->mask, pixmap, s->gc,
+                                          0, 0, s->img->width, s->img->height,
+                                          x, y);
       else
-#endif /* MAC_TODO */
        {
          mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
                               0, 0, s->img->width, s->img->height, x, y);
@@ -2605,15 +2803,16 @@ x_draw_image_foreground_1 (s, pixmap)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
-                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+             mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
+                                 s->img->width + r*2 - 1,
+                                 s->img->height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
-                             s->img->width - 1, s->img->height - 1);
+                                 s->img->width - 1, s->img->height - 1);
 }
 
 
@@ -2646,7 +2845,7 @@ x_draw_glyph_string_bg_rect (s, x, y, w, h)
             |   s->face->box
             |
             |     +-------------------------
-            |     |  s->img->vmargin
+            |     |  s->img->margin
             |     |
             |     |       +-------------------
             |     |       |  the image
@@ -2665,6 +2864,7 @@ x_draw_image_glyph_string (s)
 
   height = s->height - 2 * box_line_vwidth;
 
+
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
@@ -2672,9 +2872,7 @@ x_draw_image_glyph_string (s)
   if (height > s->img->height
       || s->img->hmargin
       || s->img->vmargin
-#if 0 /* TODO: image mask */
       || s->img->mask
-#endif
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
@@ -2684,25 +2882,21 @@ x_draw_image_glyph_string (s)
        x = s->x;
 
       y = s->y + box_line_vwidth;
-#if 0 /* TODO: image mask */
+
       if (s->img->mask)
        {
          /* Create a pixmap as large as the glyph string.  Fill it
             with the background color.  Copy the image to it, using
             its mask.  Copy the temporary pixmap to the display.  */
-         Screen *screen = FRAME_X_SCREEN (s->f);
-         int depth = DefaultDepthOfScreen (screen);
+         int depth = one_mac_display_info.n_planes;
 
          /* Create a pixmap as large as the glyph string.  */
          pixmap = XCreatePixmap (s->display, s->window,
                                  s->background_width,
                                  s->height, depth);
 
-         /* Don't clip in the following because we're working on the
-            pixmap.  */
-         XSetClipMask (s->display, s->gc, None);
-
          /* Fill the pixmap with the background color/stipple.  */
+#if 0 /* TODO: stipple */
          if (s->stippled_p)
            {
              /* Fill background with a stipple pattern.  */
@@ -2712,18 +2906,19 @@ x_draw_image_glyph_string (s)
              XSetFillStyle (s->display, s->gc, FillSolid);
            }
          else
+#endif
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
                            &xgcv);
              XSetForeground (s->display, s->gc, xgcv.background);
-             XFillRectangle (s->display, pixmap, s->gc,
-                             0, 0, s->background_width, s->height);
+             mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
+                                           0, 0, s->background_width,
+                                           s->height);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
       else
-#endif
        x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
 
       s->background_filled_p = 1;
@@ -2735,7 +2930,7 @@ x_draw_image_glyph_string (s)
       x_draw_image_foreground_1 (s, pixmap);
       x_set_glyph_string_clipping (s);
       mac_copy_area (s->display, pixmap, s->window, s->gc,
-                  0, 0, s->background_width, s->height, s->x, s->y);
+                    0, 0, s->background_width, s->height, s->x, s->y);
       mac_reset_clipping (s->display, s->window);
       XFreePixmap (s->display, pixmap);
     }
@@ -2772,10 +2967,10 @@ x_draw_stretch_glyph_string (s)
       /* Clear rest using the GC of the original non-cursor face.  */
       if (width < s->background_width)
        {
-         GC gc = s->face->gc;
          int x = s->x + width, y = s->y;
          int w = s->background_width - width, h = s->height;
          Rect r;
+         GC gc;
 
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
@@ -2835,7 +3030,6 @@ x_draw_glyph_string (s)
       x_set_glyph_string_gc (s->next);
       x_set_glyph_string_clipping (s->next);
       x_draw_glyph_string_background (s->next, 1);
-
     }
 
   /* Set up S->gc, set clipping and draw S.  */
@@ -2872,7 +3066,7 @@ x_draw_glyph_string (s)
       if (s->for_overlaps_p)
        s->background_filled_p = 1;
       else
-        x_draw_glyph_string_background (s, 0);
+       x_draw_glyph_string_background (s, 0);
       x_draw_glyph_string_foreground (s);
       break;
 
@@ -2949,9 +3143,9 @@ x_draw_glyph_string (s)
            }
        }
 
-      /* Draw relief.  */
+      /* Draw relief if not yet drawn.  */
       if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
-        x_draw_glyph_string_box (s);
+       x_draw_glyph_string_box (s);
     }
 
   /* Reset clipping.  */
@@ -2971,7 +3165,6 @@ mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
                   x + shift_by, y);
 }
 
-
 /* Delete N glyphs at the nominal cursor position.  Not implemented
    for X frames.  */
 
@@ -3026,6 +3219,7 @@ x_clear_frame ()
 
 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
 
+
 /* Subtract the `struct timeval' values X and Y, storing the result in
    *RESULT.  Return 1 if the difference is negative, otherwise 0.  */
 
@@ -3129,7 +3323,7 @@ XTring_bell ()
    This, and those operations, are used only within an update
    that is bounded by calls to x_update_begin and x_update_end.  */
 
-void
+static void
 XTset_terminal_window (n)
      register int n;
 {
@@ -3165,7 +3359,7 @@ x_scroll_run (w, run)
 
   /* Get frame-relative bounding box of the text display area of W,
      without mode lines.  Include in this box the left and right
-     fringes of W.  */
+     fringe of W.  */
   window_box (w, -1, &x, &y, &width, &height);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
@@ -3287,8 +3481,6 @@ static void
 XTframe_rehighlight (frame)
      struct frame *frame;
 {
-
-
   x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
 }
 
@@ -4429,13 +4621,6 @@ x_draw_hollow_cursor (w, row)
   struct glyph *cursor_glyph;
   GC gc;
 
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
-  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
-       + row->ascent - w->phys_cursor_ascent);
-  h = row->height - 1;
-
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
   cursor_glyph = get_phys_cursor_glyph (w);
@@ -4450,6 +4635,20 @@ x_draw_hollow_cursor (w, row)
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
     wd = min (FRAME_COLUMN_WIDTH (f), wd);
+  w->phys_cursor_width = wd;
+
+  /* Compute frame-relative coordinates from window-relative
+     coordinates.  */
+  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+  y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
+
+  /* Compute the proper height and ascent of the rectangle, based
+     on the actual glyph.  Using the full height of the row looks
+     bad when there are tall images on that row.  */
+  h = max (FRAME_LINE_HEIGHT (f), cursor_glyph->ascent + cursor_glyph->descent);
+  if (h < row->height)
+    y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
+  h--;
 
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
@@ -4476,35 +4675,49 @@ x_draw_hollow_cursor (w, row)
    --gerd.  */
 
 static void
-x_draw_bar_cursor (w, row, width)
+x_draw_bar_cursor (w, row, width, kind)
      struct window *w;
      struct glyph_row *row;
      int width;
+     enum text_cursor_kinds kind;
 {
-  /* If cursor hpos is out of bounds, don't draw garbage.  This can
-     happen in mini-buffer windows when switching between echo area
-     glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
+  struct frame *f = XFRAME (w->frame);
+  struct glyph *cursor_glyph;
+
+  /* If cursor is out of bounds, don't draw garbage.  This can happen
+     in mini-buffer windows when switching between echo area glyphs
+     and mini-buffer.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph == NULL)
+    return;
+
+  /* If on an image, draw like a normal cursor.  That's usually better
+     visible than drawing a bar, esp. if the image is large so that
+     the bar might not be in the window.  */
+  if (cursor_glyph->type == IMAGE_GLYPH)
     {
-      struct frame *f = XFRAME (w->frame);
-      struct glyph *cursor_glyph;
-      GC gc;
-      int x;
-      unsigned long mask;
+      struct glyph_row *row;
+      row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
+      draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
+    }
+  else
+    {
+      Display *dpy = FRAME_MAC_DISPLAY (f);
+      Window window = FRAME_MAC_WINDOW (f);
+      GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
+      unsigned long mask = GCForeground | GCBackground;
+      struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
       XGCValues xgcv;
-      Display *dpy;
-      Window window;
 
-      cursor_glyph = get_phys_cursor_glyph (w);
-      if (cursor_glyph == NULL)
-       return;
-
-      xgcv.background = f->output_data.mac->cursor_pixel;
-      xgcv.foreground = f->output_data.mac->cursor_pixel;
-      mask = GCForeground | GCBackground;
-      dpy = FRAME_MAC_DISPLAY (f);
-      window = FRAME_MAC_WINDOW (f);
-      gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
+      /* If the glyph's background equals the color we normally draw
+        the bar cursor in, the bar cursor in its normal color is
+        invisible.  Use the glyph's foreground color instead in this
+        case, on the assumption that the glyph's colors are chosen so
+        that the glyph is legible.  */
+      if (face->background == f->output_data.mac->cursor_pixel)
+       xgcv.background = xgcv.foreground = face->foreground;
+      else
+       xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
 
       if (gc)
        XChangeGC (dpy, gc, mask, &xgcv);
@@ -4516,14 +4729,24 @@ x_draw_bar_cursor (w, row, width)
 
       if (width < 0)
        width = FRAME_CURSOR_WIDTH (f);
+      width = min (cursor_glyph->pixel_width, width);
 
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+      w->phys_cursor_width = width;
       x_clip_to_row (w, row, gc);
-      XFillRectangle (dpy, window, gc,
-                     x,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                     min (cursor_glyph->pixel_width, width),
-                     row->height);
+
+      if (kind == BAR_CURSOR)
+       XFillRectangle (dpy, window, gc,
+                       WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                       WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                       width, row->height);
+      else
+       XFillRectangle (dpy, window, gc,
+                       WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                       WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+                                                row->height - width),
+                       cursor_glyph->pixel_width,
+                       width);
+
       mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
     }
 }
@@ -4565,7 +4788,6 @@ mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act
   if (on_p)
     {
       w->phys_cursor_type = cursor_type;
-      w->phys_cursor_width = cursor_width;
       w->phys_cursor_on_p = 1;
 
       if (glyph_row->exact_window_width_line_p
@@ -4573,9 +4795,8 @@ mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act
        {
          glyph_row->cursor_in_fringe_p = 1;
          draw_fringe_bitmap (w, glyph_row, 0);
-         return;
        }
-
+      else
       switch (cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
@@ -4586,13 +4807,16 @@ mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act
          draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
          break;
 
-       case HBAR_CURSOR:
-         /* TODO.  For now, just draw bar cursor. */
        case BAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row, cursor_width);
+         x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+         break;
+
+       case HBAR_CURSOR:
+         x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
          break;
 
        case NO_CURSOR:
+         w->phys_cursor_width = 0;
          break;
 
        default:
@@ -5117,6 +5341,8 @@ x_make_frame_visible (f)
        FRAME_SAMPLE_VISIBILITY (f);
       }
   }
+#else
+  UNBLOCK_INPUT;
 #endif /* MAC_TODO */
 }
 
@@ -5173,10 +5399,10 @@ x_iconify_frame (f)
 }
 
 \f
-/* Destroy the X window of frame F.  */
+/* Free X resources of frame F.  */
 
 void
-x_destroy_window (f)
+x_free_frame_resources (f)
      struct frame *f;
 {
   struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
@@ -5186,10 +5412,15 @@ x_destroy_window (f)
   DisposeWindow (FRAME_MAC_WINDOW (f));
 
   free_frame_menubar (f);
-  free_frame_faces (f);
+
+  if (FRAME_FACE_CACHE (f))
+    free_frame_faces (f);
+
+  x_free_gcs (f);
 
   xfree (f->output_data.mac);
-  f->output_data.mac = 0;
+  f->output_data.mac = NULL;
+
   if (f == dpyinfo->x_focus_frame)
     dpyinfo->x_focus_frame = 0;
   if (f == dpyinfo->x_focus_event_frame)
@@ -5197,8 +5428,6 @@ x_destroy_window (f)
   if (f == dpyinfo->x_highlight_frame)
     dpyinfo->x_highlight_frame = 0;
 
-  dpyinfo->reference_count--;
-
   if (f == dpyinfo->mouse_face_mouse_frame)
     {
       dpyinfo->mouse_face_beg_row
@@ -5212,6 +5441,21 @@ x_destroy_window (f)
 
   UNBLOCK_INPUT;
 }
+
+
+/* Destroy the X window of frame F.  */
+
+void
+x_destroy_window (f)
+     struct frame *f;
+{
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  x_free_frame_resources (f);
+
+  dpyinfo->reference_count--;
+}
+
 \f
 /* Setting window manager hints.  */
 
@@ -5478,6 +5722,7 @@ char **font_name_table = NULL;
 int font_name_table_size = 0;
 int font_name_count = 0;
 
+#if 0
 /* compare two strings ignoring case */
 static int
 stricmp (const char *s, const char *t)
@@ -5557,13 +5802,53 @@ mac_font_match (char *mf, char *xf)
           && wildstrieq (m_charset, x_charset))
          || mac_font_pattern_match (mf, xf);
 }
+#endif
+
+static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
+
+static void
+decode_mac_font_name (char *name, int size, short scriptcode)
+{
+  Lisp_Object coding_system;
+  struct coding_system coding;
+  char *buf;
+
+  switch (scriptcode)
+    {
+    case smTradChinese:
+      coding_system = Qbig5;
+      break;
+    case smSimpChinese:
+      coding_system = Qcn_gb;
+      break;
+    case smJapanese:
+      coding_system = Qsjis;
+      break;
+    case smKorean:
+      coding_system = Qeuc_kr;
+      break;        
+    default:
+      return;
+    }
+
+  setup_coding_system (coding_system, &coding);
+  coding.src_multibyte = 0;
+  coding.dst_multibyte = 1;
+  coding.mode |= CODING_MODE_LAST_BLOCK;
+  coding.composing = COMPOSITION_DISABLED;
+  buf = (char *) alloca (size);
+
+  decode_coding (&coding, name, buf, strlen (name), size - 1);
+  bcopy (buf, name, coding.produced);
+  name[coding.produced] = '\0';
+}
 
 
 static char *
 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
 {
   char foundry[32], family[32], cs[32];
-  char xf[255], *result, *p;
+  char xf[256], *result, *p;
 
   if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
     {
@@ -5622,6 +5907,8 @@ static void
 x_font_name_to_mac_font_name (char *xf, char *mf)
 {
   char foundry[32], family[32], weight[20], slant[2], cs[32];
+  Lisp_Object coding_system = Qnil;
+  struct coding_system coding;
 
   strcpy (mf, "");
 
@@ -5631,13 +5918,29 @@ x_font_name_to_mac_font_name (char *xf, char *mf)
               foundry, family, weight, slant, cs) != 5)
     return;
 
-  if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
-      || strcmp (cs, "jisx0208.1983-sjis") == 0
-      || strcmp (cs, "jisx0201.1976-0") == 0
-      || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
-    strcpy(mf, family);
+  if (strcmp (cs, "big5-0") == 0)
+    coding_system = Qbig5;
+  else if (strcmp (cs, "gb2312.1980-0") == 0)
+    coding_system = Qcn_gb;
+  else if (strcmp (cs, "jisx0208.1983-sjis") == 0
+          || strcmp (cs, "jisx0201.1976-0") == 0)
+    coding_system = Qsjis;
+  else if (strcmp (cs, "ksc5601.1989-0") == 0)
+    coding_system = Qeuc_kr;
+  else if (strcmp (cs, "mac-roman") == 0)
+    strcpy (mf, family);
   else
-    sprintf(mf, "%s-%s-%s", foundry, family, cs);
+    sprintf (mf, "%s-%s-%s", foundry, family, cs);
+
+  if (!NILP (coding_system))
+    {
+      setup_coding_system (coding_system, &coding);
+      coding.src_multibyte = 1;
+      coding.dst_multibyte = 1;
+      coding.mode |= CODING_MODE_LAST_BLOCK;
+      encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
+      mf[coding.produced] = '\0';
+    }
 }
 
 
@@ -5701,36 +6004,45 @@ init_font_name_table ()
          if (FMGetFontFamilyName (ff, name) != noErr)
            break;
          p2cstr (name);
+         if (*name == '.')
+           continue;
 
          sc = FontToScript (ff);
+         decode_mac_font_name (name, sizeof (name), sc);
 
          /* Point the instance iterator at the current font family.  */
-         if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
+         if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
            break;
 
          while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
                 == noErr)
-           if (size == 0)
-             {
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             style, sc));
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             italic, sc));
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             bold, sc));
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             italic | bold,
-                                                             sc));
-             }
-           else
-             {
+           {
+             /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
+                contained in Apple Japanese (SJIS) font.  */
+           again:
+             if (size == 0)
+               {
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               style, sc));
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               italic, sc));
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               bold, sc));
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               italic | bold,
+                                                               sc));
+               }
+             else
                add_font_name_table_entry (mac_to_x_fontname (name, size,
                                                              style, sc));
-               if (smJapanese == sc)
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               style,
-                                                               -smJapanese));
-             }
+             if (sc == smJapanese)
+               {
+                 sc = -smJapanese;
+                 goto again;
+               }
+             else if (sc == -smJapanese)
+               sc = smJapanese;
+           }
        }
 
       /* Dispose of the iterators.  */
@@ -5772,6 +6084,7 @@ init_font_name_table ()
 
          TextFont (fontnum);
          scriptcode = FontToScript (fontnum);
+         decode_mac_font_name (name, sizeof (name), scriptcode);
          do
            {
              HLock (font_handle);
@@ -5806,9 +6119,9 @@ init_font_name_table ()
                                             assc_entry->fontSize,
                                             assc_entry->fontStyle,
                                             scriptcode);
-                     /* Both jisx0208.1983-sjis and
-                        jisx0201.1976-sjis parts are contained in
-                        Apple Japanese (SJIS) font.  */
+                     /* Both jisx0208.1983-sjis and jisx0201.1976-0
+                        parts are contained in Apple Japanese (SJIS)
+                        font.  */
                      if (smJapanese == scriptcode)
                        {
                          font_name_table[font_name_count++]
@@ -5835,6 +6148,145 @@ init_font_name_table ()
 }
 
 
+enum xlfd_scalable_field_index
+  {
+    XLFD_SCL_PIXEL_SIZE,
+    XLFD_SCL_POINT_SIZE,
+    XLFD_SCL_AVGWIDTH,
+    XLFD_SCL_LAST
+  };
+
+static int xlfd_scalable_fields[] =
+  {
+    6,                         /* PIXEL_SIZE */
+    7,                         /* POINT_SIZE */
+    11,                                /* AVGWIDTH */
+    -1
+  };
+
+static Lisp_Object
+mac_do_list_fonts (pattern, maxnames)
+     char *pattern;
+     int maxnames;
+{
+  int i, n_fonts = 0;
+  Lisp_Object font_list = Qnil, pattern_regex, fontname;
+  char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
+  char scaled[256];
+  char *ptr;
+  int scl_val[XLFD_SCL_LAST], *field, *val;
+
+  for (i = 0; i < XLFD_SCL_LAST; i++)
+    scl_val[i] = -1;
+
+  /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
+     POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
+     fonts are scaled according to the specified size.  */
+  ptr = pattern;
+  i = 0;
+  field = xlfd_scalable_fields;
+  val = scl_val;
+  if (*ptr == '-')
+    do
+      {
+       ptr++;
+       if (i == *field)
+         {
+           if ('1' <= *ptr && *ptr <= '9')
+             {
+               *val = *ptr++ - '0';
+               while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
+                 *val = *val * 10 + *ptr++ - '0';
+               if (*ptr != '-')
+                 *val = -1;
+             }
+           field++;
+           val++;
+         }
+       ptr = strchr (ptr, '-');
+       i++;
+      }
+    while (ptr && i < 14);
+
+  if (i == 14 && ptr == NULL)
+    {
+      if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
+       {
+         scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
+         scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
+       }
+      else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
+       {
+         scl_val[XLFD_SCL_POINT_SIZE] =
+           scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
+       }
+      else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
+       {
+         scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
+         scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
+       }
+    }
+  else
+    scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
+
+  ptr = regex;
+  *ptr++ = '^';
+
+  /* Turn pattern into a regexp and do a regexp match.  */
+  for (; *pattern; pattern++)
+    {
+      if (*pattern == '?')
+        *ptr++ = '.';
+      else if (*pattern == '*')
+        {
+          *ptr++ = '.';
+          *ptr++ = '*';
+        }
+      else
+        *ptr++ = tolower (*pattern);
+    }
+  *ptr = '$';
+  *(ptr + 1) = '\0';
+
+  pattern_regex = build_string (regex);
+
+  for (i = 0; i < font_name_count; i++)
+    {
+      fontname = build_string (font_name_table[i]);
+      if (fast_string_match (pattern_regex, fontname) >= 0)
+       {
+         font_list = Fcons (fontname, font_list);
+
+          n_fonts++;
+          if (maxnames > 0 && n_fonts >= maxnames)
+            break;
+       }
+      else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
+              && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
+       {
+         int former_len = ptr - font_name_table[i];
+
+         memcpy (scaled, font_name_table[i], former_len);
+         sprintf (scaled + former_len,
+                  "-%d-%d-75-75-m-%d-%s",
+                  scl_val[XLFD_SCL_PIXEL_SIZE],
+                  scl_val[XLFD_SCL_POINT_SIZE],
+                  scl_val[XLFD_SCL_AVGWIDTH],
+                  ptr + sizeof ("-0-0-75-75-m-0-") - 1);
+         fontname = build_string (scaled);
+         if (fast_string_match (pattern_regex, fontname) >= 0)
+           {
+             font_list = Fcons (fontname, font_list);
+             
+             n_fonts++;
+             if (maxnames > 0 && n_fonts >= maxnames)
+               break;
+           }
+       }
+    }
+  return font_list;
+}
+
 /* Return a list of at most MAXNAMES font specs matching the one in
    PATTERN.  Cache matching fonts for patterns in
    dpyinfo->name_list_element to avoid looking them up again by
@@ -5847,11 +6299,7 @@ x_list_fonts (struct frame *f,
               int size,
               int maxnames)
 {
-  char *ptnstr;
   Lisp_Object newlist = Qnil, tem, key;
-  int n_fonts = 0;
-  int i;
-  struct gcpro gcpro1, gcpro2;
   struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
 
   if (font_name_table == NULL)  /* Initialize when first used.  */
@@ -5870,27 +6318,10 @@ x_list_fonts (struct frame *f,
        }
     }
 
-  ptnstr = SDATA (pattern);
-
-  GCPRO2 (pattern, newlist);
-
-  /* Scan and matching bitmap fonts.  */
-  for (i = 0; i < font_name_count; i++)
-    {
-      if (mac_font_pattern_match (font_name_table[i], ptnstr))
-        {
-          newlist = Fcons (build_string (font_name_table[i]), newlist);
-
-          n_fonts++;
-          if (maxnames > 0 && n_fonts >= maxnames)
-            break;
-        }
-    }
+  newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
 
   /* MAC_TODO: add code for matching outline fonts here */
 
-  UNGCPRO;
-
   if (dpyinfo)
     {
       XSETCDR (dpyinfo->name_list_element,
@@ -6050,14 +6481,12 @@ XLoadQueryFont (Display *dpy, char *fontname)
     name = fontname;
   else
     {
-      for (i = 0; i < font_name_count; i++)
-        if (mac_font_pattern_match (font_name_table[i], fontname))
-          break;
+      Lisp_Object matched_fonts;
 
-      if (i >= font_name_count)
-        return NULL;
-
-      name = font_name_table[i];
+      matched_fonts = mac_do_list_fonts (fontname, 1);
+      if (NILP (matched_fonts))
+       return NULL;
+      name = SDATA (XCAR (matched_fonts));
     }
 
   GetPort (&port);  /* save the current font number used */
@@ -6179,7 +6608,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
         for (c = 0x20; c <= 0xff; c++)
           {
             font->per_char[c - 0x20] = font->max_bounds;
-            font->per_char[c - 0x20].width = CharWidth (c);
+            font->per_char[c - 0x20].width =
+             font->per_char[c - 0x20].rbearing = CharWidth (c);
           }
       }
     }
@@ -7833,14 +8263,32 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
                    }
                  else
                    {
-                     bufp->kind = MOUSE_CLICK_EVENT;
+                     Lisp_Object window;
+                     
+                     bufp->kind = MOUSE_CLICK_EVENT;
                      XSETFRAME (bufp->frame_or_window, mwp->mFP);
                      if (er.what == mouseDown)
-                       mouse_tracking_in_progress
+                       mouse_tracking_in_progress
                          = mouse_tracking_mouse_movement;
                      else
-                       mouse_tracking_in_progress = mouse_tracking_none;
-                   }
+                       mouse_tracking_in_progress = mouse_tracking_none;
+                     window = window_from_coordinates (mwp->mFP, bufp->x, bufp->y, 0, 0, 0, 1);
+                     
+                     if (EQ (window, mwp->mFP->tool_bar_window))
+                       {
+                         if (er.what == mouseDown)
+                           handle_tool_bar_click (mwp->mFP, bufp->x, bufp->y, 1, 0);
+                         else
+                           handle_tool_bar_click (mwp->mFP, bufp->x, bufp->y, 0,
+#if USE_CARBON_EVENTS
+                                                  mac_event_to_emacs_modifiers (eventRef)
+#else
+                                                  er.modifiers
+#endif
+                                                  );
+                         break;
+                       }
+                   }
 
 #if USE_CARBON_EVENTS
                  bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
@@ -8352,12 +8800,16 @@ mac_initialize_display_info ()
   dpyinfo->reference_count = 0;
   dpyinfo->resx = 75.0;
   dpyinfo->resy = 75.0;
-  dpyinfo->n_planes = 1;
-  dpyinfo->n_cbits = 16;
+  dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
+  for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
+    if (HasDepth (main_device_handle, dpyinfo->n_planes,
+                 gdDevType, dpyinfo->color_p))
+      break;
   dpyinfo->height = (**main_device_handle).gdRect.bottom;
   dpyinfo->width = (**main_device_handle).gdRect.right;
   dpyinfo->grabbed = 0;
   dpyinfo->root_window = NULL;
+  dpyinfo->image_cache = make_image_cache ();
 
   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
@@ -8696,6 +9148,18 @@ syms_of_macterm ()
   Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
   staticpro (&Qmac_ready_for_drag_n_drop);
 
+  Qbig5 = intern ("big5");
+  staticpro (&Qbig5);
+
+  Qcn_gb = intern ("cn-gb");
+  staticpro (&Qcn_gb);
+
+  Qsjis = intern ("sjis");
+  staticpro (&Qsjis);
+
+  Qeuc_kr = intern ("euc-kr");
+  staticpro (&Qeuc_kr);
+
   DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
     doc: /* *Non-nil means autoselect window with mouse pointer.  */);
   x_autoselect_window_p = 0;
index b3fe53c86eae8fa5fbb7bdfc80538a8481788bed..17b8a0fb298777c8d55e61d57264c4520c24d2ee 100644 (file)
@@ -23,45 +23,26 @@ Boston, MA 02111-1307, USA.  */
 #include "macgui.h"
 #include "frame.h"
 
-/* Include Carbon.h to define Cursor and Rect.  */
-#ifdef HAVE_CARBON
-#undef mktime
-#undef DEBUG
-#undef Z
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef Z
-#define Z (current_buffer->text->z)
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
-#endif /* MAC_OSX */
-
 #define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
 
 #define RED_FROM_ULONG(color) ((color) >> 16)
 #define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
 #define BLUE_FROM_ULONG(color) ((color) & 0xff)
 
+/* Do not change `* 0x101' in the following lines to `<< 8'.  If
+   changed, image masks in 1-bit depth will not work. */
+#define RED16_FROM_ULONG(color) (RED_FROM_ULONG(color) * 0x101)
+#define GREEN16_FROM_ULONG(color) (GREEN_FROM_ULONG(color) * 0x101)
+#define BLUE16_FROM_ULONG(color) (BLUE_FROM_ULONG(color) * 0x101)
+
 #define BLACK_PIX_DEFAULT(f) RGB_TO_ULONG(0,0,0)
 #define WHITE_PIX_DEFAULT(f) RGB_TO_ULONG(255,255,255)
 
+/* A black pixel in a mask bitmap/pixmap means ``draw a source
+   pixel''.  A white pixel means ``retain the current pixel''. */
+#define PIX_MASK_DRAW(f) BLACK_PIX_DEFAULT(f)
+#define PIX_MASK_RETAIN(f) WHITE_PIX_DEFAULT(f)
+
 #define FONT_WIDTH(f)   ((f)->max_bounds.width)
 #define FONT_HEIGHT(f)  ((f)->ascent + (f)->descent)
 #define FONT_BASE(f)    ((f)->ascent)
@@ -101,8 +82,13 @@ struct mac_display_info
   /* Number of planes on this screen.  */
   int n_planes;
 
+  /* Whether the screen supports color */ 
+  int color_p;
+
+#if 0
   /* Number of bits per pixel on this screen.  */
   int n_cbits;
+#endif
 
   /* Dimensions of this screen.  */
   int height, width;
index abc56901e175614cfaffe07f1c7871d3373f7993..814de2c2c5189f31f4e3fb4d89c48a41ff9760c5 100644 (file)
@@ -247,7 +247,7 @@ Boston, MA 02111-1307, USA.  */
    page) to leave room at the end of the header for adding load
    commands.  Needed for dumping.  0x690 is the total size of 30
    segment load commands (at 56 each).  */
-#define LD_SWITCH_SYSTEM_TEMACS -prebind -framework Carbon -lstdc++ -Xlinker -headerpad -Xlinker 690
+#define LD_SWITCH_SYSTEM_TEMACS -prebind -framework Carbon -framework QuickTime -lstdc++ -Xlinker -headerpad -Xlinker 690
 
 #define C_SWITCH_SYSTEM_TEMACS -Dtemacs