(x_create_tip_frame): Apply 2006-03-11 change for xfns.c.
[bpt/emacs.git] / src / macterm.c
index 1153efd..649bfb4 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"
@@ -93,8 +92,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 +105,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 +203,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;
 
@@ -255,7 +258,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 +267,13 @@ 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)
 
 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 +282,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);
 }
 
@@ -320,10 +322,10 @@ mac_draw_line (f, gc, x1, y1, x2, y2)
 
   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);
 }
 
 void
@@ -364,9 +366,9 @@ 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)));
 }
@@ -429,7 +431,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,7 +446,7 @@ 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)));
 }
@@ -576,9 +578,9 @@ 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);
 }
 
 
@@ -596,11 +598,11 @@ mac_draw_rectangle (f, gc, x, y, width, height)
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBForeColor (GC_FORE_COLOR (gc));
-  SetRect (&r, x, y, x + width + 1, y + height + 1);
+  SetRect (&r, x, y, x + width, y + height);
 
-  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);
 }
 
 
@@ -622,7 +624,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
@@ -678,27 +681,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 +711,144 @@ 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
+         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};
+
+         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);
+             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);
+                 CGContextSetRGBFillColor
+                   (context,
+                    RED_FROM_ULONG (gc->xgcv.background) / 255.0f,
+                    GREEN_FROM_ULONG (gc->xgcv.background) / 255.0f,
+                    BLUE_FROM_ULONG (gc->xgcv.background) / 255.0f,
+                    1.0);
+                 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);
+           }
+         CGContextSetRGBFillColor
+           (context,
+            RED_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
+            GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
+            BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
+            1.0);
+         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));
+         CGContextSynchronize (context);
+         QDEndCGContext (port, &context);
+#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
-           }
+         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
-  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 +862,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 +876,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 +1092,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,28 +1100,46 @@ 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++;
     }
 
   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);
+      if (bg_width)
+       {
+         CGContextSetRGBFillColor
+           (context,
+            RED_FROM_ULONG (gc->xgcv.background) / 255.0f,
+            GREEN_FROM_ULONG (gc->xgcv.background) / 255.0f,
+            BLUE_FROM_ULONG (gc->xgcv.background) / 255.0f,
+            1.0);
+         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);
     }
   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,
+                           RED_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
+                           GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
+                           BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
                            1.0);
   CGContextSetFont (context, GC_FONT (gc)->cg_font);
   CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
@@ -943,8 +1158,6 @@ mac_draw_string_cg (f, gc, x, y, buf, nchars)
   CGContextSynchronize (context);
   QDEndCGContext (port, &context);
 
-  xfree (advances);
-
   return 1;
 }
 #endif
@@ -971,7 +1184,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 +1202,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 +1228,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,7 +1248,7 @@ 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)));
 }
@@ -1073,9 +1286,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 */
@@ -1211,17 +1424,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 +1445,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 +1464,7 @@ mac_reset_clip_rectangles (display, gc)
      Display *display;
      GC gc;
 {
-  mac_set_clip_rectangles (display, gc, NULL, 0);
+  gc->n_clip_rects = 0;
 }
 
 
@@ -1720,63 +1924,32 @@ 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));
+         if (*row)
+           bzero (*row, sizeof (XCharStructRow));
        }
-
-      if (pcm && !pcm->valid_p)
+      if (*row)
        {
-         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);
-         UNBLOCK_INPUT;
-         if (err != noErr)
-           pcm = NULL;
-         else
+         pcm = (*row)->per_char + char2b->byte2;
+         if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2))
            {
-             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);
+             BLOCK_INPUT;
+             mac_query_char_extents (font->mac_style,
+                                     (char2b->byte1 << 8) + char2b->byte2,
+                                     NULL, NULL, pcm, NULL);
+             UNBLOCK_INPUT;
+             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 +1962,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 +1985,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));
@@ -2153,67 +2327,32 @@ mac_compute_glyph_string_overhangs (s)
 {
   if (s->cmp == NULL
       && s->first_glyph->type == CHAR_GLYPH)
-    {
-      Rect r;
-      MacFontStruct *font = s->font;
-
+    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);
+       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
 
-      s->right_overhang = r.right > s->width ? r.right - s->width : 0;
-      s->left_overhang = r.left < 0 ? -r.left : 0;
-    }
+       s->right_overhang = r.right > s->width ? r.right - s->width : 0;
+       s->left_overhang = r.left < 0 ? -r.left : 0;
+      }
 }
 
 
