]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
Fix last change:
[gnu-emacs] / src / macterm.c
index 1153efda18cb72e0aec7f4d777c9c791fa3b0906..cbef67c3bee34a0e8dc5c40498acedb1aab1054d 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of GUI terminal on the Mac OS.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-                 2005 Free Software Foundation, Inc.
+                 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -68,7 +68,6 @@ Boston, MA 02110-1301, USA.  */
 #include <errno.h>
 #include <setjmp.h>
 #include <sys/stat.h>
-#include <sys/param.h>
 
 #include "charset.h"
 #include "coding.h"
@@ -78,7 +77,6 @@ Boston, MA 02110-1301, USA.  */
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
-#include "gnu.h"
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
@@ -93,8 +91,9 @@ Boston, MA 02110-1301, USA.  */
 
 Lisp_Object Vx_toolkit_scroll_bars;
 
-/* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text.  */
-Lisp_Object Vmac_use_core_graphics;
+/* If non-zero, the text will be rendered using Core Graphics text
+   rendering which may anti-alias the text.  */
+int mac_use_core_graphics;
 
 
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
@@ -105,6 +104,10 @@ static int any_help_event_p;
 /* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
 static Lisp_Object last_window;
 
+/* Non-zero means make use of UNDERLINE_POSITION font properties.
+   (Not yet supported.)  */
+int x_use_underline_position_properties;
+
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
@@ -199,8 +202,7 @@ extern EMACS_INT extra_keyboard_modifiers;
 
 /* The keysyms to use for the various modifiers.  */
 
-static Lisp_Object Qalt, Qhyper, Qsuper, Qctrl,
-  Qmeta, Qmodifier_value;
+static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
 
 extern int inhibit_window_system;
 
@@ -212,7 +214,6 @@ QDGlobals qd;  /* QuickDraw global information structure.  */
 
 struct mac_display_info *mac_display_info_for_display (Display *);
 static void x_update_window_end P_ ((struct window *, int, int));
-static int x_io_error_quitter P_ ((Display *));
 int x_catch_errors P_ ((Display *));
 void x_uncatch_errors P_ ((Display *, int));
 void x_lower_frame P_ ((struct frame *));
@@ -255,7 +256,7 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            unsigned long *));
 
 static int is_emacs_window P_ ((WindowPtr));
-
+static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
 static void XSetFont P_ ((Display *, GC, XFontStruct *));
 
 /* Defined in macmenu.h.  */
@@ -264,14 +265,84 @@ extern void menubar_selection_callback (FRAME_PTR, int);
 #define GC_FORE_COLOR(gc)      (&(gc)->fore_color)
 #define GC_BACK_COLOR(gc)      (&(gc)->back_color)
 #define GC_FONT(gc)            ((gc)->xgcv.font)
-#define GC_CLIP_REGION(gc)     ((gc)->clip_region)
 #define FRAME_NORMAL_GC(f)     ((f)->output_data.mac->normal_gc)
+#define CG_SET_FILL_COLOR(context, color)                      \
+  CGContextSetRGBFillColor (context,                                   \
+                           RED_FROM_ULONG (color) / 255.0f,            \
+                           GREEN_FROM_ULONG (color) / 255.0f,          \
+                           BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
+#define CG_SET_STROKE_COLOR(context, color)            \
+  CGContextSetRGBStrokeColor (context,                                 \
+                             RED_FROM_ULONG (color) / 255.0f,          \
+                             GREEN_FROM_ULONG (color) / 255.0f,        \
+                             BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
+#if USE_CG_DRAWING
+#define FRAME_CG_CONTEXT(f)    ((f)->output_data.mac->cg_context)
+
+/* Fringe bitmaps.  */
+
+static int max_fringe_bmp = 0;
+static CGImageRef *fringe_bmp = 0;
+
+static CGContextRef
+mac_begin_cg_clip (f, gc)
+     struct frame *f;
+     GC gc;
+{
+  CGContextRef context = FRAME_CG_CONTEXT (f);
+
+  if (!context)
+    {
+      QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
+      FRAME_CG_CONTEXT (f) = context;
+    }
+
+  CGContextSaveGState (context);
+  CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
+  CGContextScaleCTM (context, 1, -1);
+  if (gc && gc->n_clip_rects)
+    CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+
+  return context;
+}
+
+static void
+mac_end_cg_clip (f)
+     struct frame *f;
+{
+  CGContextRestoreGState (FRAME_CG_CONTEXT (f));
+}
+
+void
+mac_prepare_for_quickdraw (f)
+     struct frame *f;
+{
+  if (f == NULL)
+    {
+      Lisp_Object rest, frame;
+      FOR_EACH_FRAME (rest, frame)
+       if (FRAME_MAC_P (XFRAME (frame)))
+         mac_prepare_for_quickdraw (XFRAME (frame));
+    }
+  else
+    {
+      CGContextRef context = FRAME_CG_CONTEXT (f);
+
+      if (context)
+       {
+         CGContextSynchronize (context);
+         QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
+                         &FRAME_CG_CONTEXT (f));
+       }
+    }
+}
+#endif
 
 static RgnHandle saved_port_clip_region = NULL;
 
 static void
-mac_begin_clip (region)
-     RgnHandle region;
+mac_begin_clip (gc)
+     GC gc;
 {
   static RgnHandle new_region = NULL;
 
@@ -280,19 +351,19 @@ mac_begin_clip (region)
   if (new_region == NULL)
     new_region = NewRgn ();
 
-  if (region)
+  if (gc->n_clip_rects)
     {
       GetClip (saved_port_clip_region);
-      SectRgn (saved_port_clip_region, region, new_region);
+      SectRgn (saved_port_clip_region, gc->clip_region, new_region);
       SetClip (new_region);
     }
 }
 
 static void
-mac_end_clip (region)
-     RgnHandle region;
+mac_end_clip (gc)
+     GC gc;
 {
-  if (region)
+  if (gc->n_clip_rects)
     SetClip (saved_port_clip_region);
 }
 
@@ -316,14 +387,27 @@ mac_draw_line (f, gc, x1, y1, x2, y2)
      GC gc;
      int x1, y1, x2, y2;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CGContextBeginPath (context);
+  CGContextMoveToPoint (context, x1 + 0.5f, y1 + 0.5f);
+  CGContextAddLineToPoint (context, x2 + 0.5f, y2 + 0.5f);
+  CGContextClosePath (context);
+  CGContextStrokePath (context);
+  mac_end_cg_clip (f);
+#else
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBForeColor (GC_FORE_COLOR (gc));
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   MoveTo (x1, y1);
   LineTo (x2, y2);
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
+#endif
 }
 
 void
@@ -357,6 +441,14 @@ mac_erase_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
@@ -364,11 +456,12 @@ mac_erase_rectangle (f, gc, x, y, width, height)
   RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   EraseRect (&r);
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+#endif
 }
 
 
@@ -389,6 +482,16 @@ static void
 mac_clear_window (f)
      struct frame *f;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+  GC gc = FRAME_NORMAL_GC (f);
+
+  context = mac_begin_cg_clip (f, NULL);
+  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
+                                         FRAME_PIXEL_HEIGHT (f)));
+  mac_end_cg_clip (f);
+#else
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
@@ -403,11 +506,50 @@ mac_clear_window (f)
 #else /* not TARGET_API_MAC_CARBON */
   EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
 #endif /* not TARGET_API_MAC_CARBON */
+#endif
 }
 
 
 /* Mac replacement for XCopyArea.  */
 
+#if USE_CG_DRAWING
+static void
+mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
+                  dest_x, dest_y, overlay_p)
+     CGImageRef image;
+     struct frame *f;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y, overlay_p;
+{
+  CGContextRef context;
+  float port_height = FRAME_PIXEL_HEIGHT (f);
+  CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
+
+  context = mac_begin_cg_clip (f, gc);
+  if (!overlay_p)
+    {
+      CG_SET_FILL_COLOR (context, gc->xgcv.background);
+      CGContextFillRect (context, dest_rect);
+    }
+  CGContextClipToRect (context, dest_rect);
+  CGContextScaleCTM (context, 1, -1);
+  CGContextTranslateCTM (context, 0, -port_height);
+  if (CGImageIsMask (image))
+    CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextDrawImage (context,
+                     CGRectMake (dest_x - src_x,
+                                 port_height - (dest_y - src_y
+                                                + CGImageGetHeight (image)),
+                                 CGImageGetWidth (image),
+                                 CGImageGetHeight (image)),
+                     image);
+  mac_end_cg_clip (f);
+}
+
+#else  /* !USE_CG_DRAWING */
+
 static void
 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
      struct frame *f;
@@ -429,7 +571,7 @@ mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
   RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
 #if TARGET_API_MAC_CARBON
   {
     CGrafPtr port;
@@ -444,10 +586,11 @@ mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
   CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
            overlay_p ? srcOr : srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCreateBitmapFromBitmapData.  */
@@ -508,7 +651,15 @@ XCreatePixmap (display, w, width, height, depth)
   SetPortWindowPort (w);
 
   SetRect (&r, 0, 0, width, height);
-  err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
+#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
+  if (depth == 1)
+#endif
+    err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
+#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
+  else
+    /* CreateCGImageFromPixMaps requires ARGB format.  */
+    err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
+#endif
   if (err != noErr)
     return NULL;
   return pixmap;
@@ -569,6 +720,14 @@ mac_fill_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
@@ -576,9 +735,10 @@ mac_fill_rectangle (f, gc, x, y, width, height)
   RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   PaintRect (&r); /* using foreground color of gc */
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
+#endif
 }
 
 
@@ -591,6 +751,15 @@ mac_draw_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CGContextStrokeRect (context,
+                      CGRectMake (x + 0.5f, y + 0.5f, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
@@ -598,9 +767,10 @@ mac_draw_rectangle (f, gc, x, y, width, height)
   RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width + 1, y + height + 1);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   FrameRect (&r); /* using foreground color of gc */
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
+#endif
 }
 
 
@@ -622,7 +792,8 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
       ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
       static ATSLineLayoutOptions line_layout =
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-       kATSLineDisableAllLayoutOperations  | kATSLineUseDeviceMetrics
+       kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
+       | kATSLineUseQDRendering
 #else
        kATSLineIsDisplayOnly | kATSLineFractDisable
 #endif
@@ -669,6 +840,9 @@ mac_invert_rectangle (f, x, y, width, height)
 {
   Rect r;
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   SetRect (&r, x, y, x + width, y + height);
@@ -678,27 +852,15 @@ mac_invert_rectangle (f, x, y, width, height)
 
 
 static void
-mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char)
+mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, bytes_per_char)
      struct frame *f;
      GC gc;
      int x, y;
      char *buf;
-     int nchars, mode, bytes_per_char;
+     int nchars, bg_width, bytes_per_char;
 {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-  UInt32 textFlags, savedFlags;
-  if (!NILP(Vmac_use_core_graphics)) {
-    textFlags = kQDUseCGTextRendering;
-    savedFlags = SwapQDTextFlags(textFlags);
-  }
-#endif
-
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  RGBForeColor (GC_FORE_COLOR (gc));
-  if (mode != srcOr)
-    RGBBackColor (GC_BACK_COLOR (gc));
-
 #if USE_ATSUI
   if (GC_FONT (gc)->mac_style)
     {
@@ -720,91 +882,151 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char)
                                                nchars,
                                                GC_FONT (gc)->mac_style,
                                                &text_layout);
-      if (err == noErr)
-       {
+      if (err != noErr)
+       return;
 #ifdef MAC_OSX
-         if (NILP (Vmac_use_core_graphics))
-           {
+      if (!mac_use_core_graphics)
+       {
 #endif
-             mac_begin_clip (GC_CLIP_REGION (gc));
-             MoveTo (x, y);
-             ATSUDrawText (text_layout,
-                           kATSUFromTextBeginning, kATSUToTextEnd,
-                           kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
-             mac_end_clip (GC_CLIP_REGION (gc));
-#ifdef MAC_OSX
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
+#endif
+         mac_begin_clip (gc);
+         RGBForeColor (GC_FORE_COLOR (gc));
+         if (bg_width)
+           {
+             Rect r;
+
+             SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
+                      x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
+             RGBBackColor (GC_BACK_COLOR (gc));
+             EraseRect (&r);
+             RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
            }
-         else
+         MoveTo (x, y);
+         ATSUDrawText (text_layout,
+                       kATSUFromTextBeginning, kATSUToTextEnd,
+                       kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
+         mac_end_clip (gc);
+#ifdef MAC_OSX
+       }
+      else
+       {
+         CGrafPtr port;
+         CGContextRef context;
+         float port_height = FRAME_PIXEL_HEIGHT (f);
+         ATSUAttributeTag tags[] = {kATSUCGContextTag};
+         ByteCount sizes[] = {sizeof (CGContextRef)};
+         ATSUAttributeValuePtr values[] = {&context};
+
+#if USE_CG_DRAWING
+         context = mac_begin_cg_clip (f, gc);
+#else
+         GetPort (&port);
+         QDBeginCGContext (port, &context);
+         if (gc->n_clip_rects || bg_width)
            {
-             CGrafPtr port;
-             CGContextRef context;
-             float port_height = FRAME_PIXEL_HEIGHT (f);
-             ATSUAttributeTag tags[] = {kATSUCGContextTag};
-             ByteCount sizes[] = {sizeof (CGContextRef)};
-             ATSUAttributeValuePtr values[] = {&context};
-
-             GetPort (&port);
-             QDBeginCGContext (port, &context);
+             CGContextTranslateCTM (context, 0, port_height);
+             CGContextScaleCTM (context, 1, -1);
              if (gc->n_clip_rects)
+               CGContextClipToRects (context, gc->clip_rects,
+                                     gc->n_clip_rects);
+#endif
+             if (bg_width)
                {
-                 CGContextTranslateCTM (context, 0, port_height);
-                 CGContextScaleCTM (context, 1, -1);
-                 CGContextClipToRects (context, gc->clip_rects,
-                                       gc->n_clip_rects);
-                 CGContextScaleCTM (context, 1, -1);
-                 CGContextTranslateCTM (context, 0, -port_height);
+                 CG_SET_FILL_COLOR (context, gc->xgcv.background);
+                 CGContextFillRect
+                   (context,
+                    CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
+                                bg_width, FONT_HEIGHT (GC_FONT (gc))));
                }
-             CGContextSetRGBFillColor
-               (context,
-                RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                1.0);
-             err = ATSUSetLayoutControls (text_layout,
-                                          sizeof (tags) / sizeof (tags[0]),
-                                          tags, sizes, values);
-             if (err == noErr)
-               ATSUDrawText (text_layout,
-                             kATSUFromTextBeginning, kATSUToTextEnd,
-                             Long2Fix (x), Long2Fix (port_height - y));
-             CGContextSynchronize (context);
-             QDEndCGContext (port, &context);
-#if 0
-             /* This doesn't work on Mac OS X 10.1.  */
-             ATSUClearLayoutControls (text_layout,
+             CGContextScaleCTM (context, 1, -1);
+             CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
+           }
+#endif
+         CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+         err = ATSUSetLayoutControls (text_layout,
                                       sizeof (tags) / sizeof (tags[0]),
-                                      tags);
+                                      tags, sizes, values);
+         if (err == noErr)
+           ATSUDrawText (text_layout,
+                         kATSUFromTextBeginning, kATSUToTextEnd,
+                         Long2Fix (x), Long2Fix (port_height - y));
+#if USE_CG_DRAWING
+         mac_end_cg_clip (f);
+         context = NULL;
 #else
-             ATSUSetLayoutControls (text_layout,
-                                    sizeof (tags) / sizeof (tags[0]),
-                                    tags, sizes, values);
+         CGContextSynchronize (context);
+         QDEndCGContext (port, &context);
 #endif
-           }
+#if 0
+         /* This doesn't work on Mac OS X 10.1.  */
+         ATSUClearLayoutControls (text_layout,
+                                  sizeof (tags) / sizeof (tags[0]), tags);
+#else
+         ATSUSetLayoutControls (text_layout,
+                                sizeof (tags) / sizeof (tags[0]),
+                                tags, sizes, values);
 #endif
        }
+#endif /* MAC_OSX */
     }
   else
+#endif /* USE_ATSUI */
     {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+      UInt32 savedFlags;
+
+      if (mac_use_core_graphics)
+       savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
+#endif
+#if USE_CG_DRAWING
+      mac_prepare_for_quickdraw (f);
 #endif
-  TextFont (GC_FONT (gc)->mac_fontnum);
-  TextSize (GC_FONT (gc)->mac_fontsize);
-  TextFace (GC_FONT (gc)->mac_fontface);
-  TextMode (mode);
+      mac_begin_clip (gc);
+      RGBForeColor (GC_FORE_COLOR (gc));
+#ifdef MAC_OS8
+      if (bg_width)
+       {
+         RGBBackColor (GC_BACK_COLOR (gc));
+         TextMode (srcCopy);
+       }
+      else
+       TextMode (srcOr);
+#else
+      /* We prefer not to use srcCopy text transfer mode on Mac OS X
+        because:
+        - Screen is double-buffered.  (In srcCopy mode, a text is
+          drawn into an offscreen graphics world first.  So
+          performance gain cannot be expected.)
+        - It lowers rendering quality.
+        - Some fonts leave garbage on cursor movement.  */
+      if (bg_width)
+       {
+         Rect r;
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
-  MoveTo (x, y);
-  DrawText (buf, 0, nchars * bytes_per_char);
-  mac_end_clip (GC_CLIP_REGION (gc));
-#if USE_ATSUI
-    }
+         RGBBackColor (GC_BACK_COLOR (gc));
+         SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
+                  x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
+         EraseRect (&r);
+       }
+      TextMode (srcOr);
 #endif
+      TextFont (GC_FONT (gc)->mac_fontnum);
+      TextSize (GC_FONT (gc)->mac_fontsize);
+      TextFace (GC_FONT (gc)->mac_fontface);
+      MoveTo (x, y);
+      DrawText (buf, 0, nchars * bytes_per_char);
+      if (bg_width)
+       RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+      mac_end_clip (gc);
 
-  if (mode != srcOr)
-    RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-  if (!NILP(Vmac_use_core_graphics))
-    SwapQDTextFlags(savedFlags);
+      if (mac_use_core_graphics)
+       SwapQDTextFlags(savedFlags);
 #endif
+    }
 }
 
 
