changeset 54150:6c8849d06ab3

Inserting Yamomotosan's changes for MacOSX image support, better support of Asian fonts, and some long awaited header cleanup and centralization.
author Steven Tamm <steventamm@mac.com>
date Thu, 26 Feb 2004 17:46:48 +0000
parents 6065441e9610
children 9a5c3b661a40 887bb2eb4a89
files 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
diffstat 9 files changed, 3218 insertions(+), 1270 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/ChangeLog	Thu Feb 26 17:46:48 2004 +0000
@@ -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
--- a/src/dispextern.h	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/dispextern.h	Thu Feb 26 17:46:48 2004 +0000
@@ -61,38 +61,8 @@
 #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
--- a/src/emacs.c	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/emacs.c	Thu Feb 26 17:46:48 2004 +0000
@@ -1589,7 +1589,7 @@
   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 ();
--- a/src/macfns.c	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/macfns.c	Thu Feb 26 17:46:48 2004 +0000
@@ -54,6 +54,8 @@
 /*#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 @@
 #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 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 @@
       xfree (dpyinfo->bitmaps[i].bitmap_data);
   dpyinfo->bitmaps_last = 0;
 }
+
+
 
-/* Connect the frame-parameter names for W32 frames
-   to the ways of passing the parameter values to the window system.
-
-   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.  */
+/* 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));
+}
+
+
+
+/* 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));
+
+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 @@
 							     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 @@
   { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
 };
 
-unsigned long
+Lisp_Object
 mac_color_map_lookup (colorname)
      char *colorname;
 {
@@ -1394,7 +1460,7 @@
   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 @@
 	      if (i == 2)
 		{
 		  UNBLOCK_INPUT;
-		  return (colorval);
+		  return make_number (colorval);
 		}
 	      color = end;
 	    }
@@ -1516,7 +1582,7 @@
 	      if (*end != '\0')
 		break;
 	      UNBLOCK_INPUT;
-	      return (colorval);
+	      return make_number (colorval);
 	    }
 	  if (*end != '/')
 	    break;
@@ -1557,7 +1623,7 @@
 	      if (*end != '\0')
 		break;
 	      UNBLOCK_INPUT;
-	      return (colorval);
+	      return make_number (colorval);
 	    }
 	  if (*end != '/')
 	    break;
@@ -1616,9 +1682,9 @@
         }
 
       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 @@
     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 @@
      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 @@
      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))
-    {
-      f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel;
-      if (f->output_data.mac->cursor_pixel == fore_pixel)
+  if (pixel == FRAME_BACKGROUND_PIXEL (f))
+    {
+      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 @@
 /* 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 @@
   update_face_from_frame_parameter (f, Qborder_color, arg);
 }
 
+
 void
 x_set_cursor_type (f, arg, oldval)
      FRAME_PTR f;
@@ -1933,9 +2010,8 @@
 {
   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;
 }
 
 #if 0 /* MAC_TODO: really no icon for Mac */
@@ -2597,7 +2673,7 @@
 
   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 @@
   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 @@
   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 @@
     /* 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 @@
     {
       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 @@
 {
   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 @@
 {
   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 @@
 {
   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 @@
   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 @@
   return Qnil;
 }
 
+
 
 /***********************************************************************
 			    Image types
@@ -3470,11 +3636,11 @@
 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 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 @@
 
   if (IMAGEP (object))
     {
-      Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
-      struct image_type *type = lookup_image_type (symbol);
-
-      if (type)
-	valid_p = type->valid_p (object);
+      Lisp_Object tem;
+
+      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 @@
 /* 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 @@
 {
   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 @@
 	  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 @@
 	    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 @@
 	    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 @@
 }
 
 
+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;
+}
+
 
 
 /***********************************************************************
@@ -3876,8 +4117,12 @@
   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,18 +4132,155 @@
   return ascent;
 }
 
+
+/* 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;
+}
 
 
 /***********************************************************************
 		  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));
 
+
+/* 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_1 (f, img, pixmap_p, mask_p, colors_p)
+     struct frame *f;
+     struct image *img;
+     int pixmap_p, mask_p, colors_p;
+{
+  if (pixmap_p && img->pixmap)
+    {
+      XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
+      img->pixmap = NULL;
+      img->background_valid = 0;
+    }
+
+  if (mask_p && img->mask)
+    {
+      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;
+    }
+}
+
 /* Free X resources of image IMG which is used on frame F.  */
 
 static void