@@ -2228,14 +2367,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 +2398,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 +2418,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.  */
@@ -2307,7 +2436,7 @@ x_draw_glyph_string_foreground (s)
        {
          struct glyph *g = s->first_glyph + i;
          mac_draw_rectangle (s->f, s->gc, x, s->y,
-                             g->pixel_width - 1, s->height - 1);
+                             g->pixel_width, s->height);
          x += g->pixel_width;
        }
     }
@@ -2328,7 +2457,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 +2464,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);
     }
 }
 
@@ -2398,7 +2515,7 @@ x_draw_composite_glyph_string_foreground (s)
     {
       if (s->gidx == 0)
        mac_draw_rectangle (s->f, s->gc, x, s->y,
-                           s->width - 1, s->height - 1);
+                           s->width, s->height);
     }
   else
     {
@@ -2951,15 +3068,15 @@ x_draw_image_foreground (s)
              int r = s->img->relief;
              if (r < 0) r = -r;
              mac_draw_rectangle (s->f, s->gc, x - r, y - r,
-                                 s->slice.width + r*2 - 1,
-                                 s->slice.height + r*2 - 1);
+                                 s->slice.width + r*2,
+                                 s->slice.height + r*2);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     mac_draw_rectangle (s->f, s->gc, x, y,
-                       s->slice.width - 1, s->slice.height - 1);
+                       s->slice.width, s->slice.height);
 }
 
 
@@ -4148,8 +4265,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 +4387,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 +4529,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 +4545,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;
 }
@@ -4466,7 +4594,12 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
   r.bottom = disp_top + disp_height;
 
 #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,
@@ -4636,6 +4769,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 +4783,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))
@@ -4684,8 +4819,10 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
           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);
@@ -4703,30 +4840,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);
 #else /* not USE_TOOLKIT_SCROLL_BARS */
@@ -5097,7 +5245,7 @@ x_draw_hollow_cursor (w, row)
   /* Compute frame-relative coordinates for phys cursor.  */
   x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
   y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
-  wd = w->phys_cursor_width;
+  wd = w->phys_cursor_width + 1;
 
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
@@ -5208,7 +5356,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);
 }
 
 
@@ -5746,7 +5897,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 +5911,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;
     }
 }
@@ -5873,7 +6024,6 @@ x_make_frame_visible (f)
 
       f->output_data.mac->asked_for_visible = 1;
 
-      SelectWindow (FRAME_MAC_WINDOW (f));
       CollapseWindow (FRAME_MAC_WINDOW (f), false);
       ShowWindow (FRAME_MAC_WINDOW (f));
     }
@@ -7371,7 +7521,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 +7538,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 +7567,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 +7637,27 @@ 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->min_byte1 = 0;
+      font->max_byte1 = 0xff;
+      font->min_char_or_byte2 = 0;
+      font->max_char_or_byte2 = 0xff;
 
-      font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000);
-      if (font->per_char == NULL)
+      font->bounds.rows = xmalloc (sizeof (XCharStructRow *) * 0x100);
+      if (font->bounds.rows == NULL)
+       {
+         mac_unload_font (&one_mac_display_info, font);
+         return NULL;
+       }
+      bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100);
+      font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow));
+      if (font->bounds.rows[0] == NULL)
        {
          mac_unload_font (&one_mac_display_info, font);
          return NULL;
        }
-      bzero (font->per_char, sizeof (XCharStruct) * 0x10000);
+      bzero (font->bounds.rows[0], sizeof (XCharStructRow));
 
 #if USE_CG_TEXT_DRAWING
       {
@@ -7521,108 +7682,58 @@ XLoadQueryFont (Display *dpy, char *fontname)
       if (font->cg_glyphs)
        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 +7772,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 +7802,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 +7818,28 @@ XLoadQueryFont (Display *dpy, char *fontname)
        }
       else
        {
-         int c, min_width, max_width;
-         Rect char_bounds, min_bounds, max_bounds;
-         char ch;
-
-         font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
-         bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1));
+         int c;
 
-         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->min_byte1 = font->max_byte1 = 0;
+         font->min_char_or_byte2 = 0x20;
+         font->max_char_or_byte2 = 0xff;
 