@@ -818,7 +1040,7 @@ mac_draw_string (f, gc, x, y, buf, nchars)
      char *buf;
      int nchars;
 {
-  mac_draw_string_common (f, gc, x, y, buf, nchars, srcOr, 1);
+  mac_draw_string_common (f, gc, x, y, buf, nchars, 0, 1);
 }
 
 
@@ -832,61 +1054,214 @@ mac_draw_string_16 (f, gc, x, y, buf, nchars)
      XChar2b *buf;
      int nchars;
 {
-  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcOr, 2);
+  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, 0, 2);
 }
 
 
 /* Mac replacement for XDrawImageString.  */
 
 static void
-mac_draw_image_string (f, gc, x, y, buf, nchars)
+mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width)
      struct frame *f;
      GC gc;
      int x, y;
      char *buf;
-     int nchars;
+     int nchars, bg_width;
 {
-  mac_draw_string_common (f, gc, x, y, buf, nchars, srcCopy, 1);
+  mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, 1);
 }
 
 
 /* Mac replacement for XDrawString16.  */
 
 static void
-mac_draw_image_string_16 (f, gc, x, y, buf, nchars)
+mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width)
      struct frame *f;
      GC gc;
      int x, y;
      XChar2b *buf;
-     int nchars;
+     int nchars, bg_width;
 {
-  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcCopy, 2);
+  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width, 2);
 }
 
 
+/* Mac replacement for XQueryTextExtents, but takes a character.  If
+   STYLE is NULL, measurement is done by QuickDraw Text routines for
+   the font of the current graphics port.  If CG_GLYPH is not NULL,
+   *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained.  */
+
+static OSErr
+mac_query_char_extents (style, c,
+                       font_ascent_return, font_descent_return,
+                       overall_return, cg_glyph)
+#if USE_ATSUI
+     ATSUStyle style;
+#else
+     void *style;
+#endif
+     int c;
+     int *font_ascent_return, *font_descent_return;
+     XCharStruct *overall_return;
 #if USE_CG_TEXT_DRAWING
-static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
+     CGGlyph *cg_glyph;
+#else
+     void *cg_glyph;
+#endif
+{
+  OSErr err = noErr;
+  int width;
+  Rect char_bounds;
+
+#if USE_ATSUI
+  if (style)
+    {
+      ATSUTextLayout text_layout;
+      UniChar ch = c;
+
+      err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
+      if (err == noErr)
+       {
+         ATSTrapezoid glyph_bounds;
+
+         err = ATSUGetGlyphBounds (text_layout, 0, 0,
+                                   kATSUFromTextBeginning, kATSUToTextEnd,
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+                                   kATSUseFractionalOrigins,
+#else
+                                   kATSUseDeviceOrigins,
+#endif
+                                   1, &glyph_bounds, NULL);
+         if (err == noErr)
+           {
+             xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
+                      == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
+
+             width = Fix2Long (glyph_bounds.upperRight.x
+                               - glyph_bounds.upperLeft.x);
+             if (font_ascent_return)
+               *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
+             if (font_descent_return)
+               *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
+           }
+       }
+      if (err == noErr && overall_return)
+       {
+         err = ATSUMeasureTextImage (text_layout,
+                                     kATSUFromTextBeginning, kATSUToTextEnd,
+                                     0, 0, &char_bounds);
+         if (err == noErr)
+           STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
+#if USE_CG_TEXT_DRAWING
+         if (err == noErr && cg_glyph)
+           {
+             OSErr err1;
+             ATSUGlyphInfoArray glyph_info_array;
+             ByteCount count = sizeof (ATSUGlyphInfoArray);
+
+             err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
+                                          kATSUToTextEnd, NULL, NULL, NULL);
+             if (err1 == noErr)
+               err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
+                                        kATSUToTextEnd, &count,
+                                        &glyph_info_array);
+             if (err1 == noErr)
+               {
+                 xassert (glyph_info_array.glyphs[0].glyphID);
+                 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
+               }
+             else
+               *cg_glyph = 0;
+           }
+#endif
+       }
+    }
+  else
+#endif
+    {
+      if (font_ascent_return || font_descent_return)
+       {
+         FontInfo font_info;
+
+         GetFontInfo (&font_info);
+         if (font_ascent_return)
+           *font_ascent_return = font_info.ascent;
+         if (font_descent_return)
+           *font_descent_return = font_info.descent;
+       }
+      if (overall_return)
+       {
+         char ch = c;
+
+         width = CharWidth (ch);
+         QDTextBounds (1, &ch, &char_bounds);
+         STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
+       }
+    }
+
+  return err;
+}
+
+
+/* Mac replacement for XTextExtents16.  Only sets horizontal metrics.  */
+
+static int
+mac_text_extents_16 (font_struct, string, nchars, overall_return)
+     XFontStruct *font_struct;
+     XChar2b *string;
+     int nchars;
+     XCharStruct *overall_return;
+{
+  int i;
+  short width = 0, lbearing = 0, rbearing = 0;
+  XCharStruct *pcm;
+
+  for (i = 0; i < nchars; i++)
+    {
+      pcm = mac_per_char_metric (font_struct, string, 0);
+      if (pcm == NULL)
+       width += FONT_WIDTH (font_struct);
+      else
+       {
+         lbearing = min (lbearing, width + pcm->lbearing);
+         rbearing = max (rbearing, width + pcm->rbearing);
+         width += pcm->width;
+       }
+      string++;
+    }
+
+  overall_return->lbearing = lbearing;
+  overall_return->rbearing = rbearing;
+  overall_return->width = width;
 
+  /* What's the meaning of the return value of XTextExtents16?  */
+}
+
+
+#if USE_CG_TEXT_DRAWING
 static int cg_text_anti_aliasing_threshold = 8;
 
 static void
 init_cg_text_anti_aliasing_threshold ()
 {
-  Lisp_Object val =
-    Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"),
-                        Qnil, Qnil, Qnil);
+  int threshold;
+  Boolean valid_p;
 
-  if (INTEGERP (val))
-    cg_text_anti_aliasing_threshold = XINT (val);
+  threshold =
+    CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
+                                    kCFPreferencesCurrentApplication,
+                                    &valid_p);
+  if (valid_p)
+    cg_text_anti_aliasing_threshold = threshold;
 }
 
 static int
-mac_draw_string_cg (f, gc, x, y, buf, nchars)
+mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width)
      struct frame *f;
      GC gc;
      int x, y;
      XChar2b *buf;
-     int nchars;
+     int nchars, bg_width;
 {
   CGrafPtr port;
   float port_height, gx, gy;
@@ -895,7 +1270,7 @@ mac_draw_string_cg (f, gc, x, y, buf, nchars)
   CGGlyph *glyphs;
   CGSize *advances;
 
-  if (NILP (Vmac_use_core_graphics) || GC_FONT (gc)->cg_font == NULL)
+  if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
     return 0;
 
   port = GetWindowPort (FRAME_MAC_WINDOW (f));
@@ -903,29 +1278,44 @@ mac_draw_string_cg (f, gc, x, y, buf, nchars)
   gx = x;
   gy = port_height - y;
   glyphs = (CGGlyph *)buf;
-  advances = xmalloc (sizeof (CGSize) * nchars);
+  advances = alloca (sizeof (CGSize) * nchars);
+  if (advances == NULL)
+    return 0;
   for (i = 0; i < nchars; i++)
     {
-      advances[i].width = x_per_char_metric (GC_FONT (gc), buf)->width;
+      XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
+
+      advances[i].width = pcm->width;
       advances[i].height = 0;
       glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
       buf++;
     }
 
+#if USE_CG_DRAWING
+  context = mac_begin_cg_clip (f, gc);
+#else
   QDBeginCGContext (port, &context);
-  if (gc->n_clip_rects)
+  if (gc->n_clip_rects || bg_width)
     {
       CGContextTranslateCTM (context, 0, port_height);
       CGContextScaleCTM (context, 1, -1);
-      CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+      if (gc->n_clip_rects)
+       CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+#endif
+      if (bg_width)
+       {
+         CG_SET_FILL_COLOR (context, gc->xgcv.background);
+         CGContextFillRect
+           (context,
+            CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
+                        bg_width, FONT_HEIGHT (GC_FONT (gc))));
+       }
       CGContextScaleCTM (context, 1, -1);
       CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
     }
-  CGContextSetRGBFillColor (context,
-                           RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                           GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                           BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                           1.0);
+#endif
+  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
   CGContextSetFont (context, GC_FONT (gc)->cg_font);
   CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
   if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
@@ -940,16 +1330,19 @@ mac_draw_string_cg (f, gc, x, y, buf, nchars)
       gx += advances[i].width;
     }
 #endif
+#if USE_CG_DRAWING
+  mac_end_cg_clip (f);
+#else
   CGContextSynchronize (context);
   QDEndCGContext (port, &context);
-
-  xfree (advances);
+#endif
 
   return 1;
 }
 #endif
 
 
+#if !USE_CG_DRAWING
 /* Mac replacement for XCopyArea: dest must be window.  */
 
 static void
@@ -971,7 +1364,7 @@ mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
   ForeColor (blackColor);
   BackColor (whiteColor);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
 #if TARGET_API_MAC_CARBON
   {
@@ -989,7 +1382,7 @@ mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
            &src_r, &dest_r, srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (src));
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
@@ -1015,7 +1408,7 @@ mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
   ForeColor (blackColor);
   BackColor (whiteColor);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
   LockPixels (GetGWorldPixMap (mask));
 #if TARGET_API_MAC_CARBON
@@ -1035,10 +1428,11 @@ mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (mask));
   UnlockPixels (GetGWorldPixMap (src));
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCopyArea: used only for scrolling.  */
@@ -1056,6 +1450,9 @@ mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
   RgnHandle dummy = NewRgn (); /* For avoiding update events.  */
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   ScrollWindowRect (FRAME_MAC_WINDOW (f),
                    &src_r, dest_x - src_x, dest_y - src_y,
                    kScrollWindowNoOptions, dummy);
@@ -1073,9 +1470,9 @@ mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
      color mapping in CopyBits.  Otherwise, it will be slow.  */
   ForeColor (blackColor);
   BackColor (whiteColor);
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 #endif /* not TARGET_API_MAC_CARBON */
@@ -1111,11 +1508,8 @@ XCreateGC (display, window, mask, xgcv)
 {
   GC gc = xmalloc (sizeof (*gc));
 
-  if (gc)
-    {
-      bzero (gc, sizeof (*gc));
-      XChangeGC (display, gc, mask, xgcv);
-    }
+  bzero (gc, sizeof (*gc));
+  XChangeGC (display, gc, mask, xgcv);
 
   return gc;
 }
@@ -1211,17 +1605,10 @@ mac_set_clip_rectangles (display, gc, rectangles, n)
 {
   int i;
 
-  if (n < 0 || n > MAX_CLIP_RECTS)
-    abort ();
-  if (n == 0)
-    {
-      if (gc->clip_region)
-       {
-         DisposeRgn (gc->clip_region);
-         gc->clip_region = NULL;
-       }
-    }
-  else
+  xassert (n >= 0 && n <= MAX_CLIP_RECTS);
+
+  gc->n_clip_rects = n;
+  if (n > 0)
     {
       if (gc->clip_region == NULL)
        gc->clip_region = NewRgn ();
@@ -1239,8 +1626,6 @@ mac_set_clip_rectangles (display, gc, rectangles, n)
        }
     }
 #if defined (MAC_OSX) && USE_ATSUI
-  gc->n_clip_rects = n;
-
   for (i = 0; i < n; i++)
     {
       Rect *rect = rectangles + i;
@@ -1260,7 +1645,7 @@ mac_reset_clip_rectangles (display, gc)
      Display *display;
      GC gc;
 {
-  mac_set_clip_rectangles (display, gc, NULL, 0);
+  gc->n_clip_rects = 0;
 }
 
 
@@ -1307,14 +1692,6 @@ XSetWindowBackground (display, w, color)
 #endif
 }
 
-/* x_sync is a no-op on Mac.  */
-void
-x_sync (f)
-     void *f;
-{
-}
-
-
 /* Flush display of frame F, or of all frames if F is null.  */
 
 static void
@@ -1323,6 +1700,9 @@ x_flush (f)
 {
 #if TARGET_API_MAC_CARBON
   BLOCK_INPUT;
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   if (f)
     QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
   else
@@ -1653,9 +2033,12 @@ x_draw_fringe_bitmap (w, row, p)
 #endif
     }
 