@@ -3906,39 +4288,9 @@
      struct frame *f;
      struct image *img;
 {
-#if 0 /* MAC_TODO: W32 image support  */
-
-  if (img->pixmap)
-    {
-      BLOCK_INPUT;
-      XFreePixmap (NULL, img->pixmap);
-      img->pixmap = 0;
-      UNBLOCK_INPUT;
-    }
-
-  if (img->ncolors)
-    {
-      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;
-	}
-
-      xfree (img->colors);
-      img->colors = NULL;
-      img->ncolors = 0;
-    }
-#endif /* MAC_TODO */
+  BLOCK_INPUT;
+  x_clear_image_1 (f, img, 1, 1, 1);
+  UNBLOCK_INPUT;
 }
 
 
@@ -3954,13 +4306,12 @@
      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 @@
     }
   else
     result = dflt;
+
   return result;
-#endif /* MAC_TODO */
-  return 0;
 }
 
 
@@ -3985,6 +4335,7 @@
  ***********************************************************************/
 
 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 @@
     {
       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 @@
 	 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 @@
        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,6 +4467,81 @@
 }
 
 
+/* Compute masks and transform image IMG on frame F, as specified
+   by the image's specification,  */
+
+static void
+postprocess_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  /* Manipulation of the image's mask.  */
+  if (img->pixmap)
+    {
+      Lisp_Object conversion, spec;
+      Lisp_Object mask;
+
+      spec = img->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).  */
 
@@ -4135,11 +4575,12 @@
   /* 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 @@
       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 @@
 	      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 @@
 			    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));
-
-
-/* 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
+					    XImagePtr *, Pixmap *));
+static void x_destroy_x_image P_ ((XImagePtr));
+static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, 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 @@
       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);
-    }
-}
-
-
-/* Put XImage XIMG into pixmap PIXMAP on frame F.  WIDTH and HEIGHT
-   are width and height of both the image and pixmap.  */
+    XDestroyImage (ximg);
+}
 
 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);
-}
-
-#endif /* MAC_TODO */
+  xassert (ximg == pixmap);
+}
+
 
 
 /***********************************************************************
-			      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 @@
   /* 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 @@
   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;
+}
+
+
+
+/***********************************************************************
+			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
+
+
 
 /***********************************************************************
 			      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 @@
   XBM_RELIEF,
   XBM_ALGORITHM,
   XBM_HEURISTIC_MASK,
+  XBM_MASK,
   XBM_LAST
 };
 
@@ -4434,13 +5239,14 @@
   {":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 @@
    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 @@
       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 @@
 	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 @@
    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 @@
 	  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 @@
   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 @@
      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 @@
 
   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 @@
 
   if (v10)
     {
-
       for (i = 0; i < nbytes; i += 2)
 	{
 	  int val = value;
@@ -4788,13 +5613,12 @@
 	}
     }
 
-  fclose (fp);
+ success:
   return 1;
 
  failure:
 
-  fclose (fp);
-  if (*data)
+  if (data && *data)
     {
       xfree (*data);
       *data = NULL;
@@ -4807,38 +5631,24 @@
 }
 
 
-/* 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 @@
       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);
-
-#if 0 /* MAC_TODO : Port image display to Mac */
-      BLOCK_INPUT;
+	{
+	  background = x_alloc_image_color (f, img, value, background);
+	  img->background = background;
+	  img->background_valid = 1;
+	}
+
       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 @@
       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 @@
   /* 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 @@
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       char *bits;
       int parsed_p;
-
-      /* Parse the list specification.  */
+      int in_memory_file_p = 0;
+
+      /* 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;
-
-	  p = bits = (char *) alloca (nbytes * img->height);
-	  for (i = 0; i < img->height; ++i, p += nbytes)
+	  if (VECTORP (data))
 	    {
-	      Lisp_Object line = XVECTOR (data)->contents[i];
-	      if (STRINGP (line))
-		bcopy (SDATA (line), p, nbytes);
-	      else
-		bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+	      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)
+		{
+		  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
+	    {
+	      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 @@
   XPM_RELIEF,
   XPM_ALGORITHM,
   XPM_HEURISTIC_MASK,
+  XPM_MASK,
   XPM_COLOR_SYMBOLS,
+  XPM_BACKGROUND,
   XPM_LAST
 };
 
@@ -5026,12 +5880,14 @@
   {":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 @@
 	  /* 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 @@
      struct frame *f;
      struct image *img;
 {
-  int rc, i;
+  int rc;
   XpmAttributes attrs;
   Lisp_Object specified_file, color_symbols;
 
@@ -5111,10 +5965,10 @@
 #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 @@
 
   /* 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 @@
       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 @@
       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 @@
 
 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
@@ -5422,6 +6264,17 @@
   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 */
 
 