-             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)
+         font->bounds.per_char =
+           xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
+         if (font->bounds.per_char == NULL)
            {
-             /* Fixed width and no overhangs.  */
-             xfree (font->per_char);
-             font->per_char = NULL;
+             mac_unload_font (&one_mac_display_info, font);
+             return NULL;
            }
+         bzero (font->bounds.per_char,
+                sizeof (XCharStruct) * (0xff - 0x20 + 1));
+
+         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 +7848,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 +7911,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);
 }
@@ -8109,17 +8236,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 +8254,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 +8276,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 +8304,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 +8391,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 +8409,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 +8443,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 +8471,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);
@@ -8699,179 +8829,49 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   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 ();
-
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
-                              NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_open_documents),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
-                              NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_open_documents),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
-
-#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 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 ();
-}
-
-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 = noErr;
   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);
-
-  buf.arg = Qapplication;
-  kbd_buffer_store_event (&buf);
+  AEDesc *desc_copy;
 
-#if USE_CARBON_EVENTS
-  switch (GetEventClass (event))
+  desc_copy = xmalloc (sizeof (AEDesc));
+  if (desc_copy == NULL)
+    err = memFullErr;
+  else
+    err = AEDuplicateDesc (desc, desc_copy);
+  if (err == noErr)
     {
-#ifdef MAC_OSX
-    case kEventClassService:
-      buf.arg = Qservices;
+      EVENT_INIT (buf);
+
+      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);
-      switch (GetEventKind (event))
-       {
-       case kEventServicePaste:
-         entry = Qpaste;
-         break;
+    }
 
-       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;
+  return err;
+}
 
-       default:
-         abort ();
-       }
-      break;
-#endif /* MAC_OSX */
-    case kEventClassCommand:
-      {
-       HICommand command;
+Lisp_Object
+mac_make_lispy_event_code (code)
+     int code;
+{
+  AEDesc *desc = (AEDesc *)code;
+  Lisp_Object obj;
 
-       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;
+  obj = mac_aedesc_to_lisp (desc);
+  AEDisposeDesc (desc);
+  xfree (desc);
 
-    default:
-      abort ();
-    }
-#else  /* USE_CARBON_EVENTS */
-  switch (event)
-    {
-    case kHICommandAbout:
-      entry = Qabout;
-      break;
-    case kHICommandQuit:
-      entry = Qquit;
-      break;
-    default:
-      abort ();
-    }
-#endif
-
-  buf.arg = entry;
-  kbd_buffer_store_event (&buf);
+  return obj;
 }
 
 #if USE_CARBON_EVENTS
@@ -8881,28 +8881,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;
+       UInt32 modifiers;
+       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;
 }
@@ -8928,12 +8946,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 +8970,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 +8983,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 +9037,7 @@ mac_handle_mouse_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  OSStatus result;
+  OSStatus result, err;
 
   switch (GetEventKind (event))
     {
@@ -9027,22 +9053,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 +9099,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 +9201,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 +9296,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 +9336,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 +9355,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 +9406,11 @@ main (void)
 
   init_environ ();
 
+  init_coercion_handler ();
+
   initialize_applescript ();
 
-  init_required_apple_events ();
+  init_apple_event_handler ();
 
   {
     char **argv;
@@ -9649,13 +9539,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 +9558,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 +9578,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 +9617,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,6 +9667,8 @@ 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 ();
 
@@ -10247,9 +10142,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)))
@@ -10318,12 +10213,10 @@ XTread_socket (sd, expected, hold_quit)
                }
              else
                {
-
                  inev.code =
                    backtranslate_modified_keycode(er.modifiers, keycode,
                                                   er.message & charCodeMask);
                  inev.kind = ASCII_KEYSTROKE_EVENT;
-
                }
          }
 
@@ -10416,6 +10309,7 @@ XTread_socket (sd, expected, hold_quit)
   }
 #endif
 
+  --handling_signal;
   UNBLOCK_INPUT;
   return count;
 }
@@ -10891,7 +10785,6 @@ mac_initialize ()
   BLOCK_INPUT;
 
 #if TARGET_API_MAC_CARBON
-  init_required_apple_events ();
 
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
@@ -10906,6 +10799,10 @@ mac_initialize ()
 #endif /* USE_CARBON_EVENTS */
 
 #ifdef MAC_OSX
+  init_coercion_handler ();
+
+  init_apple_event_handler ();
+
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
@@ -10922,27 +10819,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 +10849,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 +10863,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 +10886,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);