-  if (p->which)
+  if (p->which
+#if USE_CG_DRAWING
+      && p->which < max_fringe_bmp
+#endif
+      )
     {
-      unsigned short *bits = p->bits + p->dh;
       XGCValues gcv;
 
       XGetGCValues (display, face->gc, GCForeground, &gcv);
@@ -1664,14 +2047,63 @@ x_draw_fringe_bitmap (w, row, p)
                       ? (p->overlay_p ? face->background
                          : f->output_data.mac->cursor_pixel)
                       : face->foreground));
+#if USE_CG_DRAWING
+      mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
+                        p->wd, p->h, p->x, p->y, p->overlay_p);
+#else
       mac_draw_bitmap (f, face->gc, p->x, p->y,
-                      p->wd, p->h, bits, p->overlay_p);
+                      p->wd, p->h, p->bits + p->dh, p->overlay_p);
+#endif
       XSetForeground (display, face->gc, gcv.foreground);
     }
 
   mac_reset_clip_rectangles (display, face->gc);
 }
 
+#if USE_CG_DRAWING
+static void
+mac_define_fringe_bitmap (which, bits, h, wd)
+     int which;
+     unsigned short *bits;
+     int h, wd;
+{
+  int i;
+  CGDataProviderRef provider;
+
+  if (which >= max_fringe_bmp)
+    {
+      i = max_fringe_bmp;
+      max_fringe_bmp = which + 20;
+      fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
+      while (i < max_fringe_bmp)
+       fringe_bmp[i++] = 0;
+    }
+
+  for (i = 0; i < h; i++)
+    bits[i] = ~bits[i];
+  provider = CGDataProviderCreateWithData (NULL, bits,
+                                          sizeof (unsigned short) * h, NULL);
+  if (provider)
+    {
+      fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
+                                            sizeof (unsigned short),
+                                            provider, NULL, 0);
+      CGDataProviderRelease (provider);
+    }
+}
+
+static void
+mac_destroy_fringe_bitmap (which)
+     int which;
+{
+  if (which >= max_fringe_bmp)
+    return;
+
+  if (fringe_bmp[which])
+    CGImageRelease (fringe_bmp[which]);
+  fringe_bmp[which] = 0;
+}
+#endif
 \f
 
 /* This is called when starting Emacs and when restarting after
@@ -1720,63 +2152,28 @@ x_per_char_metric (font, char2b)
 #if USE_ATSUI
   if (font->mac_style)
     {
-      if (char2b->byte1 >= font->min_byte1
-         && char2b->byte1 <= font->max_byte1
-         && char2b->byte2 >= font->min_char_or_byte2
-         && char2b->byte2 <= font->max_char_or_byte2)
+      XCharStructRow **row = font->bounds.rows + char2b->byte1;
+
+      if (*row == NULL)
        {
-         pcm = (font->per_char
-                + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
-                   * (char2b->byte1 - font->min_byte1))
-                + (char2b->byte2 - font->min_char_or_byte2));
+         *row = xmalloc (sizeof (XCharStructRow));
+         bzero (*row, sizeof (XCharStructRow));
        }
-
-      if (pcm && !pcm->valid_p)
+      pcm = (*row)->per_char + char2b->byte2;
+      if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2))
        {
-         OSErr err;
-         ATSUTextLayout text_layout;
-         UniChar c;
-         int char_width;
-         ATSTrapezoid glyph_bounds;
-         Rect char_bounds;
-
-         c = (char2b->byte1 << 8) + char2b->byte2;
          BLOCK_INPUT;
-         err = atsu_get_text_layout_with_text_ptr (&c, 1,
-                                                   font->mac_style,
-                                                   &text_layout);
-         if (err == noErr)
-           err = ATSUMeasureTextImage (text_layout,
-                                       kATSUFromTextBeginning, kATSUToTextEnd,
-                                       0, 0, &char_bounds);
-
-         if (err == noErr)
-           err = ATSUGetGlyphBounds (text_layout, 0, 0,
-                                     kATSUFromTextBeginning, kATSUToTextEnd,
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-                                     kATSUseFractionalOrigins,
-#else
-                                     kATSUseDeviceOrigins,
-#endif
-                                     1, &glyph_bounds, NULL);
+         mac_query_char_extents (font->mac_style,
+                                 (char2b->byte1 << 8) + char2b->byte2,
+                                 NULL, NULL, pcm, NULL);
          UNBLOCK_INPUT;
-         if (err != noErr)
-           pcm = NULL;
-         else
-           {
-             xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
-                      == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
-
-             char_width = Fix2Long (glyph_bounds.upperRight.x
-                                    - glyph_bounds.upperLeft.x);
-             STORE_XCHARSTRUCT (*pcm, char_width, char_bounds);
-           }
+         XCHARSTRUCTROW_SET_CHAR_VALID (*row, char2b->byte2);
        }
     }
   else
     {
 #endif
-  if (font->per_char != NULL)
+  if (font->bounds.per_char != NULL)
     {
       if (font->min_byte1 == 0 && font->max_byte1 == 0)
        {
@@ -1789,7 +2186,8 @@ x_per_char_metric (font, char2b)
          if (char2b->byte1 == 0
              && char2b->byte2 >= font->min_char_or_byte2
              && char2b->byte2 <= font->max_char_or_byte2)
-           pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
+           pcm = font->bounds.per_char
+             + (char2b->byte2 - font->min_char_or_byte2);
        }
       else
        {
@@ -1811,7 +2209,7 @@ x_per_char_metric (font, char2b)
              && char2b->byte2 >= font->min_char_or_byte2
              && char2b->byte2 <= font->max_char_or_byte2)
            {
-             pcm = (font->per_char
+             pcm = (font->bounds.per_char
                     + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
                        * (char2b->byte1 - font->min_byte1))
                     + (char2b->byte2 - font->min_char_or_byte2));
@@ -1832,7 +2230,11 @@ x_per_char_metric (font, char2b)
 #endif
 
   return ((pcm == NULL
-          || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
+          || (pcm->width == 0
+#if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics.  */
+              && (pcm->rbearing - pcm->lbearing) == 0
+#endif
+              ))
          ? NULL : pcm);
 }
 
@@ -1950,7 +2352,6 @@ static void x_setup_relief_colors P_ ((struct glyph_string *));
 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
 static void x_draw_image_relief P_ ((struct glyph_string *));
 static void x_draw_image_foreground P_ ((struct glyph_string *));
-static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
@@ -2151,65 +2552,32 @@ static void
 mac_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-  if (s->cmp == NULL
-      && s->first_glyph->type == CHAR_GLYPH)
-    {
-      Rect r;
-      MacFontStruct *font = s->font;
+  if (!(s->cmp == NULL
+       && s->first_glyph->type == CHAR_GLYPH))
+    return;
 
+  if (!s->two_byte_p
 #if USE_ATSUI
-      if (font->mac_style)
-       {
-         OSErr err;
-         ATSUTextLayout text_layout;
-         UniChar *buf;
-         int i;
+      || s->font->mac_style
+#endif
+      )
+    {
+      XCharStruct cs;
 
-         SetRect (&r, 0, 0, 0, 0);
-         buf = xmalloc (sizeof (UniChar) * s->nchars);
-         if (buf)
-           {
-             for (i = 0; i < s->nchars; i++)
-               buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2;
+      mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
+      s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
+      s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
+    }
+  else
+    {
+      Rect r;
+      MacFontStruct *font = s->font;
 
-             err = atsu_get_text_layout_with_text_ptr (buf, s->nchars,
-                                                       font->mac_style,
-                                                       &text_layout);
-             if (err == noErr)
-               err = ATSUMeasureTextImage (text_layout,
-                                           kATSUFromTextBeginning,
-                                           kATSUToTextEnd,
-                                           0, 0, &r);
-             xfree (buf);
-           }
-       }
-      else
-       {
-#endif
       TextFont (font->mac_fontnum);
       TextSize (font->mac_fontsize);
       TextFace (font->mac_fontface);
 
-      if (s->two_byte_p)
-       QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
-      else
-       {
-         int i;
-         char *buf = xmalloc (s->nchars);
-
-         if (buf == NULL)
-           SetRect (&r, 0, 0, 0, 0);
-         else
-           {
-             for (i = 0; i < s->nchars; ++i)
-               buf[i] = s->char2b[i].byte2;
-             QDTextBounds (s->nchars, buf, &r);
-             xfree (buf);
-           }
-       }
-#if USE_ATSUI
-        }
-#endif
+      QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
 
       s->right_overhang = r.right > s->width ? r.right - s->width : 0;
       s->left_overhang = r.left < 0 ? -r.left : 0;
@@ -2228,14 +2596,6 @@ x_clear_glyph_string_rect (s, x, y, w, h)
 }
 
 
-/* We prefer not to use XDrawImageString (srcCopy text transfer mode)
-   on Mac OS X because:
-   - Screen is double-buffered.  (In srcCopy mode, a text is drawn
-     into an offscreen graphics world first.  So performance gain
-     cannot be expected.)
-   - It lowers rendering quality.
-   - Some fonts leave garbage on cursor movement.  */
-
 /* Draw the background of glyph_string S.  If S->background_filled_p
    is non-zero don't draw it.  FORCE_P non-zero means draw the
    background even if it wouldn't be drawn normally.  This is used
@@ -2267,12 +2627,10 @@ x_draw_glyph_string_background (s, force_p)
        }
       else
 #endif
-#if defined (MAC_OS8) && !USE_ATSUI
         if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
               || force_p)
-#endif
        {
          x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
                                     s->background_width,
@@ -2289,7 +2647,7 @@ static void
 x_draw_glyph_string_foreground (s)
      struct glyph_string *s;
 {
-  int i, x;
+  int i, x, bg_width;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
@@ -2328,7 +2686,6 @@ x_draw_glyph_string_foreground (s)
        for (i = 0; i < s->nchars; ++i)
          char1b[i] = s->char2b[i].byte2;
 
-#if defined (MAC_OS8) && !USE_ATSUI
       /* Draw text with XDrawString if background has already been
         filled.  Otherwise, use XDrawImageString.  (Note that
         XDrawImageString is usually faster than XDrawString.)  Always
@@ -2336,38 +2693,27 @@ x_draw_glyph_string_foreground (s)
         no chance that characters under a box cursor are invisible.  */
       if (s->for_overlaps
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
-#endif
-       {
-         /* Draw characters with 16-bit or 8-bit functions.  */
-         if (s->two_byte_p
+       bg_width = 0;           /* Corresponds to XDrawString.  */
+      else
+       bg_width = s->background_width; /* Corresponds to XDrawImageString.  */
+
+      if (s->two_byte_p
 #if USE_ATSUI
-             || GC_FONT (s->gc)->mac_style
+         || GC_FONT (s->gc)->mac_style
 #endif
-             )
+         )
 #if USE_CG_TEXT_DRAWING
-           if (!s->two_byte_p
-               && mac_draw_string_cg (s->f, s->gc, x, s->ybase - boff,
-                                      s->char2b, s->nchars))
-             ;
-           else
+       if (!s->two_byte_p
+           && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
+                                        s->char2b, s->nchars, bg_width))
+         ;
+       else
 #endif
-           mac_draw_string_16 (s->f, s->gc, x, s->ybase - boff,
-                               s->char2b, s->nchars);
-         else
-           mac_draw_string (s->f, s->gc, x, s->ybase - boff,
-                            char1b, s->nchars);
-       }
-#if defined (MAC_OS8) && !USE_ATSUI
+         mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
+                                   s->char2b, s->nchars, bg_width);
       else
-       {
-         if (s->two_byte_p)
-           mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
-                                     s->char2b, s->nchars);
-         else
-           mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
-                                  char1b, s->nchars);
-       }
-#endif
+       mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
+                              char1b, s->nchars, bg_width);
     }
 }
 
@@ -2930,15 +3276,26 @@ x_draw_image_foreground (s)
     {
       x_set_glyph_string_clipping (s);
 
+#if USE_CG_DRAWING
+      mac_draw_cg_image (s->img->data.ptr_val,
+                        s->f, s->gc, s->slice.x, s->slice.y,
+                        s->slice.width, s->slice.height, x, y, 1);
+#endif
       if (s->img->mask)
+#if !USE_CG_DRAWING
        mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
                                 s->f, s->gc, s->slice.x, s->slice.y,
                                 s->slice.width, s->slice.height, x, y);
+#else
+       ;
+#endif
       else
        {
+#if !USE_CG_DRAWING
          mac_copy_area (s->img->pixmap,
                         s->f, s->gc, s->slice.x, s->slice.y,
                         s->slice.width, s->slice.height, x, y);
+#endif
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -3060,7 +3417,6 @@ x_draw_image_glyph_string (s)
   int box_line_hwidth = abs (s->face->box_line_width);
   int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
-  Pixmap pixmap = 0;
 
   height = s->height - 2 * box_line_vwidth;
 
@@ -3806,142 +4162,6 @@ x_frame_rehighlight (dpyinfo)
 
 
 \f
-/* Keyboard processing - modifier keys, vendor-specific keysyms, etc.  */
-
-#if 0 /* MAC_TODO */
-/* Initialize mode_switch_bit and modifier_meaning.  */
-static void
-x_find_modifier_meanings (dpyinfo)
-     struct x_display_info *dpyinfo;
-{
-  int min_code, max_code;
-  KeySym *syms;
-  int syms_per_code;
-  XModifierKeymap *mods;
-
-  dpyinfo->meta_mod_mask = 0;
-  dpyinfo->shift_lock_mask = 0;
-  dpyinfo->alt_mod_mask = 0;
-  dpyinfo->super_mod_mask = 0;
-  dpyinfo->hyper_mod_mask = 0;
-
-#ifdef HAVE_X11R4
-  XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-#else
-  min_code = dpyinfo->display->min_keycode;
-  max_code = dpyinfo->display->max_keycode;
-#endif
-
-  syms = XGetKeyboardMapping (dpyinfo->display,
-                             min_code, max_code - min_code + 1,
-                             &syms_per_code);
-  mods = XGetModifierMapping (dpyinfo->display);
-
-  /* Scan the modifier table to see which modifier bits the Meta and
-     Alt keysyms are on.  */
-  {
-    int row, col;      /* The row and column in the modifier table.  */
-
-    for (row = 3; row < 8; row++)
-      for (col = 0; col < mods->max_keypermod; col++)
-       {
-         KeyCode code
-           = mods->modifiermap[(row * mods->max_keypermod) + col];
-
-         /* Zeroes are used for filler.  Skip them.  */
-         if (code == 0)
-           continue;
-
-         /* Are any of this keycode's keysyms a meta key?  */
-         {
-           int code_col;
-
-           for (code_col = 0; code_col < syms_per_code; code_col++)
-             {
-               int sym = syms[((code - min_code) * syms_per_code) + code_col];
-
-               switch (sym)
-                 {
-                 case XK_Meta_L:
-                 case XK_Meta_R:
-                   dpyinfo->meta_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Alt_L:
-                 case XK_Alt_R:
-                   dpyinfo->alt_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Hyper_L:
-                 case XK_Hyper_R:
-                   dpyinfo->hyper_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Super_L:
-                 case XK_Super_R:
-                   dpyinfo->super_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Shift_Lock:
-                   /* Ignore this if it's not on the lock modifier.  */
-                   if ((1 << row) == LockMask)
-                     dpyinfo->shift_lock_mask = LockMask;
-                   break;
-                 }
-             }
-         }
-       }
-  }
-
-  /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
-  if (! dpyinfo->meta_mod_mask)
-    {
-      dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
-      dpyinfo->alt_mod_mask = 0;
-    }
-
-  /* If some keys are both alt and meta,
-     make them just meta, not alt.  */
-  if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
-    {
-      dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
-    }
-
-  XFree ((char *) syms);
-  XFreeModifiermap (mods);
-}
-
-#endif /* MAC_TODO */
-
-/* Convert between the modifier bits X uses and the modifier bits
-   Emacs uses.  */
-
-static unsigned int
-x_mac_to_emacs_modifiers (dpyinfo, state)
-     struct x_display_info *dpyinfo;
-     unsigned short state;
-{
-  return (((state & shiftKey) ? shift_modifier : 0)
-         | ((state & controlKey) ? ctrl_modifier : 0)
-         | ((state & cmdKey) ? meta_modifier : 0)
-         | ((state & optionKey) ? alt_modifier : 0));
-}
-
-#if 0 /* MAC_TODO */
-static unsigned short
-x_emacs_to_x_modifiers (dpyinfo, state)
-     struct x_display_info *dpyinfo;
-     unsigned int state;
-{
-  return (  ((state & alt_modifier)    ? dpyinfo->alt_mod_mask   : 0)
-         | ((state & super_modifier)   ? dpyinfo->super_mod_mask : 0)
-         | ((state & hyper_modifier)   ? dpyinfo->hyper_mod_mask : 0)
-         | ((state & shift_modifier)   ? ShiftMask        : 0)
-         | ((state & ctrl_modifier)    ? ControlMask      : 0)
-         | ((state & meta_modifier)    ? dpyinfo->meta_mod_mask  : 0));
-}
-#endif /* MAC_TODO */
-
 /* Convert a keysym to its name.  */
 
 char *
@@ -4148,8 +4368,8 @@ static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
                                            struct input_event *));