@@ -5429,151 +6282,333 @@
 			      Algorithms
  ***********************************************************************/
 
-#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));
-
-
-/* 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.  */
+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_laplace_read_row (f, cmap, colors, width, ximg, y)
+x_from_xcolors (f, img, colors)
      struct frame *f;
-     Colormap cmap;
+     struct image *img;
      XColor *colors;
-     int width;
-     XImage *ximg;
-     int y;
-{
-  int x;
-
-  for (x = 0; x < width; ++x)
-    colors[x].pixel = XGetPixel (ximg, x, y);
-
-  XQueryColors (NULL, cmap, colors, width);
-}
-
-
-/* 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.  */
+{
+  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_laplace_write_row (f, pixels, width, ximg, y)
+x_detect_edges (f, img, matrix, color_adjust)
      struct frame *f;
-     long *pixels;
-     int width;
-     XImage *ximg;
-     int y;
-{
-  int x;
-
-  for (x = 0; x < width; ++x)
-    XPutPixel (ximg, x, y, pixels[x]);
-}
-#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.  */
+     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;
+		}
+
+	  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);
+	}
+    }
+
+  xfree (colors);
+  x_from_xcolors (f, img, new);
+
+#undef COLOR
+}
+
+
+/* Perform the pre-defined `emboss' edge-detection on image IMG
+   on frame F.  */
+
+static void
+x_emboss (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
+}
+
+
+/* Perform the pre-defined `laplace' edge-detection on image IMG
+   on frame F.  */
 
 static void
 x_laplace (f, img)
      struct frame *f;
      struct image *img;
 {
-#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;
-
-  BLOCK_INPUT;
-
-  /* Get the X image IMG->pixmap.  */
-  ximg = XGetImage (NULL, img->pixmap,
-		    0, 0, img->width, img->height, ~0, ZPixmap);
-
-  /* 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));
-
-  /* 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;
-
-  /* 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;
-
-  for (y = 2; y < img->height; ++y)
-    {
-      int rowa = y % 3;
-      int rowb = (y + 2) % 3;
-
-      x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
-
-      for (x = 0; x < img->width - 2; ++x)
+  x_detect_edges (f, img, laplace_matrix, 45000);
+}
+
+
+/* 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_edge_detection (f, img, matrix, color_adjust)
+     struct frame *f;
+     struct image *img;
+     Lisp_Object matrix, color_adjust;
+{
+  int i = 0;
+  int trans[9];
+
+  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));
+    }
+
+  if (NILP (color_adjust))
+    color_adjust = make_number (0xffff / 2);
+
+  if (i == 9 && NUMBERP (color_adjust))
+    x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
+}
+
+
+/* Transform image IMG on frame F so that it looks disabled.  */
+
+static void
+x_disable_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  if (dpyinfo->n_planes >= 2)
+    {
+      /* 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;
+
+      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++);
-    }
-
-  /* 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);
-
-  /* Remember new pixmap and colors in IMG.  */
-  img->pixmap = pixmap;
-  img->colors = colors_in_color_table (&img->ncolors);
-  free_color_table ();
-
-  UNBLOCK_INPUT;
-#endif /* MAC_TODO */
-}
-
-
-/* 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)',
+      x_from_xcolors (f, img, colors);
+    }
+
+  /* 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;
+
+      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);
+
+      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)',
    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 @@
      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;
-
-  BLOCK_INPUT;
+  Display *dpy = FRAME_X_DISPLAY (f);
+  XImagePtr ximg, mask_img;
+  int x, y, rc, use_img_background;
+  unsigned long bg = 0;
+
+  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;
-
-      while (i < 3
-	     && CONSP (how)
-	     && NATNUMP (XCAR (how)))
+      int rgb[3], i;
+
+      for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
 	{
 	  rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
 	  how = XCDR (how);
@@ -5622,59 +6655,29 @@
       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 @@
 /***********************************************************************
 		       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 @@
   PBM_RELIEF,
   PBM_ALGORITHM,
   PBM_HEURISTIC_MASK,
+  PBM_MASK,
+  PBM_FOREGROUND,
+  PBM_BACKGROUND,
   PBM_LAST
 };
 
@@ -5716,11 +6721,14 @@
   {":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 @@
 
   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 @@
 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 @@
 }
 
 
-/* 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 @@
 {
   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 @@
     {
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
-
-      contents = pbm_read_file (file, &size);
+	{
+	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  UNGCPRO;
+	  return 0;
+	}
+
+      contents = slurp_file (SDATA (file), &size);
       if (contents == NULL)
 	{
 	  image_error ("Error reading `%s'", file, Qnil);
@@ -5937,20 +6907,37 @@
       || (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 @@
 	    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 @@
 
 	    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 @@
 	  }
     }
 
+#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 */
+
 
 
 /***********************************************************************
 				 PNG
  ***********************************************************************/
 
-#if HAVE_PNG
-
-#include <png.h>
 
 /* Function prototypes.  */
 
@@ -6061,6 +7045,8 @@
   PNG_RELIEF,
   PNG_ALGORITHM,
   PNG_HEURISTIC_MASK,
+  PNG_MASK,
+  PNG_BACKGROUND,
   PNG_LAST
 };
 