-static OSErr get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
-                                         Rect *));
+static OSStatus get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
+                                            Rect *));
 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
                                           ControlPartCode,
                                           struct input_event *));
@@ -4270,7 +4490,7 @@ construct_scroll_bar_click (bar, part, bufp)
   bufp->modifiers = 0;
 }
 
-static OSErr
+static OSStatus
 get_control_part_bounds (ch, part_code, rect)
      ControlHandle ch;
      ControlPartCode part_code;
@@ -4412,10 +4632,12 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
      int portion, position, whole;
 {
   ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
-
   int value, viewsize, maximum;
 
-  if (whole == 0 || XINT (bar->track_height) == 0)
+  if (XINT (bar->track_height) == 0)
+    return;
+
+  if (whole == 0)
     value = 0, viewsize = 1, maximum = 0;
   else
     {
@@ -4426,10 +4648,19 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
 
   BLOCK_INPUT;
 
-  SetControl32BitMinimum (ch, 0);
-  SetControl32BitMaximum (ch, maximum);
-  SetControl32BitValue (ch, value);
-  SetControlViewSize (ch, viewsize);
+  if (GetControlViewSize (ch) != viewsize
+      || GetControl32BitValue (ch) != value
+      || GetControl32BitMaximum (ch) != maximum)
+    {
+      /* Temporarily hide the scroll bar to avoid multiple redraws.  */
+      SetControlVisibility (ch, false, false);
+
+      SetControl32BitMaximum (ch, maximum);
+      SetControl32BitValue (ch, value);
+      SetControlViewSize (ch, viewsize);
+
+      SetControlVisibility (ch, true, true);
+    }
 
   UNBLOCK_INPUT;
 }
@@ -4465,8 +4696,16 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
   r.right = left + width;
   r.bottom = disp_top + disp_height;
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
 #if TARGET_API_MAC_CARBON
-  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
+  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
+#if USE_TOOLKIT_SCROLL_BARS
+                  false,
+#else
+                  width < disp_height,
+#endif
                   0, 0, 0, kControlScrollBarProc, (long) bar);
 #else
   ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
@@ -4586,6 +4825,9 @@ x_scroll_bar_remove (bar)
 
   BLOCK_INPUT;
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   /* Destroy the Mac scroll bar control  */
   DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
 
@@ -4636,6 +4878,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   /* Adjustments according to Inside Macintosh to make it look nice */
   disp_top = top;
   disp_height = height;
+#ifdef MAC_OS8
   if (disp_top == 0)
     {
       disp_top = -1;
@@ -4649,6 +4892,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
   if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
     sb_left++;
+#endif
 
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
@@ -4680,12 +4924,17 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
             for them on the frame, we have to clear "under" them.  */
          mac_clear_area (f, left, top, width, height);
 
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
+#endif
           HideControl (ch);
           MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
           SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                       disp_height);
+#ifndef USE_TOOLKIT_SCROLL_BARS
          if (sb_width < disp_height)
            ShowControl (ch);
+#endif
 
           /* Remember new settings.  */
           XSETINT (bar->left, sb_left);
@@ -4704,28 +4953,41 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 #ifdef USE_TOOLKIT_SCROLL_BARS
   if (NILP (bar->track_top))
     {
-      ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
-      Rect r0, r1;
+      if (sb_width >= disp_height)
+       {
+         XSETINT (bar->track_top, 0);
+         XSETINT (bar->track_height, 0);
+       }
+      else
+       {
+         ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+         Rect r0, r1;
 
-      BLOCK_INPUT;
+         BLOCK_INPUT;
 
-      SetControl32BitMinimum (ch, 0);
-      SetControl32BitMaximum (ch, 1);
-      SetControlViewSize (ch, 1);
+         SetControl32BitMinimum (ch, 0);
+         SetControl32BitMaximum (ch, 1);
+         SetControlViewSize (ch, 1);
 
-      /* Move the scroll bar thumb to the top.  */
-      SetControl32BitValue (ch, 0);
-      get_control_part_bounds (ch, kControlIndicatorPart, &r0);
+         /* Move the scroll bar thumb to the top.  */
+         SetControl32BitValue (ch, 0);
+         get_control_part_bounds (ch, kControlIndicatorPart, &r0);
 
-      /* Move the scroll bar thumb to the bottom.  */
-      SetControl32BitValue (ch, 1);
-      get_control_part_bounds (ch, kControlIndicatorPart, &r1);
+         /* Move the scroll bar thumb to the bottom.  */
+         SetControl32BitValue (ch, 1);
+         get_control_part_bounds (ch, kControlIndicatorPart, &r1);
 
-      UnionRect (&r0, &r1, &r0);
-      XSETINT (bar->track_top, r0.top);
-      XSETINT (bar->track_height, r0.bottom - r0.top);
+         UnionRect (&r0, &r1, &r0);
+         XSETINT (bar->track_top, r0.top);
+         XSETINT (bar->track_height, r0.bottom - r0.top);
 
-      UNBLOCK_INPUT;
+         /* Don't show the scroll bar if its height is not enough to
+            display the scroll bar thumb.  */
+         if (r0.bottom - r0.top > 0)
+           ShowControl (ch);
+
+         UNBLOCK_INPUT;
+       }
     }
 
   x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
@@ -5111,7 +5373,7 @@ x_draw_hollow_cursor (w, row)
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
   x_clip_to_row (w, row, TEXT_AREA, gc);
-  mac_draw_rectangle (f, gc, x, y, wd, h);
+  mac_draw_rectangle (f, gc, x, y, wd, h - 1);
   mac_reset_clip_rectangles (dpy, gc);
 }
 
@@ -5208,7 +5470,10 @@ mac_define_frame_cursor (f, cursor)
      struct frame *f;
      Cursor cursor;
 {
-  SetThemeCursor (cursor);
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  if (dpyinfo->x_focus_frame == f)
+    SetThemeCursor (cursor);
 }
 
 
@@ -5635,8 +5900,13 @@ x_set_window_size (f, change_gravity, cols, rows)
   SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
 #if TARGET_API_MAC_CARBON
   if (f->output_data.mac->hourglass_control)
-    MoveControl (f->output_data.mac->hourglass_control,
-                pixelwidth - HOURGLASS_WIDTH, 0);
+    {
+#if USE_CG_DRAWING
+      mac_prepare_for_quickdraw (f);
+#endif
+      MoveControl (f->output_data.mac->hourglass_control,
+                  pixelwidth - HOURGLASS_WIDTH, 0);
+    }
 #endif
 
   /* Now, strictly speaking, we can't be sure that this is accurate,
@@ -5746,7 +6016,7 @@ x_raise_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-      SelectWindow (FRAME_MAC_WINDOW (f));
+      BringToFront (FRAME_MAC_WINDOW (f));
       UNBLOCK_INPUT;
     }
 }
@@ -5760,7 +6030,7 @@ x_lower_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-      SendBehind (FRAME_MAC_WINDOW (f), nil);
+      SendBehind (FRAME_MAC_WINDOW (f), NULL);
       UNBLOCK_INPUT;
     }
 }
@@ -5787,10 +6057,12 @@ mac_handle_visibility_change (f)
   struct input_event buf;
 
   if (IsWindowVisible (wp))
-    if (IsWindowCollapsed (wp))
-      iconified = 1;
-    else
-      visible = 1;
+    {
+      if (IsWindowCollapsed (wp))
+       iconified = 1;
+      else
+       visible = 1;
+    }
 
   if (!f->async_visible && visible)
     {
@@ -5836,9 +6108,6 @@ void
 x_make_frame_visible (f)
      struct frame *f;
 {
-  Lisp_Object type;
-  int original_top, original_left;
-
   BLOCK_INPUT;
 
   if (! FRAME_VISIBLE_P (f))
@@ -5849,31 +6118,32 @@ x_make_frame_visible (f)
         before the window gets really visible.  */
       if (! FRAME_ICONIFIED_P (f)
          && ! f->output_data.mac->asked_for_visible)
+       {
 #if TARGET_API_MAC_CARBON
-       if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
-         {
-           struct frame *sf = SELECTED_FRAME ();
-           if (!FRAME_MAC_P (sf))
-             RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
-                               kWindowCenterOnMainScreen);
-           else
-             RepositionWindow (FRAME_MAC_WINDOW (f),
-                               FRAME_MAC_WINDOW (sf),
+         if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
+           {
+             struct frame *sf = SELECTED_FRAME ();
+             if (!FRAME_MAC_P (sf))
+               RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
+                                 kWindowCenterOnMainScreen);
+             else
+               RepositionWindow (FRAME_MAC_WINDOW (f),
+                                 FRAME_MAC_WINDOW (sf),
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-                               kWindowCascadeStartAtParentWindowScreen
+                                 kWindowCascadeStartAtParentWindowScreen
 #else
-                               kWindowCascadeOnParentWindowScreen
+                                 kWindowCascadeOnParentWindowScreen
 #endif
-                               );
-           x_real_positions (f, &f->left_pos, &f->top_pos);
-         }
-       else
+                                 );
+             x_real_positions (f, &f->left_pos, &f->top_pos);
+           }
+         else
 #endif
-         x_set_offset (f, f->left_pos, f->top_pos, 0);
+           x_set_offset (f, f->left_pos, f->top_pos, 0);
+       }
 
       f->output_data.mac->asked_for_visible = 1;
 
-      SelectWindow (FRAME_MAC_WINDOW (f));
       CollapseWindow (FRAME_MAC_WINDOW (f), false);
       ShowWindow (FRAME_MAC_WINDOW (f));
     }
@@ -6290,12 +6560,7 @@ xlfdpat_create (pattern)
   struct xlfdpat_block *blk;
 
   pat = xmalloc (sizeof (struct xlfdpat));
-  if (pat == NULL)
-    goto error;
-
   pat->buf = xmalloc (strlen (pattern) + 1);
-  if (pat->buf == NULL)
-    goto error;
 
   /* Normalize the pattern string and store it to `pat->buf'.  */
   nblocks = 0;
@@ -6313,15 +6578,17 @@ xlfdpat_create (pattern)
        else
          {
            if (last_char == '?')
-             if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
-               /*  ...*??* -> ...*??  */
-               continue;
-             else
-               /*  ...a??* -> ...a*??  */
-               {
-                 *anychar_head++ = '*';
-                 c = '?';
-               }
+             {
+               if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
+                 /*  ...*??* -> ...*??  */
+                 continue;
+               else
+                 /*  ...a??* -> ...a*??  */
+                 {
+                   *anychar_head++ = '*';
+                   c = '?';
+                 }
+             }
            nblocks++;
          }
       else if (c == '?')
@@ -6357,8 +6624,6 @@ xlfdpat_create (pattern)
     }
 
   pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
-  if (pat->blocks == NULL)
-    goto error;
 
   /* Divide the normalized pattern into blocks.  */
   p = pat->buf;
@@ -6781,6 +7046,25 @@ add_font_name_table_entry (char *font_name)
   font_name_table[font_name_count++] = font_name;
 }
 
+static void
+add_mac_font_name (name, size, style, charset)
+     char *name;
+     int size;
+     Style style;
+     char *charset;
+{
+  if (size > 0)
+    add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
+  else
+    {
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
+                                                   charset));
+    }
+}
+
 /* Sets up the table font_name_table to contain the list of all fonts
    in the system the first time the table is used so that the Resource
    Manager need not be accessed every time this information is
@@ -6806,21 +7090,27 @@ init_font_name_table ()
                           text_encoding_info_alist)))
     {
       OSErr err;
+      struct Lisp_Hash_Table *h;
+      unsigned hash_code;
       ItemCount nfonts, i;
       ATSUFontID *font_ids = NULL;
-      Ptr name, prev_name = NULL;
+      Ptr name;
       ByteCount name_len;
+      Lisp_Object family;
 
       atsu_font_id_hash =
        make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
                         make_float (DEFAULT_REHASH_SIZE),
                         make_float (DEFAULT_REHASH_THRESHOLD),
                         Qnil, Qnil, Qnil);;
+      h = XHASH_TABLE (atsu_font_id_hash);
+
       err = ATSUFontCount (&nfonts);
       if (err == noErr)
-       font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
-      if (font_ids)
-       err = ATSUGetFontIDs (font_ids, nfonts, NULL);
+       {
+         font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
+         err = ATSUGetFontIDs (font_ids, nfonts, NULL);
+       }
       if (err == noErr)
        for (i = 0; i < nfonts; i++)
          {
@@ -6830,40 +7120,25 @@ init_font_name_table ()
            if (err != noErr)
              continue;
            name = xmalloc (name_len + 1);
-           if (name == NULL)
-             continue;
            name[name_len] = '\0';
            err = ATSUFindFontName (font_ids[i], kFontFamilyName,
                                    kFontMacintoshPlatform, kFontNoScript,
                                    kFontNoLanguage, name_len, name,
                                    NULL, NULL);
            if (err == noErr)
-             decode_mac_font_name (name, name_len + 1, Qnil);
-           if (err == noErr
-               && *name != '.'
-               && (prev_name == NULL
-                   || strcmp (name, prev_name) != 0))
              {
-               static char *cs = "iso10646-1";
-
-               add_font_name_table_entry (mac_to_x_fontname (name, 0,
-                                                             normal, cs));
-               add_font_name_table_entry (mac_to_x_fontname (name, 0,
-                                                             italic, cs));
-               add_font_name_table_entry (mac_to_x_fontname (name, 0,
-                                                             bold, cs));
-               add_font_name_table_entry (mac_to_x_fontname (name, 0,
-                                                             italic | bold, cs));
-               Fputhash (make_unibyte_string (name, name_len),
-                         long_to_cons (font_ids[i]), atsu_font_id_hash);
-               xfree (prev_name);
-               prev_name = name;
+               decode_mac_font_name (name, name_len + 1, Qnil);
+               family = make_unibyte_string (name, name_len);
+               if (*name != '.'
+                   && hash_lookup (h, family, &hash_code) < 0)
+                 {
+                   add_mac_font_name (name, 0, normal, "iso10646-1");
+                   hash_put (h, family, long_to_cons (font_ids[i]),
+                             hash_code);
+                 }
              }
-           else
-             xfree (name);
+           xfree (name);
          }
-      if (prev_name)
-       xfree (prev_name);
       if (font_ids)
        xfree (font_ids);
     }
@@ -6891,16 +7166,16 @@ init_font_name_table ()
       FMFontSize size;
       TextEncoding encoding;
       TextEncodingBase sc;
-      Lisp_Object text_encoding_info;
+      Lisp_Object text_encoding_info, family;
 
       if (FMGetFontFamilyName (ff, name) != noErr)
-       break;
+       continue;
       p2cstr (name);
       if (*name == '.')
        continue;
 
       if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
-       break;
+       continue;
       sc = GetTextEncodingBase (encoding);
       text_encoding_info = assq_no_quit (make_number (sc),
                                         text_encoding_info_alist);
@@ -6909,13 +7184,15 @@ init_font_name_table ()
                                           text_encoding_info_alist);
       decode_mac_font_name (name, sizeof (name),
                            XCAR (XCDR (text_encoding_info)));
-      fm_font_family_alist = Fcons (Fcons (build_string (name),
-                                          make_number (ff)),
+      family = build_string (name);
+      if (!NILP (Fassoc (family, fm_font_family_alist)))
+       continue;
+      fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
                                    fm_font_family_alist);
 
       /* Point the instance iterator at the current font family.  */
       if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
-       break;
+       continue;
 
       while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
             == noErr)
@@ -6924,27 +7201,7 @@ init_font_name_table ()
 
          if (size > 0 || style == normal)
            for (; !NILP (rest); rest = XCDR (rest))
-             {
-               char *cs = SDATA (XCAR (rest));
-
-               if (size == 0)
-                 {
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 style, cs));
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 italic, cs));
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 bold, cs));
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 italic | bold,
-                                                                 cs));
-                 }
-               else
-                 {
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 style, cs));
-                 }
-             }
+             add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
        }
     }
 
@@ -6964,7 +7221,7 @@ init_font_name_table ()
   Str255 name;
   struct FontAssoc *fat;
   struct AsscEntry *assc_entry;
-  Lisp_Object text_encoding_info_alist, text_encoding_info;
+  Lisp_Object text_encoding_info_alist, text_encoding_info, family;
   struct gcpro gcpro1;
 
   GetPort (&port);  /* save the current font number used */
@@ -6983,7 +7240,7 @@ init_font_name_table ()
       GetResInfo (font_handle, &id, &type, name);
       GetFNum (name, &fontnum);
       p2cstr (name);
-      if (fontnum == 0)
+      if (fontnum == 0 || *name == '.')
        continue;
 
       TextFont (fontnum);
@@ -6995,8 +7252,10 @@ init_font_name_table ()
                                           text_encoding_info_alist);
       decode_mac_font_name (name, sizeof (name),
                            XCAR (XCDR (text_encoding_info)));
-      fm_font_family_alist = Fcons (Fcons (build_string (name),
-                                          make_number (fontnum)),
+      family = build_string (name);
+      if (!NILP (Fassoc (family, fm_font_family_alist)))
+       continue;
+      fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
                                    fm_font_family_alist);
       do
        {
@@ -7017,14 +7276,9 @@ init_font_name_table ()
                  Lisp_Object rest = XCDR (XCDR (text_encoding_info));
 
                  for (; !NILP (rest); rest = XCDR (rest))
-                   {
-                     char *cs = SDATA (XCAR (rest));
-
-                     add_font_name_table_entry (mac_to_x_fontname (name,
-                                                                   assc_entry->fontSize,
-                                                                   assc_entry->fontStyle,
-                                                                   cs));
-                   }
+                   add_mac_font_name (name, assc_entry->fontSize,
+                                      assc_entry->fontStyle,
+                                      SDATA (XCAR (rest)));
                }
            }
 
@@ -7152,7 +7406,7 @@ mac_do_list_fonts (pattern, maxnames)
       if (xlfdpat_match (pat, font_name_table[i]))
        {
          font_list = Fcons (build_string (font_name_table[i]), font_list);
-         if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+         if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
            break;
        }
       else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
@@ -7161,8 +7415,6 @@ mac_do_list_fonts (pattern, maxnames)
          int former_len = ptr - font_name_table[i];
 
          scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
-         if (scaled == NULL)
-           continue;
          memcpy (scaled, font_name_table[i], former_len);
          sprintf (scaled + former_len,
                   "-%d-%d-72-72-m-%d-%s",
@@ -7175,7 +7427,7 @@ mac_do_list_fonts (pattern, maxnames)
            {
              font_list = Fcons (build_string (scaled), font_list);
              xfree (scaled);
-             if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+             if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
                  break;
            }
          else
@@ -7371,7 +7623,7 @@ is_fully_specified_xlfd (char *p)
 static MacFontStruct *
 XLoadQueryFont (Display *dpy, char *fontname)
 {
-  int i, size, char_width;
+  int size;
   char *name;
   Str255 family;
   Str31 charset;
@@ -7388,6 +7640,7 @@ XLoadQueryFont (Display *dpy, char *fontname)
   short scriptcode;
 #endif
   MacFontStruct *font;
+  XCharStruct *space_bounds = NULL, *pcm;
 
   if (is_fully_specified_xlfd (fontname))
     name = fontname;
@@ -7416,8 +7669,10 @@ XLoadQueryFont (Display *dpy, char *fontname)
       static Boolean bold_p, italic_p;
       ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
                                        &bold_p, &italic_p};
-      ATSUFontFeatureType types[] = {kAllTypographicFeaturesType};
-      ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector};
+      ATSUFontFeatureType types[] = {kAllTypographicFeaturesType,
+                                    kDiacriticsType};
+      ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector,
+                                            kDecomposeDiacriticsSelector};
       Lisp_Object font_id_cons;
 
       font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
@@ -7484,19 +7739,17 @@ XLoadQueryFont (Display *dpy, char *fontname)
   if (font->mac_style)
     {
       OSErr err;
-      ATSUTextLayout text_layout;
-      UniChar c = 0x20;
-      Rect char_bounds, min_bounds, max_bounds;
-      int min_width, max_width;
-      ATSTrapezoid glyph_bounds;
+      UniChar c;
 
-      font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000);
-      if (font->per_char == NULL)
-       {
-         mac_unload_font (&one_mac_display_info, font);
-         return NULL;
-       }
-      bzero (font->per_char, sizeof (XCharStruct) * 0x10000);
+      font->min_byte1 = 0;
+      font->max_byte1 = 0xff;
+      font->min_char_or_byte2 = 0;
+      font->max_char_or_byte2 = 0xff;
+
+      font->bounds.rows = xmalloc (sizeof (XCharStructRow *) * 0x100);
+      bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100);
+      font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow));
+      bzero (font->bounds.rows[0], sizeof (XCharStructRow));
 
 #if USE_CG_TEXT_DRAWING
       {
@@ -7517,112 +7770,63 @@ XLoadQueryFont (Display *dpy, char *fontname)
       }
 
       if (font->cg_font)
-       font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
-      if (font->cg_glyphs)
-       bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
+       {
+         font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
+         bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
+       }
 #endif
-
-      err = atsu_get_text_layout_with_text_ptr (&c, 1,
-                                               font->mac_style,
-                                               &text_layout);
+      space_bounds = font->bounds.rows[0]->per_char + 0x20;
+      err = mac_query_char_extents (font->mac_style, 0x20,
+                                   &font->ascent, &font->descent,
+                                   space_bounds,
+#if USE_CG_TEXT_DRAWING
+                                   (font->cg_glyphs ? font->cg_glyphs + 0x20
+                                    : NULL)
+#else
+                                   NULL
+#endif
+                                   );
       if (err != noErr)
        {
          mac_unload_font (&one_mac_display_info, font);
          return NULL;
        }
+      XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], 0x20);
 
-      for (c = 0x20; c <= 0xff; c++)
+      pcm = font->bounds.rows[0]->per_char;
+      for (c = 0x21; c <= 0xff; c++)
        {
          if (c == 0xad)
            /* Soft hyphen is not supported in ATSUI.  */
            continue;
          else if (c == 0x7f)
            {
-             STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
-             STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
              c = 0x9f;
              continue;
            }
 
-         err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning);
-         if (err == noErr)
-           err = ATSUMeasureTextImage (text_layout,
-                                       kATSUFromTextBeginning, kATSUToTextEnd,
-                                       0, 0, &char_bounds);
-         if (err == noErr)
-           err = ATSUGetGlyphBounds (text_layout, 0, 0,
-                                     kATSUFromTextBeginning, kATSUToTextEnd,
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-                                     kATSUseFractionalOrigins,
+         mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
+#if USE_CG_TEXT_DRAWING
+                                 (font->cg_glyphs ? font->cg_glyphs + c
+                                  : NULL)
 #else
-                                     kATSUseDeviceOrigins,
+                                   NULL
 #endif
-                                     1, &glyph_bounds, NULL);
-         if (err == noErr)
-           {
-             xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
-                      == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
+                                 );
+         XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], c);
 
-             char_width = Fix2Long (glyph_bounds.upperRight.x
-                                    - glyph_bounds.upperLeft.x);
-             STORE_XCHARSTRUCT (font->per_char[c],
-                                char_width, char_bounds);
-             if (c == 0x20)
-               {
-                 min_width = max_width = char_width;
-                 min_bounds = max_bounds = char_bounds;
-                 font->ascent = -Fix2Long (glyph_bounds.upperLeft.y);
-                 font->descent = Fix2Long (glyph_bounds.lowerLeft.y);
-               }
-             else
-               {
-                 if (char_width > 0)
-                   {
-                     min_width = min (min_width, char_width);
-                     max_width = max (max_width, char_width);
-                   }
-                 if (!EmptyRect (&char_bounds))
-                   {
-                     SetRect (&min_bounds,
-                              max (min_bounds.left, char_bounds.left),
-                              max (min_bounds.top, char_bounds.top),
-                              min (min_bounds.right, char_bounds.right),
-                              min (min_bounds.bottom, char_bounds.bottom));
-                     UnionRect (&max_bounds, &char_bounds, &max_bounds);
-                   }
-               }
-           }
 #if USE_CG_TEXT_DRAWING
-         if (err == noErr && char_width > 0 && font->cg_font)
+         if (font->cg_glyphs && font->cg_glyphs[c] == 0)
            {
-             ATSUGlyphInfoArray glyph_info_array;
-             ByteCount count = sizeof (ATSUGlyphInfoArray);
-
-             err = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
-                                         kATSUToTextEnd, NULL, NULL, NULL);
-             if (err == noErr)
-               err = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
-                                       kATSUToTextEnd, &count,
-                                       &glyph_info_array);
-             if (err == noErr)
-               font->cg_glyphs[c] = glyph_info_array.glyphs[0].glyphID;
-             else
-               {
-                 /* Don't use CG text drawing if font substitution
-                    occurs in ASCII or Latin-1 characters.  */
-                 CGFontRelease (font->cg_font);
-                 font->cg_font = NULL;
-                 xfree (font->cg_glyphs);
-                 font->cg_glyphs = NULL;
-               }
+             /* Don't use CG text drawing if font substitution occurs in
+                ASCII or Latin-1 characters.  */
+             CGFontRelease (font->cg_font);
+             font->cg_font = NULL;
+             xfree (font->cg_glyphs);
+             font->cg_glyphs = NULL;
            }
 #endif
        }
-
-      font->min_byte1 = 0;
-      font->max_byte1 = 0xff;
-      font->min_char_or_byte2 = 0;
-      font->max_char_or_byte2 = 0xff;
     }
   else
 #endif
@@ -7661,6 +7865,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
 
       if (is_two_byte_font)
        {
+         int char_width;
+
          font->min_byte1 = 0xa1;
          font->max_byte1 = 0xfe;
          font->min_char_or_byte2 = 0xa1;
@@ -7689,21 +7895,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
              char_width = StringWidth("\p\xa1\xa1");
              break;
            }
-       }
-      else
-       {
-         font->min_byte1 = font->max_byte1 = 0;
-         font->min_char_or_byte2 = 0x20;
-         font->max_char_or_byte2 = 0xff;
-
-         /* Do this instead of use the_fontinfo.widMax, which
-            incorrectly returns 15 for 12-point Monaco! */
-         char_width = CharWidth ('m');
-       }
 
-      if (is_two_byte_font)
-       {
-         font->per_char = NULL;
+         font->bounds.per_char = NULL;
 
          if (fontface & italic)
            font->max_bounds.rbearing = char_width + 1;
@@ -7718,54 +7911,23 @@ XLoadQueryFont (Display *dpy, char *fontname)
        }
       else
        {
-         int c, min_width, max_width;
-         Rect char_bounds, min_bounds, max_bounds;
-         char ch;
+         int c;
 
-         font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
-         bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1));
+         font->min_byte1 = font->max_byte1 = 0;
+         font->min_char_or_byte2 = 0x20;
+         font->max_char_or_byte2 = 0xff;
 
-         min_width = max_width = char_width;
-         SetRect (&min_bounds, -32767, -32767, 32767, 32767);
-         SetRect (&max_bounds, 0, 0, 0, 0);
-         for (c = 0x20; c <= 0xff; c++)
-           {
-             if (c == 0x7f)
-               {
-                 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
-                 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
-                 continue;
-               }
+         font->bounds.per_char =
+           xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
+         bzero (font->bounds.per_char,
+                sizeof (XCharStruct) * (0xff - 0x20 + 1));
 
-             ch = c;
-             char_width = CharWidth (ch);
-             QDTextBounds (1, &ch, &char_bounds);
-             STORE_XCHARSTRUCT (font->per_char[c - 0x20],
-                                char_width, char_bounds);
-             /* Some Japanese fonts (in SJIS encoding) return 0 as
-                the character width of 0x7f.  */
-             if (char_width > 0)
-               {
-                 min_width = min (min_width, char_width);
-                 max_width = max (max_width, char_width);
-               }
-             if (!EmptyRect (&char_bounds))
-               {
-                 SetRect (&min_bounds,
-                          max (min_bounds.left, char_bounds.left),
-                          max (min_bounds.top, char_bounds.top),
-                          min (min_bounds.right, char_bounds.right),
-                          min (min_bounds.bottom, char_bounds.bottom));
-                 UnionRect (&max_bounds, &char_bounds, &max_bounds);
-               }
-           }
-         if (min_width == max_width
-             && max_bounds.left >= 0 && max_bounds.right <= max_width)
-           {
-             /* Fixed width and no overhangs.  */
-             xfree (font->per_char);
-             font->per_char = NULL;
-           }
+         space_bounds = font->bounds.per_char;
+         mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
+                                 space_bounds, NULL);
+
+         for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
+           mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
        }
 
       /* Restore previous font number, size and face.  */