@@ -6072,11 +7058,13 @@
   {":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 @@
   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 @@
 }
 
 
+#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 @@
   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 @@
     {
       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 @@
       || 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;
-
-      if (png_get_bKGD (png_ptr, info_ptr, &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;
+
+	      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;
-
-	  BLOCK_INPUT;
-	  cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
-	  color.pixel = FRAME_BACKGROUND_PIXEL (f);
-	  XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
-	  UNBLOCK_INPUT;
-
+	  color = FRAME_BACKGROUND_PIXEL (f);
+#if 0 /* TODO : Colormap support.  */
+	  Colormap cmap;
+
+	  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 @@
       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 @@
 				       &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 @@
 	  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 @@
   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 @@
   /* 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 */
 
 
 
@@ -6511,23 +7552,6 @@
 				 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 @@
   JPEG_RELIEF,
   JPEG_ALGORITHM,
   JPEG_HEURISTIC_MASK,
+  JPEG_MASK,
+  JPEG_BACKGROUND,
   JPEG_LAST
 };
 
@@ -6558,11 +7584,13 @@
   {":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'.  */
@@ -6587,9 +7615,7 @@
 
   bcopy (jpeg_format, fmt, sizeof fmt);
 
-  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
-      || (fmt[JPEG_ASCENT].count
-	  && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -6597,12 +7623,42 @@
 }
 
 
+#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
+
+/* 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
+
 struct my_jpeg_error_mgr
 {
   struct jpeg_error_mgr pub;
   jmp_buf setjmp_buffer;
 };
 
+
 static void
 my_error_exit (cinfo)
      j_common_ptr cinfo;
@@ -6611,6 +7667,7 @@
   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 @@
   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 @@
     {
       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. */
+     error is detected.  This function will perform a longjmp.  */
+  cinfo.err = jpeg_std_error (&mgr.pub);
   mgr.pub.error_exit = my_error_exit;
-  cinfo.err = jpeg_std_error (&mgr.pub);
 
   if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
     {
@@ -6771,28 +7828,25 @@
 
       /* 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_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 @@
     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 @@
 	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_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 @@
 				 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 @@
   TIFF_RELIEF,
   TIFF_ALGORITHM,
   TIFF_HEURISTIC_MASK,
+  TIFF_MASK,
+  TIFF_BACKGROUND,
   TIFF_LAST
 };
 
@@ -6921,11 +7974,13 @@
   {":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 @@
   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 @@
 }
 tiff_memory_source;
 
+
 static size_t
 tiff_read_from_memory (data, buf, size)
      thandle_t data;
@@ -6991,6 +8058,7 @@
   return size;
 }
 
+
 static size_t
 tiff_write_from_memory (data, buf, size)
      thandle_t data;
@@ -7000,6 +8068,7 @@
   return (size_t) -1;
 }
 
+
 static toff_t
 tiff_seek_in_memory (data, off, whence)
      thandle_t data;
@@ -7023,7 +8092,7 @@
       idx = src->index + off;
       break;
 
-    default:			/* Invalid `whence'.  */
+    default:			/* Invalid `whence'.   */
       return -1;
     }
 
@@ -7034,6 +8103,7 @@
   return src->index;
 }
 
+
 static int
 tiff_close_memory (data)
      thandle_t data;
@@ -7042,6 +8112,7 @@
   return 0;
 }
 
+
 static int
 tiff_mmap_memory (data, pbase, psize)
      thandle_t data;
@@ -7052,6 +8123,7 @@
   return 0;
 }
 