@@ -7774,12 +7936,56 @@ XLoadQueryFont (Display *dpy, char *fontname)
       TextFace (old_fontface);
     }
 
+  if (space_bounds)
+    {
+      int c;
+
+      font->min_bounds = font->max_bounds = *space_bounds;
+      for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
+       if (pcm->width > 0)
+         {
+           font->min_bounds.lbearing = min (font->min_bounds.lbearing,
+                                            pcm->lbearing);
+           font->min_bounds.rbearing = min (font->min_bounds.rbearing,
+                                            pcm->rbearing);
+           font->min_bounds.width    = min (font->min_bounds.width,
+                                            pcm->width);
+           font->min_bounds.ascent   = min (font->min_bounds.ascent,
+                                            pcm->ascent);
+
+           font->max_bounds.lbearing = max (font->max_bounds.lbearing,
+                                            pcm->lbearing);
+           font->max_bounds.rbearing = max (font->max_bounds.rbearing,
+                                            pcm->rbearing);
+           font->max_bounds.width    = max (font->max_bounds.width,
+                                            pcm->width);
+           font->max_bounds.ascent   = max (font->max_bounds.ascent,
+                                            pcm->ascent);
+         }
+      if (
+#if USE_ATSUI
+         font->mac_style == NULL &&
+#endif
+         font->max_bounds.width == font->min_bounds.width
+         && font->min_bounds.lbearing >= 0
+         && font->max_bounds.rbearing <= font->max_bounds.width)
+       {
+         /* Fixed width and no overhangs.  */
+         xfree (font->bounds.per_char);
+         font->bounds.per_char = NULL;
+       }
+    }
+
 #if !defined (MAC_OS8) || USE_ATSUI
   /* AppKit and WebKit do some adjustment to the heights of Courier,
      Helvetica, and Times.  This only works on the environments where
-     the XDrawImageString counterpart is never used.  */
-  if (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
-      || strcmp (family, "times") == 0)
+     srcCopy text transfer mode is never used.  */
+  if (
+#ifdef MAC_OS8                 /* implies USE_ATSUI */
+      font->mac_style &&
+#endif
+      (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
+       || strcmp (family, "times") == 0))
     font->ascent += (font->ascent + font->descent) * .15 + 0.5;
 #endif
 
@@ -7793,17 +7999,26 @@ mac_unload_font (dpyinfo, font)
      XFontStruct *font;
 {
   xfree (font->full_name);
-  if (font->per_char)
-    xfree (font->per_char);
 #if USE_ATSUI
   if (font->mac_style)
-    ATSUDisposeStyle (font->mac_style);
+    {
+      int i;
+
+      for (i = font->min_byte1; i <= font->max_byte1; i++)
+       if (font->bounds.rows[i])
+         xfree (font->bounds.rows[i]);
+      xfree (font->bounds.rows);
+      ATSUDisposeStyle (font->mac_style);
+    }
+  else
+#endif
+    if (font->bounds.per_char)
+      xfree (font->bounds.per_char);
 #if USE_CG_TEXT_DRAWING
   if (font->cg_font)
     CGFontRelease (font->cg_font);
   if (font->cg_glyphs)
     xfree (font->cg_glyphs);
-#endif
 #endif
   xfree (font);
 }
@@ -7847,10 +8062,8 @@ x_load_font (f, fontname, size)
 
   /* Load the font and add it to the table.  */
   {
-    char *full_name;
     struct MacFontStruct *font;
     struct font_info *fontp;
-    unsigned long value;
     int i;
 
     fontname = (char *) SDATA (XCAR (font_names));
@@ -8109,17 +8322,17 @@ Lisp_Object Vmac_function_modifier;
 Lisp_Object Vmac_emulate_three_button_mouse;
 
 #if USE_CARBON_EVENTS
-/* True if the mouse wheel button (i.e. button 4) should map to
+/* Non-zero if the mouse wheel button (i.e. button 4) should map to
    mouse-2, instead of mouse-3.  */
-Lisp_Object Vmac_wheel_button_is_mouse_2;
+int mac_wheel_button_is_mouse_2;
 
-/* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
+/* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
    for processing before Emacs sees it.  */
-Lisp_Object Vmac_pass_command_to_system;
+int mac_pass_command_to_system;
 
-/* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
+/* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
    for processing before Emacs sees it.  */
-Lisp_Object Vmac_pass_control_to_system;
+int mac_pass_control_to_system;
 #endif
 
 /* Points to the variable `inev' in the function XTread_socket.  It is
@@ -8127,20 +8340,19 @@ Lisp_Object Vmac_pass_control_to_system;
    Carbon/Apple event handlers.  */
 static struct input_event *read_socket_inev = NULL;
 
-/* Set in term/mac-win.el to indicate that event loop can now generate
-   drag and drop events.  */
-Lisp_Object Qmac_ready_for_drag_n_drop;
-
 Point saved_menu_event_location;
 
 /* Apple Events */
-static void init_required_apple_events (void);
-static pascal OSErr
-do_ae_open_application (const AppleEvent *, AppleEvent *, long);
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
+#if USE_CARBON_EVENTS
+static Lisp_Object Qhicommand;
+#endif
+extern int mac_ready_for_apple_events;
+extern Lisp_Object Qundefined;
+extern void init_apple_event_handler P_ ((void));
+extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
+                                          Lisp_Object *, Lisp_Object *,
+                                          Lisp_Object *));
+extern OSErr init_coercion_handler P_ ((void));
 
 #if TARGET_API_MAC_CARBON
 /* Drag and Drop */
@@ -8150,11 +8362,10 @@ static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL;
 static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
 #endif
 
-static Lisp_Object Qapplication, Qabout;
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
 extern void init_service_handler ();
-static Lisp_Object Qpreferences, Qservices, Qpaste, Qperform;
+static Lisp_Object Qservices, Qpaste, Qperform;
 #endif
 /* Window Event Handler */
 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
@@ -8179,8 +8390,6 @@ mac_to_emacs_modifiers (EventModifiers mods)
   if (mods & shiftKey)
     result |= shift_modifier;
 
-
-
   /* Deactivated to simplify configuration:
      if Vmac_option_modifier is non-NIL, we fully process the Option
      key. Otherwise, we only process it if an additional Ctrl or Command
@@ -8268,10 +8477,10 @@ mac_get_mouse_btn (EventRef ref)
        return mac_get_emulated_btn(mods);
       }
     case kEventMouseButtonSecondary:
-      return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
+      return mac_wheel_button_is_mouse_2 ? 2 : 1;
     case kEventMouseButtonTertiary:
     case 4:  /* 4 is the number for the mouse wheel button */
-      return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
+      return mac_wheel_button_is_mouse_2 ? 1 : 2;
     default:
       return 0;
     }
@@ -8286,6 +8495,7 @@ mac_get_mouse_btn (EventRef ref)
    XTread_socket loop).  */
 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
 {
+  OSStatus err;
   Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
 
   if (result)
@@ -8319,13 +8529,19 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
            unsigned char char_codes;
            UInt32 key_code;
 
-           eventRec->what = keyDown;
-           GetEventParameter (eventRef, kEventParamKeyMacCharCodes, typeChar,
-                              NULL, sizeof (char), NULL, &char_codes);
-           GetEventParameter (eventRef, kEventParamKeyCode, typeUInt32,
-                              NULL, sizeof (UInt32), NULL, &key_code);
-           eventRec->message = char_codes | ((key_code & 0xff) << 8);
-           result = 1;
+           err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
+                                    typeChar, NULL, sizeof (char),
+                                    NULL, &char_codes);
+           if (err == noErr)
+             err = GetEventParameter (eventRef, kEventParamKeyCode,
+                                      typeUInt32, NULL, sizeof (UInt32),
+                                      NULL, &key_code);
+           if (err == noErr)
+             {
+               eventRec->what = keyDown;
+               eventRec->message = char_codes | ((key_code & 0xff) << 8);
+               result = 1;
+             }
          }
          break;
 
@@ -8341,7 +8557,7 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
   if (result)
     {
       /* Need where and when.  */
-      UInt32 mods;
+      UInt32 mods = 0;
 
       GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
                         NULL, sizeof (Point), NULL, &eventRec->where);
@@ -8359,6 +8575,7 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
 
 #endif
 
+#ifdef MAC_OS8
 static void
 do_get_menus (void)
 {
@@ -8420,6 +8637,7 @@ do_check_ram_size (void)
       exit (1);
     }
 }
+#endif /* MAC_OS8 */
 
 static void
 do_window_update (WindowPtr win)
@@ -8601,42 +8819,41 @@ do_grow_window (WindowPtr w, EventRecord *e)
 static void
 do_zoom_window (WindowPtr w, int zoom_in_or_out)
 {
-  GrafPtr save_port;
   Rect zoom_rect, port_rect;
-  Point top_left;
-  int w_title_height, columns, rows, width, height;
+  int columns, rows, width, height;
   struct frame *f = mac_window_to_frame (w);
   struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
 #if TARGET_API_MAC_CARBON
-  {
-    Point standard_size;
+  Point standard_size;
 
-    standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-    standard_size.v = dpyinfo->height;
+  standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+  standard_size.v = dpyinfo->height;
 
-    if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
-      zoom_in_or_out = inZoomIn;
-    else
-      {
-       /* Adjust the standard size according to character boundaries.  */
-
-       columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
-       rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
-       standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
-       standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
-       GetWindowBounds (w, kWindowContentRgn, &port_rect);
-       if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
-           && port_rect.left == zoom_rect.left
-           && port_rect.top == zoom_rect.top)
-         zoom_in_or_out = inZoomIn;
-       else
-         zoom_in_or_out = inZoomOut;
-      }
+  if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
+    zoom_in_or_out = inZoomIn;
+  else
+    {
+      /* Adjust the standard size according to character boundaries.  */
 
-    ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
-  }
+      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
+      standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
+      standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+      GetWindowBounds (w, kWindowContentRgn, &port_rect);
+      if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
+         && port_rect.left == zoom_rect.left
+         && port_rect.top == zoom_rect.top)
+       zoom_in_or_out = inZoomIn;
+      else
+       zoom_in_or_out = inZoomOut;
+    }
+
+  ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
 #else /* not TARGET_API_MAC_CARBON */
+  GrafPtr save_port;
+  Point top_left;
+  int w_title_height;
+
   GetPort (&save_port);
 
   SetPortWindowPort (w);
@@ -8672,206 +8889,73 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
 
   SetPort (save_port);
-#endif /* not TARGET_API_MAC_CARBON */
-
-  /* retrieve window size and update application values */
-#if TARGET_API_MAC_CARBON
-  GetWindowPortBounds (w, &port_rect);
-#else
-  port_rect = w->portRect;
-#endif
-  height = port_rect.bottom - port_rect.top;
-  width = port_rect.right - port_rect.left;
-
-  if (width != FRAME_PIXEL_WIDTH (f)
-      || height != FRAME_PIXEL_HEIGHT (f))
-    {
-      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
-      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
-
-      change_frame_size (f, rows, columns, 0, 1, 0);
-      SET_FRAME_GARBAGED (f);
-      cancel_mouse_face (f);
-
-      FRAME_PIXEL_WIDTH (f) = width;
-      FRAME_PIXEL_HEIGHT (f) = height;
-    }
-  x_real_positions (f, &f->left_pos, &f->top_pos);
-}
-
-/* Intialize AppleEvent dispatcher table for the required events.  */
-void
-init_required_apple_events ()
-{
-  OSErr err;
-  long result;
-
-  /* Make sure we have apple events before starting.  */
-  err = Gestalt (gestaltAppleEventsAttr, &result);
-  if (err != noErr)
-    abort ();
-
-  if (!(result & (1 << gestaltAppleEventsPresent)))
-    abort ();
-
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
-                             NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_open_application),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
-                             NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_open_application),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
+#endif /* not TARGET_API_MAC_CARBON */
 
+  /* retrieve window size and update application values */
 #if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
-                              NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_open_documents),
-                              0L, false);
+  GetWindowPortBounds (w, &port_rect);
 #else
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
-                              NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_open_documents),
-                              0L, false);
+  port_rect = w->portRect;
 #endif
-  if (err != noErr)
-    abort ();
+  height = port_rect.bottom - port_rect.top;
+  width = port_rect.right - port_rect.left;
 
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
-                              NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_print_documents),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
-                              NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_print_documents),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
+  if (width != FRAME_PIXEL_WIDTH (f)
+      || height != FRAME_PIXEL_HEIGHT (f))
+    {
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
+      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
 
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
-                              NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_quit_application),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
-                              NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_quit_application),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
+      change_frame_size (f, rows, columns, 0, 1, 0);
+      SET_FRAME_GARBAGED (f);
+      cancel_mouse_face (f);
+
+      FRAME_PIXEL_WIDTH (f) = width;
+      FRAME_PIXEL_HEIGHT (f) = height;
+    }
+  x_real_positions (f, &f->left_pos, &f->top_pos);
 }
 
-void
-mac_store_application_menu_event (event)
-#if USE_CARBON_EVENTS
-     EventRef event;
-#else
-     UInt32 event;
-#endif
+OSErr
+mac_store_apple_event (class, id, desc)
+     Lisp_Object class, id;
+     const AEDesc *desc;
 {
+  OSErr err;
   struct input_event buf;
-  Lisp_Object frame, entry;
-
-  EVENT_INIT (buf);
-
-  XSETFRAME (frame, mac_focus_frame (&one_mac_display_info));
-  buf.kind = MENU_BAR_EVENT;
-  buf.frame_or_window = frame;
-  buf.arg = frame;
-  kbd_buffer_store_event (&buf);
+  AEDesc *desc_copy;
 
-  buf.arg = Qapplication;
-  kbd_buffer_store_event (&buf);
-
-#if USE_CARBON_EVENTS
-  switch (GetEventClass (event))
+  desc_copy = xmalloc (sizeof (AEDesc));
+  err = AEDuplicateDesc (desc, desc_copy);
+  if (err == noErr)
     {
-#ifdef MAC_OSX
-    case kEventClassService:
-      buf.arg = Qservices;
-      kbd_buffer_store_event (&buf);
-      switch (GetEventKind (event))
-       {
-       case kEventServicePaste:
-         entry = Qpaste;
-         break;
+      EVENT_INIT (buf);
 
-       case kEventServicePerform:
-         {
-           OSErr err;
-           CFStringRef message;
-
-           err = GetEventParameter (event, kEventParamServiceMessageName,
-                                    typeCFStringRef, NULL,
-                                    sizeof (CFStringRef), NULL, &message);
-           buf.arg = Qperform;
-           kbd_buffer_store_event (&buf);
-           if (err == noErr && message)
-             entry = intern (SDATA (cfstring_to_lisp (message)));
-           else
-             entry = Qnil;
-         }
-         break;
+      buf.kind = MAC_APPLE_EVENT;
+      buf.x = class;
+      buf.y = id;
+      buf.code = (int)desc_copy;
+      XSETFRAME (buf.frame_or_window,
+                mac_focus_frame (&one_mac_display_info));
+      buf.arg = Qnil;
+      kbd_buffer_store_event (&buf);
+    }
 
-       default:
-         abort ();
-       }
-      break;
-#endif /* MAC_OSX */
-    case kEventClassCommand:
-      {
-       HICommand command;
+  return err;
+}
 
-       GetEventParameter(event, kEventParamDirectObject, typeHICommand,
-                         NULL, sizeof (HICommand), NULL, &command);
-       switch (command.commandID)
-         {
-         case kHICommandAbout:
-           entry = Qabout;
-           break;
-#ifdef MAC_OSX
-         case kHICommandPreferences:
-           entry = Qpreferences;
-           break;
-#endif /* MAC_OSX */
-         case kHICommandQuit:
-           entry = Qquit;
-           break;
-         default:
-           abort ();
-         }
-      }
-      break;
+Lisp_Object
+mac_make_lispy_event_code (code)
+     int code;
+{
+  AEDesc *desc = (AEDesc *)code;
+  Lisp_Object obj;
 
-    default:
-      abort ();
-    }
-#else  /* USE_CARBON_EVENTS */
-  switch (event)
-    {
-    case kHICommandAbout:
-      entry = Qabout;
-      break;
-    case kHICommandQuit:
-      entry = Qquit;
-      break;
-    default:
-      abort ();
-    }
-#endif
+  obj = mac_aedesc_to_lisp (desc);
+  AEDisposeDesc (desc);
+  xfree (desc);
 