+
 static void
 tiff_unmap_memory (data, base, size)
      thandle_t data;
@@ -7061,6 +8133,7 @@
   /* We don't need to do this. */
 }
 
+
 static toff_t
 tiff_size_of_memory (data)
      thandle_t data;
@@ -7068,6 +8141,35 @@
   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 @@
   int width, height, x, y;
   uint32 *buf;
   int rc;
-  XImage *ximg;
+  XImagePtr ximg;
   struct gcpro gcpro1;
   tiff_memory_source memsrc;
 
@@ -7091,25 +8193,28 @@
   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 @@
       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 @@
 	}
     }
 
+#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 */
 
 
 
@@ -7205,10 +8314,6 @@
 				 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 @@
   GIF_RELIEF,
   GIF_ALGORITHM,
   GIF_HEURISTIC_MASK,
+  GIF_MASK,
   GIF_IMAGE,
+  GIF_BACKGROUND,
   GIF_LAST
 };
 
@@ -7240,12 +8347,14 @@
   {":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 @@
   NULL
 };
 
+
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
@@ -7268,15 +8378,200 @@
   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 @@
 }
 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 @@
   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 @@
     {
       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 @@
       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 @@
   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_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 @@
       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 @@
     {
       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 @@
       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 */
 
 
 
@@ -7513,11 +8812,6 @@
 				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 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 @@
   GS_RELIEF,
   GS_ALGORITHM,
   GS_HEURISTIC_MASK,
+  GS_MASK,
+  GS_BACKGROUND,
   GS_LAST
 };
 
@@ -7555,11 +8856,13 @@
   {":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 @@
 
   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 @@
      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 @@
   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 @@
     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 @@
 	     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 @@
 
       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 @@
 
   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 @@
   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 @@
 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 @@
   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 @@
   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);
+  tip_timer = Qnil;
   staticpro (&tip_timer);
-  tip_timer = Qnil;
+  tip_frame = Qnil;
+  staticpro (&tip_frame);
 
 #if 0 /* MAC_TODO */
   defsubr (&Sx_file_dialog);
@@ -9009,30 +10328,26 @@
   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);
+  define_image_type (&gif_type);
+  define_image_type (&png_type);
+
+  /* Animated gifs use QuickTime Movie Toolbox.  So initialize it
+     here. */
+  EnterMovies ();
+#ifdef MAC_OSX
+  init_image_func_pointer ();
 #endif
-
-#if HAVE_GIF
-  define_image_type (&gif_type);
-#endif
-
-#if HAVE_PNG
-  define_image_type (&png_type);
-#endif
-#endif /* NTEMACS_TODO */
 }
 
 /* arch-tag: d7591289-f374-4377-b245-12f5dbbb8edc
--- a/src/macgui.h	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/macgui.h	Thu Feb 26 17:46:48 2004 +0000
@@ -23,9 +23,6 @@
 #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 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)
 
 
--- a/src/macmenu.c	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/macmenu.c	Thu Feb 26 17:46:48 2004 +0000
@@ -35,34 +35,7 @@
 #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>
--- a/src/macterm.c	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/macterm.c	Thu Feb 26 17:46:48 2004 +0000
@@ -35,29 +35,6 @@
 #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 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 @@
 
 /* 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 @@
 {
   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 @@
 {
   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 @@
   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 @@
   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 @@
 #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 @@
 }
 
 
+/* 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 @@
      char *bits;
      int w, h;
 {
-  int bytes_per_row, i, j;
-
-  bitmap->rowBytes = (w + 15) / 16 * 2;  /* must be on word boundary */
+  int i, j, w1;
+  char *p;
+
+  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 @@
   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 @@
 }
 
 
+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 @@
      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 @@
   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
+  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));
+}
+
+
+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
-  {
-    PixMapHandle pmh;
-
-    LockPortBits (GetWindowPort (dest));
-    pmh = GetPortPixMap (GetWindowPort (dest));
-    CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
-    UnlockPortBits (GetWindowPort (dest));
-  }
+  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 @@
 {
 #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 @@
   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 @@
 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);