-  buf.arg = entry;
-  kbd_buffer_store_event (&buf);
+  return obj;
 }
 
 #if USE_CARBON_EVENTS
@@ -8881,27 +8965,46 @@ mac_handle_command_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
+  OSStatus result, err;
   HICommand command;
-  OSErr result;
+  Lisp_Object class_key, id_key, binding;
 
-  GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL,
-                   sizeof (HICommand), NULL, &command);
+  result = CallNextEventHandler (next_handler, event);
+  if (result != eventNotHandledErr)
+    return result;
 
-  switch (command.commandID)
-    {
-    case kHICommandAbout:
-#ifdef MAC_OSX
-    case kHICommandPreferences:
-#endif /* MAC_OSX */
-      result = CallNextEventHandler (next_handler, event);
-      if (result != eventNotHandledErr)
-       return result;
+  err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
+                          NULL, sizeof (HICommand), NULL, &command);
 
-      mac_store_application_menu_event (event);
-      return noErr;
+  if (err != noErr || command.commandID == 0)
+    return eventNotHandledErr;
 
-    default:
-      break;
+  /* A HICommand event is mapped to an Apple event whose event class
+     symbol is `hicommand' and event ID is its command ID.  */
+  class_key = Qhicommand;
+  mac_find_apple_event_spec (0, command.commandID,
+                            &class_key, &id_key, &binding);
+  if (!NILP (binding) && !EQ (binding, Qundefined))
+    {
+      if (INTEGERP (binding))
+       return XINT (binding);
+      else
+       {
+         AppleEvent apple_event;
+         static EventParamName names[] = {kEventParamDirectObject,
+                                          kEventParamKeyModifiers};
+         static EventParamType types[] = {typeHICommand,
+                                          typeUInt32};
+         err = create_apple_event_from_event_ref (event, 2, names, types,
+                                                  &apple_event);
+         if (err == noErr)
+           {
+             err = mac_store_apple_event (class_key, id_key, &apple_event);
+             AEDisposeDesc (&apple_event);
+           }
+         if (err == noErr)
+           return noErr;
+       }
     }
 
   return eventNotHandledErr;
@@ -8910,7 +9013,6 @@ mac_handle_command_event (next_handler, event, data)
 static OSErr
 init_command_handler ()
 {
-  OSErr err = noErr;
   EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
   static EventHandlerUPP handle_command_eventUPP = NULL;
 
@@ -8928,12 +9030,14 @@ mac_handle_window_event (next_handler, event, data)
      void *data;
 {
   WindowPtr wp;
-  OSStatus result;
+  OSStatus result, err;
   UInt32 attributes;
   XSizeHints *size_hints;
 
-  GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
-                    NULL, sizeof (WindowPtr), NULL, &wp);
+  err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
+                          NULL, sizeof (WindowPtr), NULL, &wp);
+  if (err != noErr)
+    return eventNotHandledErr;
 
   switch (GetEventKind (event))
     {
@@ -8950,8 +9054,11 @@ mac_handle_window_event (next_handler, event, data)
       if (result != eventNotHandledErr)
        return result;
 
-      GetEventParameter (event, kEventParamAttributes, typeUInt32,
-                        NULL, sizeof (UInt32), NULL, &attributes);
+      err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
+                              NULL, sizeof (UInt32), NULL, &attributes);
+      if (err != noErr)
+       break;
+
       size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
       if ((attributes & kWindowBoundsChangeUserResize)
          && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
@@ -8960,9 +9067,12 @@ mac_handle_window_event (next_handler, event, data)
          Rect bounds;
          int width, height;
 
-         GetEventParameter (event, kEventParamCurrentBounds,
-                            typeQDRectangle,
-                            NULL, sizeof (Rect), NULL, &bounds);
+         err = GetEventParameter (event, kEventParamCurrentBounds,
+                                  typeQDRectangle, NULL, sizeof (Rect),
+                                  NULL, &bounds);
+         if (err != noErr)
+           break;
+
          width = bounds.right - bounds.left;
          height = bounds.bottom - bounds.top;
 
@@ -9011,7 +9121,7 @@ mac_handle_mouse_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  OSStatus result;
+  OSStatus result, err;
 
   switch (GetEventKind (event))
     {
@@ -9027,22 +9137,31 @@ mac_handle_mouse_event (next_handler, event, data)
        if (result != eventNotHandledErr || read_socket_inev == NULL)
          return result;
 
-       GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
-                          NULL, sizeof (WindowRef), NULL, &wp);
+       err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
+                                NULL, sizeof (WindowRef), NULL, &wp);
+       if (err != noErr)
+         break;
+
        f = mac_window_to_frame (wp);
        if (f != mac_focus_frame (&one_mac_display_info))
          break;
 
-       GetEventParameter (event, kEventParamMouseWheelAxis,
-                          typeMouseWheelAxis, NULL,
-                          sizeof (EventMouseWheelAxis), NULL, &axis);
-       if (axis != kEventMouseWheelAxisY)
+       err = GetEventParameter (event, kEventParamMouseWheelAxis,
+                                typeMouseWheelAxis, NULL,
+                                sizeof (EventMouseWheelAxis), NULL, &axis);
+       if (err != noErr || axis != kEventMouseWheelAxisY)
          break;
 
-       GetEventParameter (event, kEventParamMouseWheelDelta, typeSInt32,
-                          NULL, sizeof (SInt32), NULL, &delta);
-       GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
-                          NULL, sizeof (Point), NULL, &point);
+       err = GetEventParameter (event, kEventParamMouseWheelDelta,
+                                typeSInt32, NULL, sizeof (SInt32),
+                                NULL, &delta);
+       if (err != noErr)
+         break;
+       err = GetEventParameter (event, kEventParamMouseLocation,
+                                typeQDPoint, NULL, sizeof (Point),
+                                NULL, &point);
+       if (err != noErr)
+         break;
        read_socket_inev->kind = WHEEL_EVENT;
        read_socket_inev->code = 0;
        read_socket_inev->modifiers =
@@ -9064,6 +9183,50 @@ mac_handle_mouse_event (next_handler, event, data)
 
   return eventNotHandledErr;
 }
+
+#ifdef MAC_OSX
+OSErr
+mac_store_services_event (event)
+     EventRef event;
+{
+  OSErr err;
+  AppleEvent apple_event;
+  Lisp_Object id_key;
+
+  switch (GetEventKind (event))
+    {
+    case kEventServicePaste:
+      id_key = Qpaste;
+      err = create_apple_event_from_event_ref (event, 0, NULL, NULL,
+                                              &apple_event);
+      break;
+
+    case kEventServicePerform:
+      {
+       static EventParamName names[] = {kEventParamServiceMessageName,
+                                        kEventParamServiceUserData};
+       static EventParamType types[] = {typeCFStringRef,
+                                        typeCFStringRef};
+
+       id_key = Qperform;
+       err = create_apple_event_from_event_ref (event, 2, names, types,
+                                                &apple_event);
+      }
+      break;
+
+    default:
+      abort ();
+    }
+
+  if (err == noErr)
+    {
+      err = mac_store_apple_event (Qservices, id_key, &apple_event);
+      AEDisposeDesc (&apple_event);
+    }
+
+  return err;
+}
+#endif /* MAC_OSX */
 #endif /* USE_CARBON_EVENTS */
 
 
@@ -9122,159 +9285,6 @@ remove_window_handler (window)
 #endif
 }
 
-/* Open Application Apple Event */
-static pascal OSErr
-do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
-{
-  return noErr;
-}
-
-
-/* Called when we receive an AppleEvent with an ID of
-   "kAEOpenDocuments".  This routine gets the direct parameter,
-   extracts the FSSpecs in it, and puts their names on a list.  */
-#pragma options align=mac68k
-typedef struct SelectionRange {
-  short unused1; // 0 (not used)
-  short lineNum; // line to select (<0 to specify range)
-  long startRange; // start of selection range (if line < 0)
-  long endRange; // end of selection range (if line < 0)
-  long unused2; // 0 (not used)
-  long theDate; // modification date/time
-} SelectionRange;
-#pragma options align=reset
-
-static pascal OSErr
-do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
-{
-  OSErr err, err2;
-  AEDesc the_desc;
-  AEKeyword keyword;
-  DescType actual_type;
-  Size actual_size;
-  SelectionRange position;
-  Lisp_Object file_list = Qnil;
-
-  xassert (read_socket_inev);
-
-  err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
-  if (err != noErr)
-    goto descriptor_error_exit;
-
-  err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
-  if (err == noErr)
-    file_list = Fcons (list3 (make_number (position.lineNum + 1),
-                             make_number (position.startRange + 1),
-                             make_number (position.endRange + 1)),
-                      file_list);
-
-  /* Check to see that we got all of the required parameters from the
-     event descriptor.  For an 'odoc' event this should just be the
-     file list.  */
-  err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
-                         &actual_type, (Ptr) &keyword,
-                          sizeof (keyword), &actual_size);
-  /* No error means that we found some unused parameters.
-     errAEDescNotFound means that there are no more parameters.  If we
-     get an error code other than that, flag it.  */
-  if ((err == noErr) || (err != errAEDescNotFound))
-    {
-      err = errAEEventNotHandled;
-      goto error_exit;
-    }
-  err = noErr;
-
-  /* Got all the parameters we need.  Now, go through the direct
-     object list and parse it up.  */
-  {
-    long num_files_to_open;
-
-    err = AECountItems (&the_desc, &num_files_to_open);
-    if (err == noErr)
-      {
-        int i;
-
-        /* AE file list is one based so just use that for indexing here.  */
-        for (i = 1; i <= num_files_to_open; i++)
-         {
-           char unix_path_name[MAXPATHLEN];
-#ifdef MAC_OSX
-           FSRef fref;
-
-           err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
-                              &actual_type, &fref, sizeof (FSRef),
-                              &actual_size);
-           if (err != noErr || actual_type != typeFSRef)
-             continue;
-
-           if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
-               == noErr)
-#else
-           FSSpec fs;
-
-           err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
-                             (Ptr) &fs, sizeof (fs), &actual_size);
-           if (err != noErr) continue;
-
-           if (fsspec_to_posix_pathname (&fs, unix_path_name,
-                                         sizeof (unix_path_name) - 1) == noErr)
-#endif
-             /* x-dnd functions expect undecoded filenames.  */
-             file_list = Fcons (make_unibyte_string (unix_path_name,
-                                                     strlen (unix_path_name)),
-                                file_list);
-         }
-      }
-
-    /* Build a DRAG_N_DROP_EVENT type event as is done in
-       constuct_drag_n_drop in w32term.c.  */
-    if (!NILP (file_list))
-      {
-       struct frame *f = mac_focus_frame (&one_mac_display_info);
-       WindowPtr wp;
-       Lisp_Object frame;
-
-       read_socket_inev->kind = DRAG_N_DROP_EVENT;
-       read_socket_inev->code = 0;
-       read_socket_inev->modifiers = 0;
-
-       XSETINT (read_socket_inev->x, 0);
-       XSETINT (read_socket_inev->y, 0);
-
-       XSETFRAME (frame, f);
-       read_socket_inev->frame_or_window = Fcons (frame, file_list);
-
-#if 0
-       /* Regardless of whether Emacs was suspended or in the
-          foreground, ask it to redraw its entire screen.  Otherwise
-          parts of the screen can be left in an inconsistent
-          state.  */
-       wp = FRAME_MAC_WINDOW (f);
-       if (wp)
-#if TARGET_API_MAC_CARBON
-         {
-           Rect r;
-
-           GetWindowPortBounds (wp, &r);
-           InvalWindowRect (wp, &r);
-         }
-#else /* not TARGET_API_MAC_CARBON */
-       InvalRect (&(wp->portRect));
-#endif /* not TARGET_API_MAC_CARBON */
-#endif
-      }
-  }
-
-error_exit:
-  /* Nuke the coerced file list in any case */
-  err2 = AEDisposeDesc(&the_desc);
-
-descriptor_error_exit:
-  /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
-  return err;
-}
-
-
 #if TARGET_API_MAC_CARBON
 static pascal OSErr
 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
@@ -9370,25 +9380,25 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
       result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
       if (result == noErr)
        {
-#ifdef MAC_OSX
-         FSRef fref;
-#endif
-         char unix_path_name[MAXPATHLEN];
+         OSErr err;
+         AEDesc desc;
 
-         GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
-#ifdef MAC_OSX
-         /* Use Carbon routines, otherwise it converts the file name
-            to /Macintosh HD/..., which is not correct. */
-         FSpMakeFSRef (&data.fileSpec, &fref);
-         if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
-#else
-         if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name,
-                                       sizeof (unix_path_name) - 1) == noErr)
-#endif
-           /* x-dnd functions expect undecoded filenames.  */
-            file_list = Fcons (make_unibyte_string (unix_path_name,
-                                                   strlen (unix_path_name)),
-                              file_list);
+         err = GetFlavorData (theDrag, theItem, flavorTypeHFS,
+                              &data, &size, 0L);
+         if (err == noErr)
+           err = AECoercePtr (typeFSS, &data.fileSpec, sizeof (FSSpec),
+                              TYPE_FILE_NAME, &desc);
+         if (err == noErr)
+           {
+             Lisp_Object file;
+
+             /* x-dnd functions expect undecoded filenames.  */
+             file = make_uninit_string (AEGetDescDataSize (&desc));
+             err = AEGetDescData (&desc, SDATA (file), SBYTES (file));
+             if (err == noErr)
+               file_list = Fcons (file, file_list);
+             AEDisposeDesc (&desc);
+           }
        }
     }
   /* If there are items in the list, construct an event and post it to
@@ -9410,8 +9420,8 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
       XSETINT (event.x, mouse.h);
       XSETINT (event.y, mouse.v);
       XSETFRAME (frame, f);
-      event.frame_or_window = Fcons (frame, file_list);
-      event.arg = Qnil;
+      event.frame_or_window = frame;
+      event.arg = file_list;
       /* Post to the interrupt queue */
       kbd_buffer_store_event (&event);
       /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
@@ -9429,44 +9439,6 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
 #endif
 
 
-/* Print Document Apple Event */
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
-{
-  return errAEEventNotHandled;
-}
-
-
-static pascal OSErr
-do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
-{
-#if USE_CARBON_EVENTS
-  OSErr err;
-  EventRef event = NULL;
-  static const HICommand quit_command = {kEventAttributeNone, kHICommandQuit};
-
-  err = CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 0,
-                    kEventAttributeUserEvent, &event);
-  if (err == noErr)
-    err = SetEventParameter (event, kEventParamDirectObject, typeHICommand,
-                            sizeof (HICommand), &quit_command);
-  if (err == noErr)
-    mac_store_application_menu_event (event);
-  if (event)
-    ReleaseEvent (event);
-
-  if (err == noErr)
-    return noErr;
-  else
-    return errAEEventNotHandled;
-#else
-  mac_store_application_menu_event (kHICommandQuit);
-
-  return noErr;
-#endif
-}
-
-
 #if __profile__
 void
 profiler_exit_proc ()
@@ -9518,9 +9490,11 @@ main (void)
 
   init_environ ();
 
+  init_coercion_handler ();
+
   initialize_applescript ();
 
-  init_required_apple_events ();
+  init_apple_event_handler ();
 
   {
     char **argv;
@@ -9649,13 +9623,13 @@ convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
   Fn modifier. That's why we need the table.
 
   */
-
+  OSStatus err;
   UInt32 mods = 0;
   if (!NILP(Vmac_function_modifier))
     {
-      GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
-                        sizeof (UInt32), NULL, &mods);
-      if (mods & kEventKeyModifierFnMask)
+      err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
+                              NULL, sizeof (UInt32), NULL, &mods);
+      if (err != noErr && mods & kEventKeyModifierFnMask)
        {  *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
 
          return (*newCode != 0);
@@ -9668,10 +9642,12 @@ convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
 static int
 backtranslate_modified_keycode(int mods, int keycode, int def)
 {
-  if  (mods &
-       (controlKey |
-       (NILP (Vmac_option_modifier) ? 0 : optionKey) |
-       cmdKey))
+  EventModifiers mapped_modifiers =
+    (NILP (Vmac_control_modifier) ? 0 : controlKey)
+    | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+    | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+
+  if (mods & mapped_modifiers)
     {
       /* This code comes from Keyboard Resource,
         Appendix C of IM - Text.  This is necessary
@@ -9686,14 +9662,15 @@ backtranslate_modified_keycode(int mods, int keycode, int def)
         to preserve key combinations translated by the OS
         such as Alt-3.
       */
-      /* mask off option and command */
-      int new_modifiers = mods & 0xe600;
+      /* Mask off modifier keys that are mapped to some Emacs
+        modifiers.  */
+      int new_modifiers = mods & ~mapped_modifiers;
       /* set high byte of keycode to modifier high byte*/
       int new_keycode = keycode | new_modifiers;
       Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
       unsigned long some_state = 0;
       return (int) KeyTranslate (kchr_ptr, new_keycode,
-                          &some_state) & 0xff;
+                                &some_state) & 0xff;
       /* TO DO: Recognize two separate resulting characters, "for
         example, when the user presses Option-E followed by N, you
         can map this through the KeyTranslate function using the
@@ -9724,7 +9701,7 @@ mac_wait_next_event (er, sleep_time, dequeue)
     mouse_region = NewRgn ();
 
   event_mask = everyEvent;
-  if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
+  if (!mac_ready_for_apple_events)
     event_mask -= highLevelEventMask;
 
   current_tick = TickCount ();
@@ -9774,10 +9751,16 @@ XTread_socket (sd, expected, hold_quit)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
+  ++handling_signal;
+
 #if USE_CARBON_EVENTS
   toolbox_dispatcher = GetEventDispatcherTarget ();
 
-  while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
+  while (
+#if USE_CG_DRAWING
+        mac_prepare_for_quickdraw (NULL),
+#endif
+        !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
                            kEventRemoveFromQueue, &eventRef))
 #else /* !USE_CARBON_EVENTS */
   while (mac_wait_next_event (&er, 0, true))
@@ -9905,18 +9888,18 @@ XTread_socket (sd, expected, hold_quit)
                    XSETINT (inev.x, mouse_loc.h);
                    XSETINT (inev.y, mouse_loc.v);
 
-                   if (dpyinfo->grabbed && tracked_scroll_bar
-                       || ch != 0
+                   if ((dpyinfo->grabbed && tracked_scroll_bar)
+                       || (ch != 0
 #ifndef USE_TOOLKIT_SCROLL_BARS
-                       /* control_part_code becomes kControlNoPart if
-                          a progress indicator is clicked.  */
-                       && control_part_code != kControlNoPart
+                           /* control_part_code becomes kControlNoPart if
+                              a progress indicator is clicked.  */
+                           && control_part_code != kControlNoPart
 #else  /* USE_TOOLKIT_SCROLL_BARS */
 #ifdef MAC_OSX
-                       && control_kind.kind == kControlKindScrollBar
+                           && control_kind.kind == kControlKindScrollBar
 #endif /* MAC_OSX */
 #endif /* USE_TOOLKIT_SCROLL_BARS */
-                       )
+                           ))
                      {
                        struct scroll_bar *bar;
 
@@ -10247,9 +10230,9 @@ XTread_socket (sd, expected, hold_quit)
               will pass back noErr, otherwise it will pass back
               "eventNotHandledErr" and we can process it
               normally.  */
-           if ((!NILP (Vmac_pass_command_to_system)
+           if ((mac_pass_command_to_system
                 || !(er.modifiers & cmdKey))
-               && (!NILP (Vmac_pass_control_to_system)
+               && (mac_pass_control_to_system
                    || !(er.modifiers & controlKey))
                && (NILP (Vmac_option_modifier)
                    || !(er.modifiers & optionKey)))
@@ -10289,7 +10272,10 @@ XTread_socket (sd, expected, hold_quit)
 
            ObscureCursor ();
 
-           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+           f = mac_focus_frame (dpyinfo);
+
+           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+               && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
              {
                clear_mouse_face (dpyinfo);
                dpyinfo->mouse_face_hidden = 1;
@@ -10318,12 +10304,10 @@ XTread_socket (sd, expected, hold_quit)
                }
              else
                {
-
                  inev.code =
                    backtranslate_modified_keycode(er.modifiers, keycode,
                                                   er.message & charCodeMask);
                  inev.kind = ASCII_KEYSTROKE_EVENT;
-
                }
          }
 
@@ -10335,7 +10319,7 @@ XTread_socket (sd, expected, hold_quit)
          inev.modifiers |= (extra_keyboard_modifiers
                             & (meta_modifier | alt_modifier
                                | hyper_modifier | super_modifier));
-         XSETFRAME (inev.frame_or_window, mac_focus_frame (dpyinfo));
+         XSETFRAME (inev.frame_or_window, f);
          break;
 
        case kHighLevelEvent:
@@ -10416,6 +10400,7 @@ XTread_socket (sd, expected, hold_quit)
   }
 #endif
 
+  --handling_signal;
   UNBLOCK_INPUT;
   return count;
 }
@@ -10714,7 +10699,6 @@ mac_check_bundle()
   extern int inhibit_window_system;
   extern int noninteractive;
   CFBundleRef appsBundle;
-  pid_t child;
 
   /* No need to test if already -nw*/
   if (inhibit_window_system || noninteractive)
@@ -10836,8 +10820,13 @@ static struct redisplay_interface x_redisplay_interface =
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
   x_draw_fringe_bitmap,
+#if USE_CG_DRAWING
+  mac_define_fringe_bitmap,
+  mac_destroy_fringe_bitmap,
+#else
   0, /* define_fringe_bitmap */
   0, /* destroy_fringe_bitmap */
+#endif
   mac_per_char_metric,
   mac_encode_char,
   mac_compute_glyph_string_overhangs,
@@ -10891,7 +10880,6 @@ mac_initialize ()
   BLOCK_INPUT;
 
 #if TARGET_API_MAC_CARBON
-  init_required_apple_events ();
 
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
@@ -10906,10 +10894,19 @@ mac_initialize ()
 #endif /* USE_CARBON_EVENTS */
 
 #ifdef MAC_OSX
+  init_coercion_handler ();
+
+  init_apple_event_handler ();
+
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
 #endif
+
+#if USE_CG_DRAWING
+  mac_init_fringe ();
+#endif
+
   UNBLOCK_INPUT;
 }
 
@@ -10922,27 +10919,28 @@ syms_of_macterm ()
   x_error_message_string = Qnil;
 #endif
 
+  Qcontrol = intern ("control");       staticpro (&Qcontrol);
+  Qmeta    = intern ("meta");          staticpro (&Qmeta);
+  Qalt     = intern ("alt");           staticpro (&Qalt);
+  Qhyper   = intern ("hyper");         staticpro (&Qhyper);
+  Qsuper   = intern ("super");         staticpro (&Qsuper);
   Qmodifier_value = intern ("modifier-value");
-  Qctrl = intern ("ctrl");
-  Fput (Qctrl, Qmodifier_value, make_number (ctrl_modifier));
-  Qmeta = intern ("meta");
-  Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
-  Qalt = intern ("alt");
-  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
-  Qhyper = intern ("hyper");
-  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
-  Qsuper = intern ("super");
-  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
-
-  Qapplication = intern ("application");  staticpro (&Qapplication);
-  Qabout       = intern ("about");       staticpro (&Qabout);
+  staticpro (&Qmodifier_value);
 
-#if USE_CARBON_EVENTS && defined (MAC_OSX)
-  Qpreferences = intern ("preferences");  staticpro (&Qpreferences);
+  Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
+  Fput (Qmeta,    Qmodifier_value, make_number (meta_modifier));
+  Fput (Qalt,     Qmodifier_value, make_number (alt_modifier));
+  Fput (Qhyper,   Qmodifier_value, make_number (hyper_modifier));
+  Fput (Qsuper,   Qmodifier_value, make_number (super_modifier));
+
+#if USE_CARBON_EVENTS
+  Qhicommand   = intern ("hicommand");    staticpro (&Qhicommand);
+#ifdef MAC_OSX
   Qservices    = intern ("services");    staticpro (&Qservices);
   Qpaste       = intern ("paste");       staticpro (&Qpaste);
   Qperform     = intern ("perform");     staticpro (&Qperform);
 #endif
+#endif
 
 #ifdef MAC_OSX
   Fprovide (intern ("mac-carbon"), Qnil);
@@ -10951,9 +10949,6 @@ syms_of_macterm ()
   staticpro (&Qreverse);
   Qreverse = intern ("reverse");
 
-  staticpro (&Qmac_ready_for_drag_n_drop);
-  Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
-
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
 
@@ -10968,6 +10963,18 @@ syms_of_macterm ()
   atsu_font_id_hash = Qnil;
 #endif
 
+  /* We don't yet support this, but defining this here avoids whining
+     from cus-start.el and other places, like "M-x set-variable".  */
+  DEFVAR_BOOL ("x-use-underline-position-properties",
+              &x_use_underline_position_properties,
+     doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
+nil means ignore them.  If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil.
+
+NOTE: Not supported on Mac yet.  */);
+  x_use_underline_position_properties = 0;
+
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
               doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
 #ifdef USE_TOOLKIT_SCROLL_BARS
@@ -10979,85 +10986,83 @@ syms_of_macterm ()
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 
-
-
 /* Variables to configure modifier key assignment.  */
 
   DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
-    doc: /* Modifier key assumed when the Mac control key is pressed.
-The value can be `alt', `ctrl', `hyper', or `super' for the respective
-modifier.  The default is `ctrl'.  */);
-  Vmac_control_modifier = Qctrl;
+    doc: /* *Modifier key assumed when the Mac control key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  The default is `control'.  */);
+  Vmac_control_modifier = Qcontrol;
 
   DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
-    doc: /* Modifier key assumed when the Mac alt/option key is pressed.
-The value can be `alt', `ctrl', `hyper', or `super' for the respective
-modifier.  If the value is nil then the key will act as the normal
-Mac control modifier, and the option key can be used to compose
-characters depending on the chosen Mac keyboard setting. */);
+    doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  If the value is nil then the key will act as the
+normal Mac control modifier, and the option key can be used to compose
+characters depending on the chosen Mac keyboard setting.  */);
   Vmac_option_modifier = Qnil;
 
   DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
-    doc: /* Modifier key assumed when the Mac command key is pressed.
-The value can be `alt', `ctrl', `hyper', or `super' for the respective
-modifier. The default is `meta'. */);
+    doc: /* *Modifier key assumed when the Mac command key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  The default is `meta'.  */);
   Vmac_command_modifier = Qmeta;
 
   DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
-    doc: /* Modifier key assumed when the Mac function key is pressed.
-The value can be `alt', `ctrl', `hyper', or `super' for the respective
-modifier. Note that remapping the function key may lead to unexpected
-results for some keys on non-US/GB keyboards.  */);
+    doc: /* *Modifier key assumed when the Mac function key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  Note that remapping the function key may lead to
+unexpected results for some keys on non-US/GB keyboards.  */);
   Vmac_function_modifier = Qnil;
 
   DEFVAR_LISP ("mac-emulate-three-button-mouse",
               &Vmac_emulate_three_button_mouse,
-    doc: /* t means that when the option-key is held down while pressing the
-mouse button, the click will register as mouse-2 and while the
-command-key is held down, the click will register as mouse-3.
-'reverse means that the option-key will register for mouse-3
-and the command-key will register for mouse-2.  nil means that
-no emulation should be done and the modifiers should be placed
-on the mouse-1 event. */);
+    doc: /* *Specify a way of three button mouse emulation.
+The value can be nil, t, or the symbol `reverse'.
+nil means that no emulation should be done and the modifiers should be
+placed on the mouse-1 event.
+t means that when the option-key is held down while pressing the mouse
+button, the click will register as mouse-2 and while the command-key
+is held down, the click will register as mouse-3.
+The symbol `reverse' means that the option-key will register for
+mouse-3 and the command-key will register for mouse-2.  */);
   Vmac_emulate_three_button_mouse = Qnil;
 
 #if USE_CARBON_EVENTS
-  DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
-   doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
-the right click will be mouse-3.
-Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
-  Vmac_wheel_button_is_mouse_2 = Qt;
+  DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
+   doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
+Otherwise, the right click will be treated as mouse-2 and the wheel
+button will be mouse-3.  */);
+  mac_wheel_button_is_mouse_2 = 1;
 
-  DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
-   doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it.  */);
-  Vmac_pass_command_to_system = Qt;
+  DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
+   doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox.  */);
+  mac_pass_command_to_system = 1;
 
-  DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
-   doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it.  */);
-  Vmac_pass_control_to_system = Qt;
+  DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
+   doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox.  */);
+  mac_pass_control_to_system = 1;
 
 #endif
 
-  DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
-   doc: /* If non-nil, allow anti-aliasing.
+  DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
+   doc: /* *If non-nil, allow anti-aliasing.
 The text will be rendered using Core Graphics text rendering which
 may anti-alias the text.  */);
-  Vmac_use_core_graphics = Qnil;
+  mac_use_core_graphics = 0;
 
   /* Register an entry for `mac-roman' so that it can be used when
      creating the terminal frame on Mac OS 9 before loading
      term/mac-win.elc.  */
   DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
-               doc: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
+               doc: /* Alist of Emacs character sets vs text encodings and coding systems.
 Each entry should be of the form:
 
    (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
 
 where CHARSET-NAME is a string used in font names to identify the
-charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
-is a coding system corresponding to TEXT-ENCODING.  */);
+charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
+CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING.  */);
   Vmac_charset_info_alist =
     Fcons (list3 (build_string ("mac-roman"),
                  make_number (smRoman), Qnil), Qnil);