-
-  SetRect (&src_r, src_x, src_y, src_right, src_bottom);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
-
-  CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
+
+  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_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+  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 @@
 
 /* Mac replacement for XSetForeground.  */
 
-static void
+void
 XSetForeground (display, gc, color)
      Display *display;
      GC gc;
@@ -2139,6 +2307,21 @@
 
 #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 @@
      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 @@
   /* 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 @@
 
   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 @@
 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 @@
     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);
-
-  mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+      XDrawLine (dpy, window, gc,
+		 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
+
+  mac_reset_clipping (dpy, window);
 }
 
 
@@ -2326,7 +2546,7 @@
 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 @@
 
   /* 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 @@
   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 @@
 
   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 @@
 }
 
 
-
 /* Draw a relief around the image glyph string S.  */
 
 static void
@@ -2567,30 +2783,12 @@
 
   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 @@
 	    {
 	      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 @@
 	     |   s->face->box
 	     |
 	     |     +-------------------------
-	     |     |  s->img->vmargin
+	     |     |  s->img->margin
 	     |     |
 	     |     |       +-------------------
 	     |     |       |  the image
@@ -2665,6 +2864,7 @@
 
   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 @@
   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 = 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 @@
 	      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_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 @@
       /* 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_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 @@
       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 @@
 	    }
 	}
 
-      /* 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 @@
 		   x + shift_by, y);
 }
 
-
 /* Delete N glyphs at the nominal cursor position.  Not implemented
    for X frames.  */
 
@@ -3026,6 +3219,7 @@
 
 #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 @@
    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 @@
 
   /* 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 @@
 XTframe_rehighlight (frame)
      struct frame *frame;
 {
-
-
   x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
 }
 
@@ -4429,13 +4621,6 @@
   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 @@
   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 @@
    --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;
-{
-  /* 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;
-      GC gc;
-      int x;
-      unsigned long mask;
+     enum text_cursor_kinds kind;
+{
+  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 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 @@
 
       if (width < 0)
 	width = FRAME_CURSOR_WIDTH (f);
-
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+      width = min (cursor_glyph->pixel_width, width);
+
+      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 @@
   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 @@
 	{
 	  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 @@
 	  draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
 	  break;
 
+	case BAR_CURSOR:
+	  x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_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, HBAR_CURSOR);
 	  break;
 
 	case NO_CURSOR:
+	  w->phys_cursor_width = 0;
 	  break;
 
 	default:
@@ -5117,6 +5341,8 @@
 	FRAME_SAMPLE_VISIBILITY (f);
       }
   }
+#else
+  UNBLOCK_INPUT;
 #endif /* MAC_TODO */
 }
 
@@ -5173,10 +5399,10 @@
 }
 
 
-/* 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 @@
   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 @@
   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 @@
 
   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--;
+}
+
 
 /* Setting window manager hints.  */
 
@@ -5478,6 +5722,7 @@
 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 @@
           && 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 @@
 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 @@
               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 @@
 	  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)
-	      {
+	    {
+	      /* 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));
-		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 @@
 
 	  TextFont (fontnum);
 	  scriptcode = FontToScript (fontnum);
+	  decode_mac_font_name (name, sizeof (name), scriptcode);
 	  do
 	    {
 	      HLock (font_handle);
@@ -5806,9 +6119,9 @@
 					     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 @@
 }
 
 
+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 @@
               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 @@
 	}
     }
 
-  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 @@
     name = fontname;
   else
     {
-      for (i = 0; i < font_name_count; i++)
-        if (mac_font_pattern_match (font_name_table[i], fontname))
-          break;
-
-      if (i >= font_name_count)
-        return NULL;
-
-      name = font_name_table[i];
+      Lisp_Object matched_fonts;
+
+      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 @@
         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 @@
 		    }
 		  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 @@
   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 @@
   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;
--- a/src/macterm.h	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/macterm.h	Thu Feb 26 17:46:48 2004 +0000
@@ -23,45 +23,26 @@
 #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 @@
   /* 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;
--- a/src/s/darwin.h	Thu Feb 26 11:14:34 2004 +0000
+++ b/src/s/darwin.h	Thu Feb 26 17:46:48 2004 +0000
@@ -247,7 +247,7 @@
    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