]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
Merge from emacs--devo--0
[gnu-emacs] / src / macterm.c
index 099b69bfb09dc5ebf069bcb3365b6aeb40a90afe..549e1e7977b3a66ed6e6fbbc35874bb5547c1e0e 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of GUI terminal on the Mac OS.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-                 2005 Free Software Foundation, Inc.
+                 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -68,7 +68,6 @@ Boston, MA 02110-1301, USA.  */
 #include <errno.h>
 #include <setjmp.h>
 #include <sys/stat.h>
-#include <sys/param.h>
 
 #include "charset.h"
 #include "coding.h"
@@ -78,7 +77,6 @@ Boston, MA 02110-1301, USA.  */
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
-#include "gnu.h"
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
@@ -89,22 +87,15 @@ Boston, MA 02110-1301, USA.  */
 #include "character.h"
 #include "ccl.h"
 
-/* Set of macros that handle mapping of Mac modifier keys to emacs.  */
-#define macCtrlKey     (NILP (Vmac_reverse_ctrl_meta) ? controlKey :   \
-                       (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
-#define macShiftKey    (shiftKey)
-#define macMetaKey     (NILP (Vmac_reverse_ctrl_meta) ?                        \
-                       (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
-                       : controlKey)
-#define macAltKey      (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
 \f
 
 /* Non-nil means Emacs uses toolkit scroll bars.  */
 
 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
@@ -115,6 +106,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.  */
 
@@ -167,6 +162,7 @@ struct frame *pending_autoraise_frame;
 /* Where the mouse was last time we reported a mouse event.  */
 
 static Rect last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
 
 /* The scroll bar in which the last X motion event occurred.
 
@@ -208,7 +204,7 @@ extern EMACS_INT extra_keyboard_modifiers;
 
 /* The keysyms to use for the various modifiers.  */
 
-static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
+static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
 
 extern int inhibit_window_system;
 
@@ -220,7 +216,6 @@ QDGlobals qd;  /* QuickDraw global information structure.  */
 
 struct mac_display_info *mac_display_info_for_display (Display *);
 static void x_update_window_end P_ ((struct window *, int, int));
-static int x_io_error_quitter P_ ((Display *));
 int x_catch_errors P_ ((Display *));
 void x_uncatch_errors P_ ((Display *, int));
 void x_lower_frame P_ ((struct frame *));
@@ -263,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.  */
@@ -272,7 +267,107 @@ 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 MAC_WINDOW_NORMAL_GC(w)        (((mac_output *) GetWRefCon (w))->normal_gc)
+#define FRAME_NORMAL_GC(f)     ((f)->output_data.mac->normal_gc)
+#define CG_SET_FILL_COLOR(context, color)                      \
+  CGContextSetRGBFillColor (context,                                   \
+                           RED_FROM_ULONG (color) / 255.0f,            \
+                           GREEN_FROM_ULONG (color) / 255.0f,          \
+                           BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
+#define CG_SET_STROKE_COLOR(context, color)            \
+  CGContextSetRGBStrokeColor (context,                                 \
+                             RED_FROM_ULONG (color) / 255.0f,          \
+                             GREEN_FROM_ULONG (color) / 255.0f,        \
+                             BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
+#if USE_CG_DRAWING
+#define FRAME_CG_CONTEXT(f)    ((f)->output_data.mac->cg_context)
+
+/* Fringe bitmaps.  */
+
+static int max_fringe_bmp = 0;
+static CGImageRef *fringe_bmp = 0;
+
+static CGContextRef
+mac_begin_cg_clip (f, gc)
+     struct frame *f;
+     GC gc;
+{
+  CGContextRef context = FRAME_CG_CONTEXT (f);
+
+  if (!context)
+    {
+      QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
+      FRAME_CG_CONTEXT (f) = context;
+    }
+
+  CGContextSaveGState (context);
+  CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
+  CGContextScaleCTM (context, 1, -1);
+  if (gc && gc->n_clip_rects)
+    CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+
+  return context;
+}
+
+static void
+mac_end_cg_clip (f)
+     struct frame *f;
+{
+  CGContextRestoreGState (FRAME_CG_CONTEXT (f));
+}
+
+void
+mac_prepare_for_quickdraw (f)
+     struct frame *f;
+{
+  if (f == NULL)
+    {
+      Lisp_Object rest, frame;
+      FOR_EACH_FRAME (rest, frame)
+       if (FRAME_MAC_P (XFRAME (frame)))
+         mac_prepare_for_quickdraw (XFRAME (frame));
+    }
+  else
+    {
+      CGContextRef context = FRAME_CG_CONTEXT (f);
+
+      if (context)
+       {
+         CGContextSynchronize (context);
+         QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
+                         &FRAME_CG_CONTEXT (f));
+       }
+    }
+}
+#endif
+
+static RgnHandle saved_port_clip_region = NULL;
+
+static void
+mac_begin_clip (gc)
+     GC gc;
+{
+  static RgnHandle new_region = NULL;
+
+  if (saved_port_clip_region == NULL)
+    saved_port_clip_region = NewRgn ();
+  if (new_region == NULL)
+    new_region = NewRgn ();
+
+  if (gc->n_clip_rects)
+    {
+      GetClip (saved_port_clip_region);
+      SectRgn (saved_port_clip_region, gc->clip_region, new_region);
+      SetClip (new_region);
+    }
+}
+
+static void
+mac_end_clip (gc)
+     GC gc;
+{
+  if (gc->n_clip_rects)
+    SetClip (saved_port_clip_region);
+}
 
 
 /* X display function emulation */
@@ -289,18 +384,53 @@ XFreePixmap (display, pixmap)
 /* Mac version of XDrawLine.  */
 
 static void
-XDrawLine (display, w, gc, x1, y1, x2, y2)
-     Display *display;
-     WindowPtr w;
+mac_draw_line (f, gc, x1, y1, x2, y2)
+     struct frame *f;
      GC gc;
      int x1, y1, x2, y2;
 {
-  SetPortWindowPort (w);
+#if USE_CG_DRAWING
+  CGContextRef context;
+  float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
+
+  if (y1 != y2)
+    gx1 += 0.5f, gx2 += 0.5f;
+  if (x1 != x2)
+    gy1 += 0.5f, gy2 += 0.5f;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CGContextBeginPath (context);
+  CGContextMoveToPoint (context, gx1, gy1);
+  CGContextAddLineToPoint (context, gx2, gy2);
+  CGContextClosePath (context);
+  CGContextStrokePath (context);
+  mac_end_cg_clip (f);
+#else
+  if (x1 == x2)
+    {
+      if (y1 > y2)
+       y1--;
+      else if (y2 > y1)
+       y2--;
+    }
+  else if (y1 == y2)
+    {
+      if (x1 > x2)
+       x1--;
+      else
+       x2--;
+    }
+
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBForeColor (GC_FORE_COLOR (gc));
 
+  mac_begin_clip (gc);
   MoveTo (x1, y1);
   LineTo (x2, y2);
+  mac_end_clip (gc);
+#endif
 }
 
 void
@@ -313,6 +443,21 @@ mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
   CGrafPtr old_port;
   GDHandle old_gdh;
 
+  if (x1 == x2)
+    {
+      if (y1 > y2)
+       y1--;
+      else if (y2 > y1)
+       y2--;
+    }
+  else if (y1 == y2)
+    {
+      if (x1 > x2)
+       x1--;
+      else
+       x2--;
+    }
+
   GetGWorld (&old_port, &old_gdh);
   SetGWorld (p, NULL);
 
@@ -328,68 +473,124 @@ mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
 
 
 static void
-mac_erase_rectangle (w, gc, x, y, width, height)
-     WindowPtr w;
+mac_erase_rectangle (f, gc, x, y, width, height)
+     struct frame *f;
      GC gc;
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
-  SetPortWindowPort (w);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
+  mac_begin_clip (gc);
   EraseRect (&r);
+  mac_end_clip (gc);
 
-  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+#endif
 }
 
 
 /* Mac version of XClearArea.  */
 
 void
-XClearArea (display, w, x, y, width, height, exposures)
-     Display *display;
-     WindowPtr w;
+mac_clear_area (f, x, y, width, height)
+     struct frame *f;
      int x, y;
      unsigned int width, height;
-     int exposures;
 {
-  mac_erase_rectangle (w, MAC_WINDOW_NORMAL_GC (w), x, y, width, height);
+  mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
 }
 
 /* Mac version of XClearWindow.  */
 
 static void
-XClearWindow (display, w)
-     Display *display;
-     WindowPtr w;
+mac_clear_window (f)
+     struct frame *f;
 {
-  SetPortWindowPort (w);
+#if USE_CG_DRAWING
+  CGContextRef context;
+  GC gc = FRAME_NORMAL_GC (f);
 
-  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
+  context = mac_begin_cg_clip (f, NULL);
+  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
+                                         FRAME_PIXEL_HEIGHT (f)));
+  mac_end_cg_clip (f);
+#else
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 
 #if TARGET_API_MAC_CARBON
   {
     Rect r;
 
-    GetWindowPortBounds (w, &r);
+    GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
     EraseRect (&r);
   }
 #else /* not TARGET_API_MAC_CARBON */
-  EraseRect (&(w->portRect));
+  EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
 #endif /* not TARGET_API_MAC_CARBON */
+#endif
 }
 
 
 /* Mac replacement for XCopyArea.  */
 
+#if USE_CG_DRAWING
 static void
-mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
-     Display *display;
-     WindowPtr w;
+mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
+                  dest_x, dest_y, overlay_p)
+     CGImageRef image;
+     struct frame *f;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y, overlay_p;
+{
+  CGContextRef context;
+  float port_height = FRAME_PIXEL_HEIGHT (f);
+  CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
+
+  context = mac_begin_cg_clip (f, gc);
+  if (!overlay_p)
+    {
+      CG_SET_FILL_COLOR (context, gc->xgcv.background);
+      CGContextFillRect (context, dest_rect);
+    }
+  CGContextClipToRect (context, dest_rect);
+  CGContextScaleCTM (context, 1, -1);
+  CGContextTranslateCTM (context, 0, -port_height);
+  if (CGImageIsMask (image))
+    CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextDrawImage (context,
+                     CGRectMake (dest_x - src_x,
+                                 port_height - (dest_y - src_y
+                                                + CGImageGetHeight (image)),
+                                 CGImageGetWidth (image),
+                                 CGImageGetHeight (image)),
+                     image);
+  mac_end_cg_clip (f);
+}
+
+#else  /* !USE_CG_DRAWING */
+
+static void
+mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
+     struct frame *f;
      GC gc;
      int x, y, width, height;
      unsigned short *bits;
@@ -402,54 +603,32 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
   bitmap.baseAddr = (char *)bits;
   SetRect (&(bitmap.bounds), 0, 0, width, height);
 
-  SetPortWindowPort (w);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBForeColor (GC_FORE_COLOR (gc));
   RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
+  mac_begin_clip (gc);
 #if TARGET_API_MAC_CARBON
-  LockPortBits (GetWindowPort (w));
-  CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
-           &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
-  UnlockPortBits (GetWindowPort (w));
+  {
+    CGrafPtr port;
+
+    GetPort (&port);
+    LockPortBits (port);
+    CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
+             &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
+    UnlockPortBits (port);
+  }
 #else /* not TARGET_API_MAC_CARBON */
-  CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
+  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);
 
-  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
-}
-
-
-/* Mac replacement for XSetClipRectangles.  */
-
-static void
-mac_set_clip_rectangle (display, w, r)
-     Display *display;
-     WindowPtr w;
-     Rect *r;
-{
-  SetPortWindowPort (w);
-
-  ClipRect (r);
-}
-
-
-/* Mac replacement for XSetClipMask.  */
-
-static void
-mac_reset_clipping (display, w)
-     Display *display;
-     WindowPtr w;
-{
-  Rect r;
-
-  SetPortWindowPort (w);
-
-  SetRect (&r, -32767, -32767, 32767, 32767);
-  ClipRect (&r);
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCreateBitmapFromBitmapData.  */
@@ -510,7 +689,15 @@ XCreatePixmap (display, w, width, height, depth)
   SetPortWindowPort (w);
 
   SetRect (&r, 0, 0, width, height);
-  err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
+#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
+  if (depth == 1)
+#endif
+    err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
+#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
+  else
+    /* CreateCGImageFromPixMaps requires ARGB format.  */
+    err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
+#endif
   if (err != noErr)
     return NULL;
   return pixmap;
@@ -565,212 +752,641 @@ XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
 /* Mac replacement for XFillRectangle.  */
 
 static void
-XFillRectangle (display, w, gc, x, y, width, height)
-     Display *display;
-     WindowPtr w;
+mac_fill_rectangle (f, gc, x, y, width, height)
+     struct frame *f;
      GC gc;
      int x, y;
      unsigned int width, height;
 {
-  Rect r;
-
-  SetPortWindowPort (w);
-
-  RGBForeColor (GC_FORE_COLOR (gc));
-  SetRect (&r, x, y, x + width, y + height);
-
-  PaintRect (&r); /* using foreground color of gc */
-}
+#if USE_CG_DRAWING
+  CGContextRef context;
 
-
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-static void
-mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
-     Display *display;
-     Pixmap p;
-     GC gc;
-     int x, y;
-     unsigned int width, height;
-{
-  CGrafPtr old_port;
-  GDHandle old_gdh;
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (p, NULL);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+
   RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
-  LockPixels (GetGWorldPixMap (p));
+  mac_begin_clip (gc);
   PaintRect (&r); /* using foreground color of gc */
-  UnlockPixels (GetGWorldPixMap (p));
-
-  SetGWorld (old_port, old_gdh);
-}
+  mac_end_clip (gc);
 #endif
+}
 
 
 /* Mac replacement for XDrawRectangle: dest is a window.  */
 
 static void
-mac_draw_rectangle (display, w, gc, x, y, width, height)
-     Display *display;
-     WindowPtr w;
+mac_draw_rectangle (f, gc, x, y, width, height)
+     struct frame *f;
      GC gc;
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CGContextStrokeRect (context,
+                      CGRectMake (x + 0.5f, y + 0.5f, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
-  SetPortWindowPort (w);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width + 1, y + height + 1);
 
+  mac_begin_clip (gc);
   FrameRect (&r); /* using foreground color of gc */
+  mac_end_clip (gc);
+#endif
 }
 
 
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-/* Mac replacement for XDrawRectangle: dest is a Pixmap.  */
+#if USE_ATSUI
+static OSStatus
+atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
+     ConstUniCharArrayPtr text;
+     UniCharCount text_length;
+     ATSUStyle style;
+     ATSUTextLayout *text_layout;
+{
+  OSStatus err;
+  static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */
+
+  if (saved_text_layout == NULL)
+    {
+      UniCharCount lengths[] = {kATSUToTextEnd};
+      ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
+      ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
+      static ATSLineLayoutOptions line_layout =
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+       kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
+       | kATSLineUseQDRendering
+#else
+       kATSLineIsDisplayOnly | kATSLineFractDisable
+#endif
+       ;
+      ATSUAttributeValuePtr values[] = {&line_layout};
+
+      err = ATSUCreateTextLayoutWithTextPtr (text,
+                                            kATSUFromTextBeginning,
+                                            kATSUToTextEnd,
+                                            text_length,
+                                            1, lengths, &style,
+                                            &saved_text_layout);
+      if (err == noErr)
+       err = ATSUSetLayoutControls (saved_text_layout,
+                                    sizeof (tags) / sizeof (tags[0]),
+                                    tags, sizes, values);
+      /* XXX: Should we do this? */
+      if (err == noErr)
+       err = ATSUSetTransientFontMatching (saved_text_layout, true);
+    }
+  else
+    {
+      err = ATSUSetRunStyle (saved_text_layout, style,
+                            kATSUFromTextBeginning, kATSUToTextEnd);
+      if (err == noErr)
+       err = ATSUSetTextPointerLocation (saved_text_layout, text,
+                                         kATSUFromTextBeginning,
+                                         kATSUToTextEnd,
+                                         text_length);
+    }
+
+  if (err == noErr)
+    *text_layout = saved_text_layout;
+  return err;
+}
+#endif
+
 
 static void
-mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
-     Display *display;
-     Pixmap p;
-     GC gc;
+mac_invert_rectangle (f, x, y, width, height)
+     struct frame *f;
      int x, y;
      unsigned int width, height;
 {
-  CGrafPtr old_port;
-  GDHandle old_gdh;
   Rect r;
 
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (p, NULL);
-  RGBForeColor (GC_FORE_COLOR (gc));
-  SetRect (&r, x, y, x + width + 1, y + height + 1);
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  LockPixels (GetGWorldPixMap (p));
-  FrameRect (&r); /* using foreground color of gc */
-  UnlockPixels (GetGWorldPixMap (p));
+  SetRect (&r, x, y, x + width, y + height);
 
-  SetGWorld (old_port, old_gdh);
+  InvertRect (&r);
 }
-#endif
 
 
 static void
-mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
-                       bytes_per_char)
-     Display *display;
-     WindowPtr w;
+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));
 
-  SetPortWindowPort (w);
+#if USE_ATSUI
+  if (GC_FONT (gc)->mac_style)
+    {
+      OSErr err;
+      ATSUTextLayout text_layout;
 
-  RGBForeColor (GC_FORE_COLOR (gc));
-  if (mode != srcOr)
-    RGBBackColor (GC_BACK_COLOR (gc));
+      xassert (bytes_per_char == 2);
+
+#ifndef WORDS_BIG_ENDIAN
+      {
+       int i;
+       UniChar *text = (UniChar *)buf;
+
+       for (i = 0; i < nchars; i++)
+         text[i] = EndianU16_BtoN (text[i]);
+      }
+#endif
+      err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
+                                               nchars,
+                                               GC_FONT (gc)->mac_style,
+                                               &text_layout);
+      if (err != noErr)
+       return;
+#ifdef MAC_OSX
+      if (!mac_use_core_graphics)
+       {
+#endif
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
+#endif
+         mac_begin_clip (gc);
+         RGBForeColor (GC_FORE_COLOR (gc));
+         if (bg_width)
+           {
+             Rect r;
+
+             SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
+                      x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
+             RGBBackColor (GC_BACK_COLOR (gc));
+             EraseRect (&r);
+             RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+           }
+         MoveTo (x, y);
+         ATSUDrawText (text_layout,
+                       kATSUFromTextBeginning, kATSUToTextEnd,
+                       kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
+         mac_end_clip (gc);
+#ifdef MAC_OSX
+       }
+      else
+       {
+         CGrafPtr port;
+         CGContextRef context;
+         float port_height = FRAME_PIXEL_HEIGHT (f);
+         ATSUAttributeTag tags[] = {kATSUCGContextTag};
+         ByteCount sizes[] = {sizeof (CGContextRef)};
+         ATSUAttributeValuePtr values[] = {&context};
+
+#if USE_CG_DRAWING
+         context = mac_begin_cg_clip (f, gc);
+#else
+         GetPort (&port);
+         QDBeginCGContext (port, &context);
+         if (gc->n_clip_rects || bg_width)
+           {
+             CGContextTranslateCTM (context, 0, port_height);
+             CGContextScaleCTM (context, 1, -1);
+             if (gc->n_clip_rects)
+               CGContextClipToRects (context, gc->clip_rects,
+                                     gc->n_clip_rects);
+#endif
+             if (bg_width)
+               {
+                 CG_SET_FILL_COLOR (context, gc->xgcv.background);
+                 CGContextFillRect
+                   (context,
+                    CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
+                                bg_width, FONT_HEIGHT (GC_FONT (gc))));
+               }
+             CGContextScaleCTM (context, 1, -1);
+             CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
+           }
+#endif
+         CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+         err = ATSUSetLayoutControls (text_layout,
+                                      sizeof (tags) / sizeof (tags[0]),
+                                      tags, sizes, values);
+         if (err == noErr)
+           ATSUDrawText (text_layout,
+                         kATSUFromTextBeginning, kATSUToTextEnd,
+                         Long2Fix (x), Long2Fix (port_height - y));
+#if USE_CG_DRAWING
+         mac_end_cg_clip (f);
+         context = NULL;
+#else
+         CGContextSynchronize (context);
+         QDEndCGContext (port, &context);
+#endif
+#if 0
+         /* This doesn't work on Mac OS X 10.1.  */
+         ATSUClearLayoutControls (text_layout,
+                                  sizeof (tags) / sizeof (tags[0]), tags);
+#else
+         ATSUSetLayoutControls (text_layout,
+                                sizeof (tags) / sizeof (tags[0]),
+                                tags, sizes, values);
+#endif
+       }
+#endif /* MAC_OSX */
+    }
+  else
+#endif /* USE_ATSUI */
+    {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+      UInt32 savedFlags;
 
-  TextFont (GC_FONT (gc)->mac_fontnum);
-  TextSize (GC_FONT (gc)->mac_fontsize);
-  TextFace (GC_FONT (gc)->mac_fontface);
-  TextMode (mode);
+      if (mac_use_core_graphics)
+       savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
+#endif
+#if USE_CG_DRAWING
+      mac_prepare_for_quickdraw (f);
+#endif
+      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;
 
-  MoveTo (x, y);
-  DrawText (buf, 0, nchars * bytes_per_char);
+         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 (MAC_WINDOW_NORMAL_GC (w)));
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-  if (!NILP(Vmac_use_core_graphics))
-    SwapQDTextFlags(savedFlags);
+      if (mac_use_core_graphics)
+       SwapQDTextFlags(savedFlags);
 #endif
+    }
 }
 
 
 /* Mac replacement for XDrawString.  */
 
 static void
-XDrawString (display, w, gc, x, y, buf, nchars)
-     Display *display;
-     WindowPtr w;
+mac_draw_string (f, gc, x, y, buf, nchars)
+     struct frame *f;
      GC gc;
      int x, y;
      char *buf;
      int nchars;
 {
-  mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
+  mac_draw_string_common (f, gc, x, y, buf, nchars, 0, 1);
 }
 
 
 /* Mac replacement for XDrawString16. */
 
 static void
-XDrawString16 (display, w, gc, x, y, buf, nchars)
-     Display *display;
-     WindowPtr w;
+mac_draw_string_16 (f, gc, x, y, buf, nchars)
+     struct frame *f;
      GC gc;
      int x, y;
      XChar2b *buf;
      int nchars;
 {
-  mac_draw_string_common (display, w, 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
-XDrawImageString (display, w, gc, x, y, buf, nchars)
-     Display *display;
-     WindowPtr w;
+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 (display, w, 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
-XDrawImageString16 (display, w, gc, x, y, buf, nchars)
-     Display *display;
-     WindowPtr w;
+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, bg_width;
+{
+  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
+     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 ()
+{
+  int threshold;
+  Boolean valid_p;
+
+  threshold =
+    CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
+                                    kCFPreferencesCurrentApplication,
+                                    &valid_p);
+  if (valid_p)
+    cg_text_anti_aliasing_threshold = threshold;
+}
+
+static int
+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, bg_width;
 {
-  mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
-                         2);
+  CGrafPtr port;
+  float port_height, gx, gy;
+  int i;
+  CGContextRef context;
+  CGGlyph *glyphs;
+  CGSize *advances;
+
+  if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
+    return 0;
+
+  port = GetWindowPort (FRAME_MAC_WINDOW (f));
+  port_height = FRAME_PIXEL_HEIGHT (f);
+  gx = x;
+  gy = port_height - y;
+  glyphs = (CGGlyph *)buf;
+  advances = alloca (sizeof (CGSize) * nchars);
+  if (advances == NULL)
+    return 0;
+  for (i = 0; i < nchars; i++)
+    {
+      XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
+
+      advances[i].width = pcm->width;
+      advances[i].height = 0;
+      glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
+      buf++;
+    }
+
+#if USE_CG_DRAWING
+  context = mac_begin_cg_clip (f, gc);
+#else
+  QDBeginCGContext (port, &context);
+  if (gc->n_clip_rects || bg_width)
+    {
+      CGContextTranslateCTM (context, 0, port_height);
+      CGContextScaleCTM (context, 1, -1);
+      if (gc->n_clip_rects)
+       CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+#endif
+      if (bg_width)
+       {
+         CG_SET_FILL_COLOR (context, gc->xgcv.background);
+         CGContextFillRect
+           (context,
+            CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
+                        bg_width, FONT_HEIGHT (GC_FONT (gc))));
+       }
+      CGContextScaleCTM (context, 1, -1);
+      CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
+    }
+#endif
+  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextSetFont (context, GC_FONT (gc)->cg_font);
+  CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
+  if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
+    CGContextSetShouldAntialias (context, false);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+  CGContextSetTextPosition (context, gx, gy);
+  CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
+#else
+  for (i = 0; i < nchars; i++)
+    {
+      CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
+      gx += advances[i].width;
+    }
+#endif
+#if USE_CG_DRAWING
+  mac_end_cg_clip (f);
+#else
+  CGContextSynchronize (context);
+  QDEndCGContext (port, &context);
+#endif
+
+  return 1;
 }
+#endif
 
 
+#if !USE_CG_DRAWING
 /* Mac replacement for XCopyArea: dest must be window.  */
 
 static void
-mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
-              dest_y)
-     Display *display;
+mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
      Pixmap src;
-     WindowPtr dest;
+     struct frame *f;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
@@ -778,7 +1394,7 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
 {
   Rect src_r, dest_r;
 
-  SetPortWindowPort (dest);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -786,29 +1402,35 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
   ForeColor (blackColor);
   BackColor (whiteColor);
 
+  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
 #if TARGET_API_MAC_CARBON
-  LockPortBits (GetWindowPort (dest));
-  CopyBits (GetPortBitMapForCopyBits (src),
-           GetPortBitMapForCopyBits (GetWindowPort (dest)),
-           &src_r, &dest_r, srcCopy, 0);
-  UnlockPortBits (GetWindowPort (dest));
+  {
+    CGrafPtr port;
+
+    GetPort (&port);
+    LockPortBits (port);
+    CopyBits (GetPortBitMapForCopyBits (src),
+             GetPortBitMapForCopyBits (port),
+             &src_r, &dest_r, srcCopy, 0);
+    UnlockPortBits (port);
+  }
 #else /* not TARGET_API_MAC_CARBON */
-  CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
+  CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
            &src_r, &dest_r, srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (src));
+  mac_end_clip (gc);
 
-  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest)));
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
 
 
 static void
-mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
+mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
                         width, height, dest_x, dest_y)
-     Display *display;
      Pixmap src, mask;
-     WindowPtr dest;
+     struct frame *f;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
@@ -816,7 +1438,7 @@ mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
 {
   Rect src_r, dest_r;
 
-  SetPortWindowPort (dest);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -824,31 +1446,38 @@ mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
   ForeColor (blackColor);
   BackColor (whiteColor);
 
+  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
   LockPixels (GetGWorldPixMap (mask));
 #if TARGET_API_MAC_CARBON
-  LockPortBits (GetWindowPort (dest));
-  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
-           GetPortBitMapForCopyBits (GetWindowPort (dest)),
-           &src_r, &src_r, &dest_r);
-  UnlockPortBits (GetWindowPort (dest));
+  {
+    CGrafPtr port;
+
+    GetPort (&port);
+    LockPortBits (port);
+    CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
+             GetPortBitMapForCopyBits (port),
+             &src_r, &src_r, &dest_r);
+    UnlockPortBits (port);
+  }
 #else /* not TARGET_API_MAC_CARBON */
   CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
-           &(dest->portBits), &src_r, &src_r, &dest_r);
+           &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (mask));
   UnlockPixels (GetGWorldPixMap (src));
+  mac_end_clip (gc);
 
-  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest)));
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCopyArea: used only for scrolling.  */
 
 static void
-mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
-     Display *display;
-     WindowPtr w;
+mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
+     struct frame *f;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
@@ -859,11 +1488,16 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
   RgnHandle dummy = NewRgn (); /* For avoiding update events.  */
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
-  ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
+  ScrollWindowRect (FRAME_MAC_WINDOW (f),
+                   &src_r, dest_x - src_x, dest_y - src_y,
                    kScrollWindowNoOptions, dummy);
   DisposeRgn (dummy);
 #else /* not TARGET_API_MAC_CARBON */
   Rect src_r, dest_r;
+  WindowPtr w = FRAME_MAC_WINDOW (f);
 
   SetPort (w);
 
@@ -874,93 +1508,13 @@ mac_scroll_area (display, w, 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);
   CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
+  mac_end_clip (gc);
 
-  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
-#endif /* not TARGET_API_MAC_CARBON */
-}
-
-
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-/* Mac replacement for XCopyArea: dest must be Pixmap.  */
-
-static void
-mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
-                     dest_x, dest_y)
-     Display *display;
-     Pixmap src, dest;
-     GC gc;
-     int src_x, src_y;
-     unsigned int width, height;
-     int dest_x, dest_y;
-{
-  CGrafPtr old_port;
-  GDHandle old_gdh;
-  Rect src_r, dest_r;
-
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (dest, NULL);
-  ForeColor (blackColor);
-  BackColor (whiteColor);
-
-  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
-  LockPixels (GetGWorldPixMap (src));
-  LockPixels (GetGWorldPixMap (dest));
-#if TARGET_API_MAC_CARBON
-  CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
-           &src_r, &dest_r, srcCopy, 0);
-#else /* not TARGET_API_MAC_CARBON */
-  CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
-           &src_r, &dest_r, srcCopy, 0);
-#endif /* not TARGET_API_MAC_CARBON */
-  UnlockPixels (GetGWorldPixMap (dest));
-  UnlockPixels (GetGWorldPixMap (src));
-
-  SetGWorld (old_port, old_gdh);
-}
-
-
-static void
-mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
-                                  width, height, dest_x, dest_y)
-     Display *display;
-     Pixmap src, mask, dest;
-     GC gc;
-     int src_x, src_y;
-     unsigned int width, height;
-     int dest_x, dest_y;
-{
-  CGrafPtr old_port;
-  GDHandle old_gdh;
-  Rect src_r, dest_r;
-
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (dest, NULL);
-  ForeColor (blackColor);
-  BackColor (whiteColor);
-
-  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
-  LockPixels (GetGWorldPixMap (src));
-  LockPixels (GetGWorldPixMap (mask));
-  LockPixels (GetGWorldPixMap (dest));
-#if TARGET_API_MAC_CARBON
-  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
-           GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
-#else /* not TARGET_API_MAC_CARBON */
-  CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
-           &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 #endif /* not TARGET_API_MAC_CARBON */
-  UnlockPixels (GetGWorldPixMap (dest));
-  UnlockPixels (GetGWorldPixMap (mask));
-  UnlockPixels (GetGWorldPixMap (src));
-
-  SetGWorld (old_port, old_gdh);
 }
-#endif
 
 
 /* Mac replacement for XChangeGC.  */
@@ -992,11 +1546,8 @@ XCreateGC (display, window, mask, xgcv)
 {
   GC gc = xmalloc (sizeof (*gc));
 
-  if (gc)
-    {
-      bzero (gc, sizeof (*gc));
-      XChangeGC (display, gc, mask, xgcv);
-    }
+  bzero (gc, sizeof (*gc));
+  XChangeGC (display, gc, mask, xgcv);
 
   return gc;
 }
@@ -1009,6 +1560,8 @@ XFreeGC (display, gc)
      Display *display;
      GC gc;
 {
+  if (gc->clip_region)
+    DisposeRgn (gc->clip_region);
   xfree (gc);
 }
 
@@ -1079,6 +1632,61 @@ XSetFont (display, gc, font)
 }
 
 
+/* Mac replacement for XSetClipRectangles.  */
+
+static void
+mac_set_clip_rectangles (display, gc, rectangles, n)
+     Display *display;
+     GC gc;
+     Rect *rectangles;
+     int n;
+{
+  int i;
+
+  xassert (n >= 0 && n <= MAX_CLIP_RECTS);
+
+  gc->n_clip_rects = n;
+  if (n > 0)
+    {
+      if (gc->clip_region == NULL)
+       gc->clip_region = NewRgn ();
+      RectRgn (gc->clip_region, rectangles);
+      if (n > 1)
+       {
+         RgnHandle region = NewRgn ();
+
+         for (i = 1; i < n; i++)
+           {
+             RectRgn (region, rectangles + i);
+             UnionRgn (gc->clip_region, region, gc->clip_region);
+           }
+         DisposeRgn (region);
+       }
+    }
+#if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
+  for (i = 0; i < n; i++)
+    {
+      Rect *rect = rectangles + i;
+
+      gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
+                                     rect->right - rect->left,
+                                     rect->bottom - rect->top);
+    }
+#endif
+}
+
+
+/* Mac replacement for XSetClipMask.  */
+
+static INLINE void
+mac_reset_clip_rectangles (display, gc)
+     Display *display;
+     GC gc;
+{
+  gc->n_clip_rects = 0;
+}
+
+
 /* Mac replacement for XSetWindowBackground.  */
 
 void
@@ -1122,14 +1730,6 @@ XSetWindowBackground (display, w, color)
 #endif
 }
 
-/* x_sync is a no-op on Mac.  */
-void
-x_sync (f)
-     void *f;
-{
-}
-
-
 /* Flush display of frame F, or of all frames if F is null.  */
 
 static void
@@ -1138,6 +1738,9 @@ x_flush (f)
 {
 #if TARGET_API_MAC_CARBON
   BLOCK_INPUT;
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   if (f)
     QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
   else
@@ -1268,8 +1871,7 @@ mac_draw_vertical_window_border (w, x, y0, y1)
     XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
                    face->foreground);
 
-  XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-            f->output_data.mac->normal_gc, x, y0, x, y1);
+  mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
 }
 
 /* End update of window W (which is equal to updated_window).
@@ -1408,11 +2010,8 @@ x_after_update_window_line (desired_row)
        y -= width;
 
       BLOCK_INPUT;
-      XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 0, y, width, height, 0);
-      XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 FRAME_PIXEL_WIDTH (f) - width, y,
-                 width, height, 0);
+      mac_clear_area (f, 0, y, width, height);
+      mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
       UNBLOCK_INPUT;
     }
 }
@@ -1431,8 +2030,6 @@ x_draw_fringe_bitmap (w, row, p)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Display *display = FRAME_MAC_DISPLAY (f);
-  WindowPtr window = FRAME_MAC_WINDOW (f);
-  GC gc = f->output_data.mac->normal_gc;
   struct face *face = p->face;
   int rowY;
 
@@ -1446,12 +2043,12 @@ x_draw_fringe_bitmap (w, row, p)
       int oldVH = row->visible_height;
       row->visible_height = p->h;
       row->y -= rowY - p->y;
-      x_clip_to_row (w, row, -1, gc);
+      x_clip_to_row (w, row, -1, face->gc);
       row->y = oldY;
       row->visible_height = oldVH;
     }
   else
-    x_clip_to_row (w, row, -1, gc);
+    x_clip_to_row (w, row, -1, face->gc);
 
   if (p->bx >= 0 && !p->overlay_p)
     {
@@ -1466,7 +2063,7 @@ x_draw_fringe_bitmap (w, row, p)
        XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
 #endif
 
-      mac_erase_rectangle (window, face->gc, p->bx, p->by, p->nx, p->ny);
+      mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
 
 #if 0  /* MAC_TODO: stipple */
       if (!face->stipple)
@@ -1474,9 +2071,12 @@ x_draw_fringe_bitmap (w, row, p)
 #endif
     }
 
-  if (p->which)
+  if (p->which
+#if USE_CG_DRAWING
+      && p->which < max_fringe_bmp
+#endif
+      )
     {
-      unsigned short *bits = p->bits + p->dh;
       XGCValues gcv;
 
       XGetGCValues (display, face->gc, GCForeground, &gcv);
@@ -1485,14 +2085,63 @@ x_draw_fringe_bitmap (w, row, p)
                       ? (p->overlay_p ? face->background
                          : f->output_data.mac->cursor_pixel)
                       : face->foreground));
-      mac_draw_bitmap (display, window, face->gc, p->x, p->y,
-                      p->wd, p->h, bits, p->overlay_p);
+#if USE_CG_DRAWING
+      mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
+                        p->wd, p->h, p->x, p->y, p->overlay_p);
+#else
+      mac_draw_bitmap (f, face->gc, p->x, p->y,
+                      p->wd, p->h, p->bits + p->dh, p->overlay_p);
+#endif
       XSetForeground (display, face->gc, gcv.foreground);
     }
 
-  mac_reset_clipping (display, window);
+  mac_reset_clip_rectangles (display, face->gc);
+}
+
+#if USE_CG_DRAWING
+static void
+mac_define_fringe_bitmap (which, bits, h, wd)
+     int which;
+     unsigned short *bits;
+     int h, wd;
+{
+  int i;
+  CGDataProviderRef provider;
+
+  if (which >= max_fringe_bmp)
+    {
+      i = max_fringe_bmp;
+      max_fringe_bmp = which + 20;
+      fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
+      while (i < max_fringe_bmp)
+       fringe_bmp[i++] = 0;
+    }
+
+  for (i = 0; i < h; i++)
+    bits[i] = ~bits[i];
+  provider = CGDataProviderCreateWithData (NULL, bits,
+                                          sizeof (unsigned short) * h, NULL);
+  if (provider)
+    {
+      fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
+                                            sizeof (unsigned short),
+                                            provider, NULL, 0);
+      CGDataProviderRelease (provider);
+    }
 }
 
+static void
+mac_destroy_fringe_bitmap (which)
+     int which;
+{
+  if (which >= max_fringe_bmp)
+    return;
+
+  if (fringe_bmp[which])
+    CGImageRelease (fringe_bmp[which]);
+  fringe_bmp[which] = 0;
+}
+#endif
 \f
 
 /* This is called when starting Emacs and when restarting after
@@ -1526,20 +2175,30 @@ static int mac_encode_char P_ ((int, XChar2b *, struct font_info *,
                                struct charset *, int *));
 
 
-/* Return a pointer to per-char metric information in FONT of a
-   character pointed by B which is a pointer to an XChar2b.  */
-
-#define PER_CHAR_METRIC(font, b)                                          \
-  ((font)->per_char                                                       \
-   ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2                   \
-      + (((font)->min_byte1 || (font)->max_byte1)                         \
-        ? (((b)->byte1 - (font)->min_byte1)                               \
-           * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
-        : 0))                                                             \
-   : &((font)->max_bounds))
-
-
-/* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
+static void
+pcm_init (pcm, count)
+     XCharStruct *pcm;
+     int count;
+{
+  bzero (pcm, sizeof (XCharStruct) * count);
+  while (--count >= 0)
+    {
+      pcm->descent = PCM_INVALID;
+      pcm++;
+    }
+}
+
+static enum pcm_status
+pcm_get_status (pcm)
+     XCharStruct *pcm;
+{
+  int height = pcm->ascent + pcm->descent;
+
+  /* Negative height means some special status.  */
+  return height >= 0 ? PCM_VALID : height;
+}
+
+/* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
    is not contained in the font.  */
 
 static INLINE XCharStruct *
@@ -1552,7 +2211,30 @@ x_per_char_metric (font, char2b)
 
   xassert (font && char2b);
 
-  if (font->per_char != NULL)
+#if USE_ATSUI
+  if (font->mac_style)
+    {
+      XCharStruct **row = font->bounds.rows + char2b->byte1;
+
+      if (*row == NULL)
+       {
+         *row = xmalloc (sizeof (XCharStruct) * 0x100);
+         pcm_init (*row, 0x100);
+       }
+      pcm = *row + char2b->byte2;
+      if (pcm_get_status (pcm) != PCM_VALID)
+       {
+         BLOCK_INPUT;
+         mac_query_char_extents (font->mac_style,
+                                 (char2b->byte1 << 8) + char2b->byte2,
+                                 NULL, NULL, pcm, NULL);
+         UNBLOCK_INPUT;
+       }
+    }
+  else
+    {
+#endif
+  if (font->bounds.per_char != NULL)
     {
       if (font->min_byte1 == 0 && font->max_byte1 == 0)
        {
@@ -1565,7 +2247,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
        {
@@ -1587,7 +2270,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));
@@ -1603,9 +2286,16 @@ x_per_char_metric (font, char2b)
          && char2b->byte2 <= font->max_char_or_byte2)
        pcm = &font->max_bounds;
     }
+#if USE_ATSUI
+    }
+#endif
 
   return ((pcm == NULL
-          || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
+          || (pcm->width == 0
+#if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics.  */
+              && (pcm->rbearing - pcm->lbearing) == 0
+#endif
+              ))
          ? NULL : pcm);
 }
 
@@ -1657,7 +2347,7 @@ mac_encode_char (c, char2b, font_info, charset, two_byte_p)
          ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
        }
 
-      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
 
       /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
@@ -1679,16 +2369,13 @@ mac_encode_char (c, char2b, font_info, charset, two_byte_p)
       if (enc == 1 || enc == 3)
        char2b->byte2 |= 0x80;
 
-      /*
       if (enc == 4)
-        {
-          int sjis1, sjis2;
+       {
+         int code = (char2b->byte1 << 8) | char2b->byte2;
 
-          ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
-          char2b->byte1 = sjis1;
-          char2b->byte2 = sjis2;
-        }
-      */
+         JIS_TO_SJIS (code);
+         STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+       }
     }
 
   if (two_byte_p)
@@ -1725,7 +2412,6 @@ static void x_setup_relief_colors P_ ((struct glyph_string *));
 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
 static void x_draw_image_relief P_ ((struct glyph_string *));
 static void x_draw_image_foreground P_ ((struct glyph_string *));
-static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
@@ -1910,9 +2596,11 @@ static INLINE void
 x_set_glyph_string_clipping (s)
      struct glyph_string *s;
 {
-  Rect r;
-  get_glyph_string_clip_rect (s, &r);
-  mac_set_clip_rectangle (s->display, s->window, &r);
+  Rect rects[MAX_CLIP_RECTS];
+  int n;
+
+  n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
+  mac_set_clip_rectangles (s->display, s->gc, rects, n);
 }
 
 
@@ -1924,8 +2612,23 @@ static void
 mac_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-  if (s->cmp == NULL
-      && s->first_glyph->type == CHAR_GLYPH)
+  if (!(s->cmp == NULL
+       && s->first_glyph->type == CHAR_GLYPH))
+    return;
+
+  if (!s->two_byte_p
+#if USE_ATSUI
+      || s->font->mac_style
+#endif
+      )
+    {
+      XCharStruct cs;
+
+      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;
@@ -1934,23 +2637,7 @@ mac_compute_glyph_string_overhangs (s)
       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);
-           }
-       }
+      QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
 
       s->right_overhang = r.right > s->width ? r.right - s->width : 0;
       s->left_overhang = r.left < 0 ? -r.left : 0;
@@ -1965,18 +2652,10 @@ x_clear_glyph_string_rect (s, x, y, w, h)
      struct glyph_string *s;
      int x, y, w, h;
 {
-  mac_erase_rectangle (s->window, s->gc, x, y, w, h);
+  mac_erase_rectangle (s->f, s->gc, 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
@@ -2008,12 +2687,10 @@ x_draw_glyph_string_background (s, force_p)
        }
       else
 #endif
-#ifdef MAC_OS8
         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,
@@ -2030,7 +2707,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.  */
@@ -2047,9 +2724,8 @@ x_draw_glyph_string_foreground (s)
       for (i = 0; i < s->nchars; ++i)
        {
          struct glyph *g = s->first_glyph + i;
-         mac_draw_rectangle (s->display, s->window,
-                           s->gc, x, s->y, g->pixel_width - 1,
-                           s->height - 1);
+         mac_draw_rectangle (s->f, s->gc, x, s->y,
+                             g->pixel_width - 1, s->height - 1);
          x += g->pixel_width;
        }
     }
@@ -2062,39 +2738,42 @@ x_draw_glyph_string_foreground (s)
        boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
 
       /* If we can use 8-bit functions, condense S->char2b.  */
-      if (!s->two_byte_p)
+      if (!s->two_byte_p
+#if USE_ATSUI
+         && GC_FONT (s->gc)->mac_style == NULL
+#endif
+         )
        for (i = 0; i < s->nchars; ++i)
          char1b[i] = s->char2b[i].byte2;
 
-#ifdef MAC_OS8
       /* Draw text with XDrawString if background has already been
         filled.  Otherwise, use XDrawImageString.  (Note that
         XDrawImageString is usually faster than XDrawString.)  Always
         use XDrawImageString when drawing the cursor so that there is
         no chance that characters under a box cursor are invisible.  */
-      if (s->for_overlaps_p
+      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)
-           XDrawString16 (s->display, s->window, s->gc, x,
-                          s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawString (s->display, s->window, s->gc, x,
-                        s->ybase - boff, char1b, s->nchars);
-       }
-#ifdef MAC_OS8
+       bg_width = 0;           /* Corresponds to XDrawString.  */
       else
-       {
-         if (s->two_byte_p)
-           XDrawImageString16 (s->display, s->window, s->gc, x,
-                               s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawImageString (s->display, s->window, s->gc, x,
-                             s->ybase - boff, char1b, s->nchars);
-       }
+       bg_width = s->background_width; /* Corresponds to XDrawImageString.  */
+
+      if (s->two_byte_p
+#if USE_ATSUI
+         || GC_FONT (s->gc)->mac_style
+#endif
+         )
+#if USE_CG_TEXT_DRAWING
+       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_image_string_16 (s->f, s->gc, x, s->ybase - boff,
+                                   s->char2b, s->nchars, bg_width);
+      else
+       mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
+                              char1b, s->nchars, bg_width);
     }
 }
 
@@ -2124,16 +2803,16 @@ x_draw_composite_glyph_string_foreground (s)
   if (s->font_not_found_p)
     {
       if (s->gidx == 0)
-       mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
-                         s->width - 1, s->height - 1);
+       mac_draw_rectangle (s->f, s->gc, x, s->y,
+                           s->width - 1, s->height - 1);
     }
   else
     {
       for (i = 0; i < s->nchars; i++, ++s->gidx)
-       XDrawString16 (s->display, s->window, s->gc,
-                      x + s->cmp->offsets[s->gidx * 2],
-                      s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                      s->char2b + i, 1);
+       mac_draw_string_16 (s->f, s->gc,
+                           x + s->cmp->offsets[s->gidx * 2],
+                           s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
+                           s->char2b + i, 1);
     }
 }
 
@@ -2489,7 +3168,6 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
      Rect *clip_rect;
 {
   Display *dpy = FRAME_MAC_DISPLAY (f);
-  Window window = FRAME_MAC_WINDOW (f);
   int i;
   GC gc;
 
@@ -2497,43 +3175,42 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
     gc = f->output_data.mac->white_relief.gc;
   else
     gc = f->output_data.mac->black_relief.gc;
-  mac_set_clip_rectangle (dpy, window, clip_rect);
+  mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
 
   /* Top.  */
   if (top_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                left_x + i * left_p, top_y + i,
-                right_x - i * right_p, top_y + i);
+      mac_draw_line (f, gc,
+                    left_x + i * left_p, top_y + i,
+                    right_x + 1 - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                left_x + i, top_y + i, left_x + i, bottom_y - i);
+      mac_draw_line (f, gc,
+                    left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
 
-  mac_reset_clipping (dpy, window);
+  mac_reset_clip_rectangles (dpy, gc);
   if (raised_p)
     gc = f->output_data.mac->black_relief.gc;
   else
     gc = f->output_data.mac->white_relief.gc;
-  mac_set_clip_rectangle (dpy, window,
-                         clip_rect);
+  mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
 
   /* Bottom.  */
   if (bot_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                left_x + i * left_p, bottom_y - i,
-                right_x - i * right_p, bottom_y - i);
+      mac_draw_line (f, gc,
+                    left_x + i * left_p, bottom_y - i,
+                    right_x + 1 - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
+      mac_draw_line (f, gc,
+                    right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
 
-  mac_reset_clipping (dpy, window);
+  mac_reset_clip_rectangles (dpy, gc);
 }
 
 
@@ -2555,28 +3232,28 @@ x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
 
   XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
   XSetForeground (s->display, s->gc, s->face->box_color);
-  mac_set_clip_rectangle (s->display, s->window, clip_rect);
+  mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
 
   /* Top.  */
-  XFillRectangle (s->display, s->window, s->gc,
-                 left_x, top_y, right_x - left_x + 1, width);
+  mac_fill_rectangle (s->f, s->gc, left_x, top_y,
+                     right_x - left_x + 1, width);
 
   /* Left.  */
   if (left_p)
-    XFillRectangle (s->display, s->window, s->gc,
-                   left_x, top_y, width, bottom_y - top_y + 1);
+    mac_fill_rectangle (s->f, s->gc, left_x, top_y,
+                       width, bottom_y - top_y + 1);
 
   /* Bottom.  */
-  XFillRectangle (s->display, s->window, s->gc,
-                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+  mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
+                     right_x - left_x + 1, width);
 
   /* Right.  */
   if (right_p)
-    XFillRectangle (s->display, s->window, s->gc,
-                   right_x - width + 1, top_y, width, bottom_y - top_y + 1);
+    mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
+                       top_y, width, bottom_y - top_y + 1);
 
   XSetForeground (s->display, s->gc, xgcv.foreground);
-  mac_reset_clipping (s->display, s->window);
+  mac_reset_clip_rectangles (s->display, s->gc);
 }
 
 
@@ -2659,15 +3336,26 @@ x_draw_image_foreground (s)
     {
       x_set_glyph_string_clipping (s);
 
+#if USE_CG_DRAWING
+      mac_draw_cg_image (s->img->data.ptr_val,
+                        s->f, s->gc, s->slice.x, s->slice.y,
+                        s->slice.width, s->slice.height, x, y, 1);
+#endif
       if (s->img->mask)
-       mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
-                                s->window, s->gc, s->slice.x, s->slice.y,
+#if !USE_CG_DRAWING
+       mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
+                                s->f, s->gc, s->slice.x, s->slice.y,
                                 s->slice.width, s->slice.height, x, y);
+#else
+       ;
+#endif
       else
        {
-         mac_copy_area (s->display, s->img->pixmap,
-                        s->window, s->gc, s->slice.x, s->slice.y,
+#if !USE_CG_DRAWING
+         mac_copy_area (s->img->pixmap,
+                        s->f, s->gc, s->slice.x, s->slice.y,
                         s->slice.width, s->slice.height, x, y);
+#endif
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2679,8 +3367,7 @@ x_draw_image_foreground (s)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             mac_draw_rectangle (s->display, s->window, s->gc,
-                                 x - r, y - r,
+             mac_draw_rectangle (s->f, s->gc, x - r, y - r,
                                  s->slice.width + r*2 - 1,
                                  s->slice.height + r*2 - 1);
            }
@@ -2688,7 +3375,7 @@ x_draw_image_foreground (s)
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
-    mac_draw_rectangle (s->display, s->window, s->gc, x, y,
+    mac_draw_rectangle (s->f, s->gc, x, y,
                        s->slice.width - 1, s->slice.height - 1);
 }
 
@@ -2746,70 +3433,6 @@ x_draw_image_relief (s)
 }
 
 
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-/* Draw the foreground of image glyph string S to PIXMAP.  */
-
-static void
-x_draw_image_foreground_1 (s, pixmap)
-     struct glyph_string *s;
-     Pixmap pixmap;
-{
-  int x = 0;
-  int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
-
-  /* If first glyph of S has a left box line, start drawing it to the
-     right of that line.  */
-  if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p
-      && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
-
-  /* If there is a margin around the image, adjust x- and y-position
-     by that margin.  */
-  if (s->slice.x == 0)
-    x += s->img->hmargin;
-  if (s->slice.y == 0)
-    y += s->img->vmargin;
-
-  if (s->img->pixmap)
-    {
-      if (s->img->mask)
-       mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
-                                          s->img->mask, pixmap, s->gc,
-                                          s->slice.x, s->slice.y,
-                                          s->slice.width, s->slice.height,
-                                          x, y);
-      else
-       {
-         mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
-                                  s->slice.x, s->slice.y,
-                                  s->slice.width, s->slice.height,
-                                  x, y);
-
-         /* When the image has a mask, we can expect that at
-            least part of a mouse highlight or a block cursor will
-            be visible.  If the image doesn't have a mask, make
-            a block cursor visible by drawing a rectangle around
-            the image.  I believe it's looking better if we do
-            nothing here for mouse-face.  */
-         if (s->hl == DRAW_CURSOR)
-           {
-             int r = s->img->relief;
-             if (r < 0) r = -r;
-             mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
-                                 s->slice.width + r*2 - 1,
-                                 s->slice.height + r*2 - 1);
-           }
-       }
-    }
-  else
-    /* Draw a rectangle if image could not be loaded.  */
-    mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
-                                 s->slice.width - 1, s->slice.height - 1);
-}
-#endif
-
-
 /* Draw part of the background of glyph string S.  X, Y, W, and H
    give the rectangle to draw.  */
 
@@ -2854,7 +3477,6 @@ x_draw_image_glyph_string (s)
   int box_line_hwidth = abs (s->face->box_line_width);
   int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
-  Pixmap pixmap = 0;
 
   height = s->height - 2 * box_line_vwidth;
 
@@ -2879,63 +3501,13 @@ x_draw_image_glyph_string (s)
       if (s->slice.y == 0)
        y += box_line_vwidth;
 
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-      if (s->img->mask)
-       {
-         /* Create a pixmap as large as the glyph string.  Fill it
-            with the background color.  Copy the image to it, using
-            its mask.  Copy the temporary pixmap to the display.  */
-         int depth = one_mac_display_info.n_planes;
-
-         /* Create a pixmap as large as the glyph string.  */
-         pixmap = XCreatePixmap (s->display, s->window,
-                                 s->background_width,
-                                 s->height, depth);
-
-         /* Fill the pixmap with the background color/stipple.  */
-#if 0 /* TODO: stipple */
-         if (s->stippled_p)
-           {
-             /* Fill background with a stipple pattern.  */
-             XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
-             XFillRectangle (s->display, pixmap, s->gc,
-                             0, 0, s->background_width, s->height);
-             XSetFillStyle (s->display, s->gc, FillSolid);
-           }
-         else
-#endif
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
-                           &xgcv);
-             XSetForeground (s->display, s->gc, xgcv.background);
-             mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
-                                           0, 0, s->background_width,
-                                           s->height);
-             XSetForeground (s->display, s->gc, xgcv.foreground);
-           }
-       }
-      else
-#endif
-       x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+      x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
 
       s->background_filled_p = 1;
     }
 
   /* Draw the foreground.  */
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-  if (pixmap != 0)
-    {
-      x_draw_image_foreground_1 (s, pixmap);
-      x_set_glyph_string_clipping (s);
-      mac_copy_area (s->display, pixmap, s->window, s->gc,
-                    0, 0, s->background_width, s->height, s->x, s->y);
-      mac_reset_clipping (s->display, s->window);
-      XFreePixmap (s->display, pixmap);
-    }
-  else
-#endif
-    x_draw_image_foreground (s);
+  x_draw_image_foreground (s);
 
   /* If we must draw a relief around the image, do it.  */
   if (s->img->relief
@@ -2959,19 +3531,28 @@ x_draw_stretch_glyph_string (s)
     {
       /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
         as wide as the stretch glyph.  */
-      int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
+      int width, background_width = s->background_width;
+      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+      if (x < left_x)
+       {
+         background_width -= left_x - x;
+         x = left_x;
+       }
+      width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
 
       /* Draw cursor.  */
-      x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
+      x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
 
       /* Clear rest using the GC of the original non-cursor face.  */
-      if (width < s->background_width)
+      if (width < background_width)
        {
-         int x = s->x + width, y = s->y;
-         int w = s->background_width - width, h = s->height;
+         int y = s->y;
+         int w = background_width - width, h = s->height;
          Rect r;
          GC gc;
 
+         x += width;
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
            {
@@ -2982,7 +3563,7 @@ x_draw_stretch_glyph_string (s)
            gc = s->face->gc;
 
          get_glyph_string_clip_rect (s, &r);
-         mac_set_clip_rectangle (s->display, s->window, &r);
+         mac_set_clip_rectangles (s->display, gc, &r, 1);
 
 #if 0 /* MAC_TODO: stipple */
          if (s->face->stipple)
@@ -2994,14 +3575,22 @@ x_draw_stretch_glyph_string (s)
            }
          else
 #endif /* MAC_TODO */
-           mac_erase_rectangle (s->window, gc, x, y, w, h);
-
-         mac_reset_clipping (s->display, s->window);
+           mac_erase_rectangle (s->f, gc, x, y, w, h);
        }
     }
   else if (!s->background_filled_p)
-    x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
-                                s->height);
+    {
+      int background_width = s->background_width;
+      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+      if (x < left_x)
+       {
+         background_width -= left_x - x;
+         x = left_x;
+       }
+      if (background_width > 0)
+       x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
+    }
 
   s->background_filled_p = 1;
 }
@@ -3019,7 +3608,7 @@ x_draw_glyph_string (s)
      draw a cursor, draw the background of the successor first so that
      S can draw into it.  This makes S->next use XDrawString instead
      of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps_p
+  if (s->next && s->right_overhang && !s->for_overlaps
       && s->next->hl != DRAW_CURSOR)
     {
       xassert (s->next->img == NULL);
@@ -3033,7 +3622,7 @@ x_draw_glyph_string (s)
 
   /* Draw relief (if any) in advance for char/composition so that the
      glyph string can be drawn over it.  */
-  if (!s->for_overlaps_p
+  if (!s->for_overlaps
       && s->face->box != FACE_NO_BOX
       && (s->first_glyph->type == CHAR_GLYPH
          || s->first_glyph->type == COMPOSITE_GLYPH))
@@ -3059,7 +3648,7 @@ x_draw_glyph_string (s)
       break;
 
     case CHAR_GLYPH:
-      if (s->for_overlaps_p)
+      if (s->for_overlaps)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 0);
@@ -3067,7 +3656,7 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps_p || s->gidx > 0)
+      if (s->for_overlaps || s->gidx > 0)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -3078,7 +3667,7 @@ x_draw_glyph_string (s)
       abort ();
     }
 
-  if (!s->for_overlaps_p)
+  if (!s->for_overlaps)
     {
       /* Draw underline.  */
       if (s->face->underline_p)
@@ -3087,15 +3676,15 @@ x_draw_glyph_string (s)
           unsigned long dy = s->height - h;
 
          if (s->face->underline_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
+           mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                               s->width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->underline_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
+             mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                                 s->width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3106,15 +3695,15 @@ x_draw_glyph_string (s)
          unsigned long dy = 0, h = 1;
 
          if (s->face->overline_color_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
+           mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                               s->width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->overline_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
+             mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                                 s->width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3126,15 +3715,15 @@ x_draw_glyph_string (s)
          unsigned long dy = (s->height - h) / 2;
 
          if (s->face->strike_through_color_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
+           mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                               s->width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->strike_through_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
+             mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                                 s->width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3145,7 +3734,7 @@ x_draw_glyph_string (s)
     }
 
   /* Reset clipping.  */
-  mac_reset_clipping (s->display, s->window);
+  mac_reset_clip_rectangles (s->display, s->gc);
 }
 
 /* Shift display to make room for inserted glyphs.   */
@@ -3155,8 +3744,7 @@ mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
      struct frame *f;
      int x, y, width, height, shift_by;
 {
-  mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                  f->output_data.mac->normal_gc,
+  mac_scroll_area (f, f->output_data.mac->normal_gc,
                   x, y, width, height,
                   x + shift_by, y);
 }
@@ -3194,7 +3782,7 @@ x_clear_frame ()
   /* We don't set the output cursor here because there will always
      follow an explicit cursor_to.  */
   BLOCK_INPUT;
-  XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+  mac_clear_window (f);
 
   /* We have to clear the scroll bars, too.  If we have changed
      colors or something like that, then they should be notified.  */
@@ -3251,9 +3839,54 @@ void
 XTflash (f)
      struct frame *f;
 {
+  /* Get the height not including a menu bar widget.  */
+  int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
+  /* Height of each line to flash.  */
+  int flash_height = FRAME_LINE_HEIGHT (f);
+  /* These will be the left and right margins of the rectangles.  */
+  int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
+  int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
+
+  int width;
+
+  /* Don't flash the area between a scroll bar and the frame
+     edge it is next to.  */
+  switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
+    {
+    case vertical_scroll_bar_left:
+      flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+      break;
+
+    case vertical_scroll_bar_right:
+      flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+      break;
+
+    default:
+      break;
+    }
+
+  width = flash_right - flash_left;
+
   BLOCK_INPUT;
 
-  FlashMenuBar (0);
+  /* If window is tall, flash top and bottom line.  */
+  if (height > 3 * FRAME_LINE_HEIGHT (f))
+    {
+      mac_invert_rectangle (f, flash_left,
+                           (FRAME_INTERNAL_BORDER_WIDTH (f)
+                            + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
+                           width, flash_height);
+      mac_invert_rectangle (f, flash_left,
+                           (height - flash_height
+                            - FRAME_INTERNAL_BORDER_WIDTH (f)),
+                           width, flash_height);
+    }
+  else
+    /* If it is short, flash it all.  */
+    mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                         width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+
+  x_flush (f);
 
   {
     struct timeval wakeup;
@@ -3265,24 +3898,46 @@ XTflash (f)
     wakeup.tv_sec += (wakeup.tv_usec / 1000000);
     wakeup.tv_usec %= 1000000;
 
-    /* Keep waiting until past the time wakeup.  */
-    while (1)
+    /* Keep waiting until past the time wakeup or any input gets
+       available.  */
+    while (! detect_input_pending ())
       {
-        struct timeval timeout;
+       struct timeval current;
+       struct timeval timeout;
+
+       EMACS_GET_TIME (current);
 
-        EMACS_GET_TIME (timeout);
+       /* Break if result would be negative.  */
+       if (timeval_subtract (&current, wakeup, current))
+         break;
 
-        /* In effect, timeout = wakeup - timeout.
-           Break if result would be negative.  */
-        if (timeval_subtract (&timeout, wakeup, timeout))
-          break;
+       /* How long `select' should wait.  */
+       timeout.tv_sec = 0;
+       timeout.tv_usec = 10000;
 
-        /* Try to wait that long--but we might wake up sooner.  */
-        select (0, NULL, NULL, NULL, &timeout);
+       /* Try to wait that long--but we might wake up sooner.  */
+       select (0, NULL, NULL, NULL, &timeout);
       }
   }
 
-  FlashMenuBar (0);
+  /* If window is tall, flash top and bottom line.  */
+  if (height > 3 * FRAME_LINE_HEIGHT (f))
+    {
+      mac_invert_rectangle (f, flash_left,
+                           (FRAME_INTERNAL_BORDER_WIDTH (f)
+                            + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
+                           width, flash_height);
+      mac_invert_rectangle (f, flash_left,
+                           (height - flash_height
+                            - FRAME_INTERNAL_BORDER_WIDTH (f)),
+                           width, flash_height);
+    }
+  else
+    /* If it is short, flash it all.  */
+    mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                         width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+
+  x_flush (f);
 
   UNBLOCK_INPUT;
 }
@@ -3384,11 +4039,10 @@ x_scroll_run (w, run)
   updated_window = w;
   x_clear_cursor (w);
 
-  mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                f->output_data.mac->normal_gc,
-                x, from_y,
-                width, height,
-                x, to_y);
+  mac_scroll_area (f, f->output_data.mac->normal_gc,
+                  x, from_y,
+                  width, height,
+                  x, to_y);
 
   UNBLOCK_INPUT;
 }
@@ -3464,6 +4118,11 @@ x_new_focus_frame (dpyinfo, frame)
        pending_autoraise_frame = dpyinfo->x_focus_frame;
       else
        pending_autoraise_frame = 0;
+
+#if USE_MAC_FONT_PANEL
+      if (frame)
+       mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
+#endif
     }
 
   x_frame_rehighlight (dpyinfo);
@@ -3587,142 +4246,6 @@ x_frame_rehighlight (dpyinfo)
 
 
 \f
-/* Keyboard processing - modifier keys, vendor-specific keysyms, etc.  */
-
-#if 0 /* MAC_TODO */
-/* Initialize mode_switch_bit and modifier_meaning.  */
-static void
-x_find_modifier_meanings (dpyinfo)
-     struct x_display_info *dpyinfo;
-{
-  int min_code, max_code;
-  KeySym *syms;
-  int syms_per_code;
-  XModifierKeymap *mods;
-
-  dpyinfo->meta_mod_mask = 0;
-  dpyinfo->shift_lock_mask = 0;
-  dpyinfo->alt_mod_mask = 0;
-  dpyinfo->super_mod_mask = 0;
-  dpyinfo->hyper_mod_mask = 0;
-
-#ifdef HAVE_X11R4
-  XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-#else
-  min_code = dpyinfo->display->min_keycode;
-  max_code = dpyinfo->display->max_keycode;
-#endif
-
-  syms = XGetKeyboardMapping (dpyinfo->display,
-                             min_code, max_code - min_code + 1,
-                             &syms_per_code);
-  mods = XGetModifierMapping (dpyinfo->display);
-
-  /* Scan the modifier table to see which modifier bits the Meta and
-     Alt keysyms are on.  */
-  {
-    int row, col;      /* The row and column in the modifier table.  */
-
-    for (row = 3; row < 8; row++)
-      for (col = 0; col < mods->max_keypermod; col++)
-       {
-         KeyCode code
-           = mods->modifiermap[(row * mods->max_keypermod) + col];
-
-         /* Zeroes are used for filler.  Skip them.  */
-         if (code == 0)
-           continue;
-
-         /* Are any of this keycode's keysyms a meta key?  */
-         {
-           int code_col;
-
-           for (code_col = 0; code_col < syms_per_code; code_col++)
-             {
-               int sym = syms[((code - min_code) * syms_per_code) + code_col];
-
-               switch (sym)
-                 {
-                 case XK_Meta_L:
-                 case XK_Meta_R:
-                   dpyinfo->meta_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Alt_L:
-                 case XK_Alt_R:
-                   dpyinfo->alt_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Hyper_L:
-                 case XK_Hyper_R:
-                   dpyinfo->hyper_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Super_L:
-                 case XK_Super_R:
-                   dpyinfo->super_mod_mask |= (1 << row);
-                   break;
-
-                 case XK_Shift_Lock:
-                   /* Ignore this if it's not on the lock modifier.  */
-                   if ((1 << row) == LockMask)
-                     dpyinfo->shift_lock_mask = LockMask;
-                   break;
-                 }
-             }
-         }
-       }
-  }
-
-  /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
-  if (! dpyinfo->meta_mod_mask)
-    {
-      dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
-      dpyinfo->alt_mod_mask = 0;
-    }
-
-  /* If some keys are both alt and meta,
-     make them just meta, not alt.  */
-  if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
-    {
-      dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
-    }
-
-  XFree ((char *) syms);
-  XFreeModifiermap (mods);
-}
-
-#endif /* MAC_TODO */
-
-/* Convert between the modifier bits X uses and the modifier bits
-   Emacs uses.  */
-
-static unsigned int
-x_mac_to_emacs_modifiers (dpyinfo, state)
-     struct x_display_info *dpyinfo;
-     unsigned short state;
-{
-  return (((state & shiftKey) ? shift_modifier : 0)
-         | ((state & controlKey) ? ctrl_modifier : 0)
-         | ((state & cmdKey) ? meta_modifier : 0)
-         | ((state & optionKey) ? alt_modifier : 0));
-}
-
-#if 0 /* MAC_TODO */
-static unsigned short
-x_emacs_to_x_modifiers (dpyinfo, state)
-     struct x_display_info *dpyinfo;
-     unsigned int state;
-{
-  return (  ((state & alt_modifier)    ? dpyinfo->alt_mod_mask   : 0)
-         | ((state & super_modifier)   ? dpyinfo->super_mod_mask : 0)
-         | ((state & hyper_modifier)   ? dpyinfo->hyper_mod_mask : 0)
-         | ((state & shift_modifier)   ? ShiftMask        : 0)
-         | ((state & ctrl_modifier)    ? ControlMask      : 0)
-         | ((state & meta_modifier)    ? dpyinfo->meta_mod_mask  : 0));
-}
-#endif /* MAC_TODO */
-
 /* Convert a keysym to its name.  */
 
 char *
@@ -3755,7 +4278,7 @@ x_get_keysym_name (keysym)
 static Point last_mouse_motion_position;
 static Lisp_Object last_mouse_motion_frame;
 
-static void
+static int
 note_mouse_movement (frame, pos)
      FRAME_PTR frame;
      Point *pos;
@@ -3786,17 +4309,22 @@ note_mouse_movement (frame, pos)
            rif->define_frame_cursor (frame,
                                      frame->output_data.mac->nontext_cursor);
        }
+      return 1;
     }
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (pos->h < last_mouse_glyph.left
-          || pos->h >= last_mouse_glyph.right
-          || pos->v < last_mouse_glyph.top
-          || pos->v >= last_mouse_glyph.bottom)
+  if (frame != last_mouse_glyph_frame
+      || !PtInRect (*pos, &last_mouse_glyph))
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, pos->h, pos->v);
+      /* Remember which glyph we're now on.  */
+      remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
+      last_mouse_glyph_frame = frame;
+      return 1;
     }
+
+  return 0;
 }
 
 \f
@@ -3804,9 +4332,6 @@ note_mouse_movement (frame, pos)
                              Mouse Face
  ************************************************************************/
 
-static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
-
-
 /* MAC TODO:  This should be called from somewhere (or removed)  ++KFS */
 
 static void
@@ -3820,137 +4345,33 @@ redo_mouse_highlight ()
 }
 
 
-/* Try to determine frame pixel position and size of the glyph under
-   frame pixel coordinates X/Y on frame F .  Return the position and
-   size in *RECT.  Value is non-zero if we could compute these
-   values.  */
-
-static int
-glyph_rect (f, x, y, rect)
-     struct frame *f;
-     int x, y;
-     Rect *rect;
+static struct frame *
+mac_focus_frame (dpyinfo)
+     struct mac_display_info *dpyinfo;
 {
-  Lisp_Object window;
+  if (dpyinfo->x_focus_frame)
+    return dpyinfo->x_focus_frame;
+  else
+    /* Mac version may get events, such as a menu bar click, even when
+       all the frames are invisible.  In this case, we regard the
+       event came to the selected frame.  */
+    return SELECTED_FRAME ();
+}
 
-  window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
 
-  if (!NILP (window))
-    {
-      struct window *w = XWINDOW (window);
-      struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-      struct glyph_row *end = r + w->current_matrix->nrows - 1;
+/* Return the current position of the mouse.
+   *FP should be a frame which indicates which display to ask about.
 
-      for (; r < end && r->enabled_p; ++r)
-       if (r->y <= y && r->y + r->height > y)
-         {
-           /* Found the row at y.  */
-           struct glyph *g = r->glyphs[TEXT_AREA];
-           struct glyph *end = g + r->used[TEXT_AREA];
-           int gx;
+   If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
+   and *PART to the frame, window, and scroll bar part that the mouse
+   is over.  Set *X and *Y to the portion and whole of the mouse's
+   position on the scroll bar.
 
-           rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
-           rect->bottom = rect->top + r->height;
+   If the mouse movement started elsewhere, set *FP to the frame the
+   mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
+   the mouse is over.
 
-           if (x < r->x)
-             {
-               /* x is to the left of the first glyph in the row.  */
-               /* Shouldn't this be a pixel value?
-                  WINDOW_LEFT_EDGE_X (w) seems to be the right value.
-                  ++KFS */
-               rect->left = WINDOW_LEFT_EDGE_COL (w);
-               rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
-               return 1;
-             }
-
-           for (gx = r->x; g < end; gx += g->pixel_width, ++g)
-             if (gx <= x && gx + g->pixel_width > x)
-               {
-                 /* x is on a glyph.  */
-                 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-                 rect->right = rect->left + g->pixel_width;
-                 return 1;
-               }
-
-           /* x is to the right of the last glyph in the row.  */
-           rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-           /* Shouldn't this be a pixel value?
-              WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
-              ++KFS */
-           rect->right = WINDOW_RIGHT_EDGE_COL (w);
-           return 1;
-         }
-    }
-
-  /* The y is not on any row.  */
-  return 0;
-}
-
-/* MAC TODO:  This should be called from somewhere (or removed)  ++KFS */
-
-/* Record the position of the mouse in last_mouse_glyph.  */
-static void
-remember_mouse_glyph (f1, gx, gy)
-     struct frame * f1;
-     int gx, gy;
-{
-  if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
-    {
-      int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
-      int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-
-      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
-        round down even for negative values.  */
-      if (gx < 0)
-       gx -= width - 1;
-      if (gy < 0)
-       gy -= height - 1;
-#if 0
-      /* This was the original code from XTmouse_position, but it seems
-        to give the position of the glyph diagonally next to the one
-        the mouse is over.  */
-      gx = (gx + width - 1) / width * width;
-      gy = (gy + height - 1) / height * height;
-#else
-      gx = gx / width * width;
-      gy = gy / height * height;
-#endif
-
-      last_mouse_glyph.left = gx;
-      last_mouse_glyph.top = gy;
-      last_mouse_glyph.right  = gx + width;
-      last_mouse_glyph.bottom = gy + height;
-    }
-}
-
-
-static struct frame *
-mac_focus_frame (dpyinfo)
-     struct mac_display_info *dpyinfo;
-{
-  if (dpyinfo->x_focus_frame)
-    return dpyinfo->x_focus_frame;
-  else
-    /* Mac version may get events, such as a menu bar click, even when
-       all the frames are invisible.  In this case, we regard the
-       event came to the selected frame.  */
-    return SELECTED_FRAME ();
-}
-
-
-/* Return the current position of the mouse.
-   *fp should be a frame which indicates which display to ask about.
-
-   If the mouse movement started in a scroll bar, set *fp, *bar_window,
-   and *part to the frame, window, and scroll bar part that the mouse
-   is over.  Set *x and *y to the portion and whole of the mouse's
-   position on the scroll bar.
-
-   If the mouse movement started elsewhere, set *fp to the frame the
-   mouse is on, *bar_window to nil, and *x and *y to the character cell
-   the mouse is over.
-
-   Set *time to the server time-stamp for the time at which the mouse
+   Set *TIME to the server time-stamp for the time at which the mouse
    was at this position.
 
    Don't store anything if we don't have a valid set of values to report.
@@ -3967,11 +4388,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
      Lisp_Object *x, *y;
      unsigned long *time;
 {
-  Point mouse_pos;
-  int ignore1, ignore2;
-  struct frame *f = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
-  WindowPtr wp = FRAME_MAC_WINDOW (f);
-  Lisp_Object frame, tail;
+  FRAME_PTR f1;
 
   BLOCK_INPUT;
 
@@ -3979,25 +4396,44 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
     x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
   else
     {
+      Lisp_Object frame, tail;
+
       /* Clear the mouse-moved flag for every frame on this display.  */
       FOR_EACH_FRAME (tail, frame)
-        XFRAME (frame)->mouse_moved = 0;
+       XFRAME (frame)->mouse_moved = 0;
 
       last_mouse_scroll_bar = Qnil;
 
-      SetPortWindowPort (wp);
-
-      GetMouse (&mouse_pos);
-
-      pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
-                             &last_mouse_glyph, insist);
+      if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
+         && FRAME_LIVE_P (last_mouse_frame))
+       f1 = last_mouse_frame;
+      else
+       f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
 
-      *bar_window = Qnil;
-      *part = scroll_bar_handle;
-      *fp = f;
-      XSETINT (*x, mouse_pos.h);
-      XSETINT (*y, mouse_pos.v);
-      *time = last_mouse_movement_time;
+      if (f1)
+       {
+         /* Ok, we found a frame.  Store all the values.
+            last_mouse_glyph is a rectangle used to reduce the
+            generation of mouse events.  To not miss any motion
+            events, we must divide the frame into rectangles of the
+            size of the smallest character that could be displayed
+            on it, i.e. into the same rectangles that matrices on
+            the frame are divided into.  */
+         Point mouse_pos;
+
+         SetPortWindowPort (FRAME_MAC_WINDOW (f1));
+         GetMouse (&mouse_pos);
+         remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
+                               &last_mouse_glyph);
+         last_mouse_glyph_frame = f1;
+
+         *bar_window = Qnil;
+         *part = 0;
+         *fp = f1;
+         XSETINT (*x, mouse_pos.h);
+         XSETINT (*y, mouse_pos.v);
+         *time = last_mouse_movement_time;
+       }
     }
 
   UNBLOCK_INPUT;
@@ -4016,8 +4452,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 *));
@@ -4044,35 +4480,11 @@ scroll_bar_timer_callback (timer, data)
      EventLoopTimerRef timer;
      void *data;
 {
-  EventRef event = NULL;
-  OSErr err;
-
-  err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
-                    kEventAttributeNone, &event);
-  if (err == noErr)
-    {
-      Point mouse_pos;
-
-      GetMouse (&mouse_pos);
-      LocalToGlobal (&mouse_pos);
-      err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
-                              sizeof (Point), &mouse_pos);
-    }
-  if (err == noErr)
-    {
-      UInt32 modifiers = GetCurrentKeyModifiers ();
+  OSStatus err;
 
-      err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
-                              sizeof (UInt32), &modifiers);
-    }
-  if (err == noErr)
-    err = PostEventToQueue (GetCurrentEventQueue (), event,
-                           kEventPriorityStandard);
+  err = mac_post_mouse_moved_event ();
   if (err == noErr)
     scroll_bar_timer_event_posted_p = 1;
-
-  if (event)
-    ReleaseEvent (event);
 }
 
 static OSStatus
@@ -4138,7 +4550,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;
@@ -4280,10 +4692,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
     {
@@ -4294,10 +4708,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;
 }
@@ -4333,8 +4756,16 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
   r.right = left + width;
   r.bottom = disp_top + disp_height;
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
 #if TARGET_API_MAC_CARBON
-  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
+  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
+#if USE_TOOLKIT_SCROLL_BARS
+                  false,
+#else
+                  width < disp_height,
+#endif
                   0, 0, 0, kControlScrollBarProc, (long) bar);
 #else
   ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
@@ -4454,6 +4885,9 @@ x_scroll_bar_remove (bar)
 
   BLOCK_INPUT;
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   /* Destroy the Mac scroll bar control  */
   DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
 
@@ -4504,6 +4938,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;
@@ -4517,13 +4952,13 @@ 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))
     {
       BLOCK_INPUT;
-      XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 left, top, width, height, 0);
+      mac_clear_area (f, left, top, width, height);
       UNBLOCK_INPUT;
       bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
                                 disp_height);
@@ -4547,21 +4982,19 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
        {
          /* Since toolkit scroll bars are smaller than the space reserved
             for them on the frame, we have to clear "under" them.  */
-         XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                     left, top, width, height, 0);
+         mac_clear_area (f, left, top, width, height);
 
-#if 0
-          if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
-            XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                       sb_left - 1, top, 1, height, 0);
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
 #endif
-
           HideControl (ch);
           MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
           SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                       disp_height);
+#ifndef USE_TOOLKIT_SCROLL_BARS
          if (sb_width < disp_height)
            ShowControl (ch);
+#endif
 
           /* Remember new settings.  */
           XSETINT (bar->left, sb_left);
@@ -4580,28 +5013,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);
@@ -4945,7 +5391,7 @@ x_clip_to_row (w, row, area, gc)
   clip_rect.right = clip_rect.left + window_width;
   clip_rect.bottom = clip_rect.top + row->visible_height;
 
-  mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
+  mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
 }
 
 
@@ -4971,8 +5417,7 @@ x_draw_hollow_cursor (w, row)
     return;
 
   /* 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);
+  get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
   wd = w->phys_cursor_width;
 
   /* The foreground of cursor_gc is typically the same as the normal
@@ -4987,8 +5432,8 @@ x_draw_hollow_cursor (w, row)
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
   x_clip_to_row (w, row, TEXT_AREA, gc);
-  mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
-  mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
+  mac_draw_rectangle (f, gc, x, y, wd, h - 1);
+  mac_reset_clip_rectangles (dpy, gc);
 }
 
 
@@ -5060,19 +5505,19 @@ x_draw_bar_cursor (w, row, width, kind)
       x_clip_to_row (w, row, TEXT_AREA, gc);
 
       if (kind == BAR_CURSOR)
-       XFillRectangle (dpy, window, gc,
-                       WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
-                       WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                       width, row->height);
+       mac_fill_rectangle (f, gc,
+                           WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                           WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                           width, row->height);
       else
-       XFillRectangle (dpy, window, gc,
-                       WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
-                       WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
-                                                row->height - width),
-                       cursor_glyph->pixel_width,
-                       width);
+       mac_fill_rectangle (f, gc,
+                           WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                           WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+                                                    row->height - width),
+                           cursor_glyph->pixel_width,
+                           width);
 
-      mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
+      mac_reset_clip_rectangles (dpy, gc);
     }
 }
 
@@ -5084,7 +5529,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);
 }
 
 
@@ -5095,8 +5543,7 @@ mac_clear_frame_area (f, x, y, width, height)
      struct frame *f;
      int x, y, width, height;
 {
-  XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-             x, y, width, height, 0);
+  mac_clear_area (f, x, y, width, height);
 }
 
 
@@ -5292,11 +5739,17 @@ x_new_font (f, fontname)
 
   return build_string (fontp->full_name);
 }
+\f
+/* Give frame F the fontset named FONTSETNAME as its default fontset,
+   and return the full name of that fontset.  FONTSETNAME may be a
+   wildcard pattern; in that case, we choose some fontset that fits
+   the pattern.  FONTSETNAME may be a font name for ASCII characters;
+   in that case, we create a fontset from that font name.
 
-/* Give frame F the fontset named FONTSETNAME as its default font, and
-   return the full name of that fontset.  FONTSETNAME may be a wildcard
-   pattern; in that case, we choose some fontset that fits the pattern.
-   The return value shows which fontset we chose.  */
+   The return value shows which fontset we chose.
+   If FONTSETNAME specifies the default fontset, return Qt.
+   If an ASCII font in the specified fontset can't be loaded, return
+   Qnil.  */
 
 Lisp_Object
 x_new_fontset (f, fontsetname)
@@ -5523,8 +5976,13 @@ x_set_window_size (f, change_gravity, cols, rows)
   SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
 #if TARGET_API_MAC_CARBON
   if (f->output_data.mac->hourglass_control)
-    MoveControl (f->output_data.mac->hourglass_control,
-                pixelwidth - HOURGLASS_WIDTH, 0);
+    {
+#if USE_CG_DRAWING
+      mac_prepare_for_quickdraw (f);
+#endif
+      MoveControl (f->output_data.mac->hourglass_control,
+                  pixelwidth - HOURGLASS_WIDTH, 0);
+    }
 #endif
 
   /* Now, strictly speaking, we can't be sure that this is accurate,
@@ -5634,7 +6092,7 @@ x_raise_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-      SelectWindow (FRAME_MAC_WINDOW (f));
+      BringToFront (FRAME_MAC_WINDOW (f));
       UNBLOCK_INPUT;
     }
 }
@@ -5648,7 +6106,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;
     }
 }
@@ -5675,10 +6133,12 @@ mac_handle_visibility_change (f)
   struct input_event buf;
 
   if (IsWindowVisible (wp))
-    if (IsWindowCollapsed (wp))
-      iconified = 1;
-    else
-      visible = 1;
+    {
+      if (IsWindowCollapsed (wp))
+       iconified = 1;
+      else
+       visible = 1;
+    }
 
   if (!f->async_visible && visible)
     {
@@ -5693,6 +6153,7 @@ mac_handle_visibility_change (f)
          EVENT_INIT (buf);
          buf.kind = DEICONIFY_EVENT;
          XSETFRAME (buf.frame_or_window, f);
+         buf.arg = Qnil;
          kbd_buffer_store_event (&buf);
        }
       else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
@@ -5706,6 +6167,7 @@ mac_handle_visibility_change (f)
        EVENT_INIT (buf);
        buf.kind = ICONIFY_EVENT;
        XSETFRAME (buf.frame_or_window, f);
+       buf.arg = Qnil;
        kbd_buffer_store_event (&buf);
       }
 
@@ -5724,9 +6186,6 @@ void
 x_make_frame_visible (f)
      struct frame *f;
 {
-  Lisp_Object type;
-  int original_top, original_left;
-
   BLOCK_INPUT;
 
   if (! FRAME_VISIBLE_P (f))
@@ -5737,31 +6196,32 @@ x_make_frame_visible (f)
         before the window gets really visible.  */
       if (! FRAME_ICONIFIED_P (f)
          && ! f->output_data.mac->asked_for_visible)
+       {
 #if TARGET_API_MAC_CARBON
-       if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
-         {
-           struct frame *sf = SELECTED_FRAME ();
-           if (!FRAME_MAC_P (sf))
-             RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
-                               kWindowCenterOnMainScreen);
-           else
-             RepositionWindow (FRAME_MAC_WINDOW (f),
-                               FRAME_MAC_WINDOW (sf),
+         if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
+           {
+             struct frame *sf = SELECTED_FRAME ();
+             if (!FRAME_MAC_P (sf))
+               RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
+                                 kWindowCenterOnMainScreen);
+             else
+               RepositionWindow (FRAME_MAC_WINDOW (f),
+                                 FRAME_MAC_WINDOW (sf),
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-                               kWindowCascadeStartAtParentWindowScreen
+                                 kWindowCascadeStartAtParentWindowScreen
 #else
-                               kWindowCascadeOnParentWindowScreen
+                                 kWindowCascadeOnParentWindowScreen
 #endif
-                               );
-           x_real_positions (f, &f->left_pos, &f->top_pos);
-         }
-       else
+                                 );
+             x_real_positions (f, &f->left_pos, &f->top_pos);
+           }
+         else
 #endif
-         x_set_offset (f, f->left_pos, f->top_pos, 0);
+           x_set_offset (f, f->left_pos, f->top_pos, 0);
+       }
 
       f->output_data.mac->asked_for_visible = 1;
 
-      SelectWindow (FRAME_MAC_WINDOW (f));
       CollapseWindow (FRAME_MAC_WINDOW (f), false);
       ShowWindow (FRAME_MAC_WINDOW (f));
     }
@@ -5918,11 +6378,21 @@ x_free_frame_resources (f)
   if (FRAME_SIZE_HINTS (f))
     xfree (FRAME_SIZE_HINTS (f));
 
+#if TARGET_API_MAC_CARBON
+  if (FRAME_FILE_NAME (f))
+    xfree (FRAME_FILE_NAME (f));
+#endif
+
   xfree (f->output_data.mac);
   f->output_data.mac = NULL;
 
   if (f == dpyinfo->x_focus_frame)
-    dpyinfo->x_focus_frame = 0;
+    {
+      dpyinfo->x_focus_frame = 0;
+#if USE_MAC_FONT_PANEL
+      mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
+#endif
+    }
   if (f == dpyinfo->x_focus_event_frame)
     dpyinfo->x_focus_event_frame = 0;
   if (f == dpyinfo->x_highlight_frame)
@@ -6098,6 +6568,326 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 #endif /* MAC_TODO */
 }
 
+\f
+/***********************************************************************
+                         XLFD Pattern Match
+ ***********************************************************************/
+
+/* An XLFD pattern is divided into blocks delimited by '*'.  This
+   structure holds information for each block.  */
+struct xlfdpat_block
+{
+  /* Length of the pattern string in this block.  Non-zero except for
+     the first and the last blocks.  */
+  int len;
+
+  /* Pattern string except the last character in this block.  The last
+     character is replaced with NUL in order to use it as a
+     sentinel.  */
+  unsigned char *pattern;
+
+  /* Last character of the pattern string.  Must not be '?'.  */
+  unsigned char last_char;
+
+  /* One of the tables for the Boyer-Moore string search.  It
+     specifies the number of positions to proceed for each character
+     with which the match fails.  */
+  int skip[256];
+
+  /* The skip value for the last character in the above `skip' is
+     assigned to `infinity' in order to simplify a loop condition.
+     The original value is saved here.  */
+  int last_char_skip;
+};
+
+struct xlfdpat
+{
+  /* Normalized pattern string.  "Normalized" means that capital
+     letters are lowered, blocks are not empty except the first and
+     the last ones, and trailing '?'s in a block that is not the last
+     one are moved to the next one.  The last character in each block
+     is replaced with NUL.  */
+  unsigned char *buf;
+
+  /* Number of characters except '*'s and trailing '?'s in the
+     normalized pattern string.  */
+  int nchars;
+
+  /* Number of trailing '?'s in the normalized pattern string.  */
+  int trailing_anychars;
+
+  /* Number of blocks and information for each block.  The latter is
+     NULL if the pattern is exact (no '*' or '?' in it).  */
+  int nblocks;
+  struct xlfdpat_block *blocks;
+};
+
+static void
+xlfdpat_destroy (pat)
+     struct xlfdpat *pat;
+{
+  if (pat)
+    {
+      if (pat->buf)
+       {
+         if (pat->blocks)
+           xfree (pat->blocks);
+         xfree (pat->buf);
+       }
+      xfree (pat);
+    }
+}
+
+static struct xlfdpat *
+xlfdpat_create (pattern)
+     char *pattern;
+{
+  struct xlfdpat *pat;
+  int nblocks, i, skip;
+  unsigned char last_char, *p, *q, *anychar_head;
+  struct xlfdpat_block *blk;
+
+  pat = xmalloc (sizeof (struct xlfdpat));
+  pat->buf = xmalloc (strlen (pattern) + 1);
+
+  /* Normalize the pattern string and store it to `pat->buf'.  */
+  nblocks = 0;
+  anychar_head = NULL;
+  q = pat->buf;
+  last_char = '\0';
+  for (p = pattern; *p; p++)
+    {
+      unsigned char c = *p;
+
+      if (c == '*')
+       if (last_char == '*')
+         /*  ...a** -> ...a*  */
+         continue;
+       else
+         {
+           if (last_char == '?')
+             {
+               if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
+                 /*  ...*??* -> ...*??  */
+                 continue;
+               else
+                 /*  ...a??* -> ...a*??  */
+                 {
+                   *anychar_head++ = '*';
+                   c = '?';
+                 }
+             }
+           nblocks++;
+         }
+      else if (c == '?')
+       {
+         if (last_char != '?')
+           anychar_head = q;
+       }
+      else
+       /* On Mac OS X 10.3, tolower also converts non-ASCII
+          characters for some locales.  */
+       if (isascii (c))
+         c = tolower (c);
+
+      *q++ = last_char = c;
+    }
+  *q = '\0';
+  nblocks++;
+  pat->nblocks = nblocks;
+  if (last_char != '?')
+    pat->trailing_anychars = 0;
+  else
+    {
+      pat->trailing_anychars = q - anychar_head;
+      q = anychar_head;
+    }
+  pat->nchars = q - pat->buf - (nblocks - 1);
+
+  if (anychar_head == NULL && nblocks == 1)
+    {
+      /* The pattern is exact.  */
+      pat->blocks = NULL;
+      return pat;
+    }
+
+  pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
+
+  /* Divide the normalized pattern into blocks.  */
+  p = pat->buf;
+  for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
+    {
+      blk->pattern = p;
+      while (*p != '*')
+       p++;
+      blk->len = p - blk->pattern;
+      p++;
+    }
+  blk->pattern = p;
+  blk->len = q - blk->pattern;
+
+  /* Setup a table for the Boyer-Moore string search.  */
+  for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
+    if (blk->len != 0)
+      {
+       blk->last_char = blk->pattern[blk->len - 1];
+       blk->pattern[blk->len - 1] = '\0';
+
+       for (skip = 1; skip < blk->len; skip++)
+         if (blk->pattern[blk->len - skip - 1] == '?')
+           break;
+
+       for (i = 0; i < 256; i++)
+         blk->skip[i] = skip;
+
+       p = blk->pattern + (blk->len - skip);
+       while (--skip > 0)
+         blk->skip[*p++] = skip;
+
+       blk->last_char_skip = blk->skip[blk->last_char];
+      }
+
+  return pat;
+}
+
+static INLINE int
+xlfdpat_exact_p (pat)
+     struct xlfdpat *pat;
+{
+  return pat->blocks == NULL;
+}
+
+/* Return the first string in STRING + 0, ..., STRING + START_MAX such
+   that the pattern in *BLK matches with its prefix.  Return NULL
+   there is no such strings.  STRING must be lowered in advance.  */
+
+static char *
+xlfdpat_block_match_1 (blk, string, start_max)
+     struct xlfdpat_block *blk;
+     unsigned char *string;
+     int start_max;
+{
+  int start, infinity;
+  unsigned char *p, *s;
+
+  xassert (blk->len > 0);
+  xassert (start_max + blk->len <= strlen (string));
+  xassert (blk->last_char != '?');
+
+  /* See the comments in the function `boyer_moore' (search.c) for the
+     use of `infinity'.  */
+  infinity = start_max + blk->len + 1;
+  blk->skip[blk->last_char] = infinity;
+
+  start = 0;
+  do
+    {
+      /* Check the last character of the pattern. */
+      s = string + blk->len - 1;
+      do
+       {
+         start += blk->skip[*(s + start)];
+       }
+      while (start <= start_max);
+
+      if (start < infinity)
+       /* Couldn't find the last character.  */
+       return NULL;
+
+      /* No less than `infinity' means we could find the last
+        character at `s[start - infinity]'.  */
+      start -= infinity;
+
+      /* Check the remaining characters.  We prefer making no-'?'
+        cases faster because the use of '?' is really rare.  */
+      p = blk->pattern;
+      s = string + start;
+      do
+       {
+         while (*p++ == *s++)
+           ;
+       }
+      while (*(p - 1) == '?');
+
+      if (*(p - 1) == '\0')
+       /* Matched.  */
+       return string + start;
+
+      /* Didn't match.  */
+      start += blk->last_char_skip;
+    }
+  while (start <= start_max);
+
+  return NULL;
+}
+
+#define xlfdpat_block_match(b, s, m) \
+  ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
+   : xlfdpat_block_match_1 (b, s, m))
+
+/* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
+   matches with STRING.  STRING must be lowered in advance.  */
+
+static int
+xlfdpat_match (pat, string)
+     struct xlfdpat *pat;
+     unsigned char *string;
+{
+  int str_len, nblocks, i, start_max;
+  struct xlfdpat_block *blk;
+  unsigned char *s;
+
+  xassert (pat->nblocks > 0);
+
+  if (xlfdpat_exact_p (pat))
+    return strcmp (pat->buf, string) == 0;
+
+  /* The number of the characters in the string must not be smaller
+     than that in the pattern.  */
+  str_len = strlen (string);
+  if (str_len < pat->nchars + pat->trailing_anychars)
+    return 0;
+
+  /* Chop off the trailing '?'s.  */
+  str_len -= pat->trailing_anychars;
+
+  /* The last block.  When it is non-empty, it must match at the end
+     of the string.  */
+  nblocks = pat->nblocks;
+  blk = pat->blocks + (nblocks - 1);
+  if (nblocks == 1)
+    /* The last block is also the first one.  */
+    return (str_len == blk->len
+           && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
+  else if (blk->len != 0)
+    if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
+      return 0;
+
+  /* The first block.  When it is non-empty, it must match at the
+     beginning of the string.  */
+  blk = pat->blocks;
+  if (blk->len != 0)
+    {
+      s = xlfdpat_block_match (blk, string, 0);
+      if (s == NULL)
+       return 0;
+      string = s + blk->len;
+    }
+
+  /* The rest of the blocks.  */
+  start_max = str_len - pat->nchars;
+  for (i = 1, blk++; i < nblocks - 1; i++, blk++)
+    {
+      s = xlfdpat_block_match (blk, string, start_max);
+      if (s == NULL)
+       return 0;
+      start_max -= s - string;
+      string = s + blk->len;
+    }
+
+  return 1;
+}
+
 \f
 /***********************************************************************
                                Fonts
@@ -6118,6 +6908,18 @@ static char **font_name_table = NULL;
 static int font_name_table_size = 0;
 static int font_name_count = 0;
 
+/* Alist linking font family names to Font Manager font family
+   references (which can also be used as QuickDraw font IDs).  We use
+   an alist because hash tables are not ready when the terminal frame
+   for Mac OS Classic is created.  */
+static Lisp_Object fm_font_family_alist;
+#if USE_ATSUI
+/* Hash table linking font family names to ATSU font IDs.  */
+static Lisp_Object atsu_font_id_hash;
+static Lisp_Object Vmac_atsu_font_table;
+extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
+#endif
+
 /* Alist linking character set strings to Mac text encoding and Emacs
    coding system. */
 static Lisp_Object Vmac_charset_info_alist;
@@ -6164,28 +6966,39 @@ decode_mac_font_name (name, size, coding_system)
   struct coding_system coding;
   char *buf, *p;
 
-  for (p = name; *p; p++)
-    if (!isascii (*p) || iscntrl (*p))
-      break;
+  if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
+    {
+      for (p = name; *p; p++)
+       if (!isascii (*p) || iscntrl (*p))
+         break;
 
-  if (*p == '\0'
-      || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
-    return;
+      if (*p)
+       {
+         setup_coding_system (coding_system, &coding);
+         coding.src_multibyte = 0;
+         coding.dst_multibyte = 1;
+         coding.mode |= CODING_MODE_LAST_BLOCK;
+         coding.dst_bytes = size;
+         coding.destination = (unsigned char *) alloca (coding.dst_bytes);
+
+         decode_coding_c_string (&coding, name, strlen (name), Qnil);
+         bcopy (coding.destination, name, min (coding.produced, size));
+         name[min (coding.produced, size)] = '\0';
+       }
+    }
 
-  #if 0
-  /* MAC_TODO: Fix encoding system... */
-  setup_coding_system (coding_system, &coding);
-  coding.src_multibyte = 0;
-  coding.dst_multibyte = 1;
-  coding.mode |= CODING_MODE_LAST_BLOCK;
-  coding.dst_bytes = MAX_MULTsize;
-  coding.destination = (char *) alloca (size);
-  coding_decode_c_string(&coding, name, strlen(name), qNil);
+  /* If there's just one occurrence of '-' in the family name, it is
+     replaced with '_'.  (More than one occurrence of '-' means a
+     "FOUNDRY-FAMILY-CHARSET"-style name.)  */
+  p = strchr (name, '-');
+  if (p && strchr (p + 1, '-') == NULL)
+    *p = '_';
 
-  decode_coding (&coding, name, buf, strlen (name), size - 1);
-  bcopy (buf, name, coding.produced);
-  name[coding.produced] = '\0';
-  #endif
+  for (p = name; *p; p++)
+    /* On Mac OS X 10.3, tolower also converts non-ASCII characters
+       for some locales.  */
+    if (isascii (*p))
+      *p = tolower (*p);
 }
 
 
@@ -6198,7 +7011,8 @@ mac_to_x_fontname (name, size, style, charset)
 {
   Str31 foundry, cs;
   Str255 family;
-  char xf[256], *result, *p;
+  char xf[256], *result;
+  unsigned char *p;
 
   if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
     charset = cs;
@@ -6210,42 +7024,59 @@ mac_to_x_fontname (name, size, style, charset)
 
   sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
           style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
-          size, size * 10, size ? 75 : 0, size ? 75 : 0, size * 10, charset);
+          size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
 
   result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
   sprintf (result, "-%s-%s-%s", foundry, family, xf);
   for (p = result; *p; p++)
-    *p = tolower(*p);
+    /* On Mac OS X 10.3, tolower also converts non-ASCII characters
+       for some locales.  */
+    if (isascii (*p))
+      *p = tolower (*p);
   return result;
 }
 
 
-/* Convert an X font spec to the corresponding mac font name, which
-   can then be passed to GetFNum after conversion to a Pascal string.
-   For ordinary Mac fonts, this should just be their names, like
-   "monaco", "Taipei", etc.  Fonts converted from the GNU intlfonts
-   collection contain their charset designation in their names, like
-   "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc.  Both types of font
-   names are handled accordingly.  */
-static void
-x_font_name_to_mac_font_name (xf, mf, mf_decoded, style, cs)
-     char *xf, *mf, *mf_decoded;
+/* Parse fully-specified and instantiated X11 font spec XF, and store
+   the results to FAMILY, *SIZE, *STYLE, and CHARSET.  Return 1 if the
+   parsing succeeded, and 0 otherwise.  For FAMILY and CHARSET, the
+   caller must allocate at least 256 and 32 bytes respectively.  For
+   ordinary Mac fonts, the value stored to FAMILY should just be their
+   names, like "monaco", "Taipei", etc.  Fonts converted from the GNU
+   intlfonts collection contain their charset designation in their
+   names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc.  Both
+   types of font names are handled accordingly.  */
+
+const int kDefaultFontSize = 12;
+
+static int
+parse_x_font_name (xf, family, size, style, charset)
+     char *xf, *family;
+     int *size;
      Style *style;
-     char *cs;
+     char *charset;
 {
-  Str31 foundry;
-  Str255 family;
-  char weight[20], slant[2], *p;
-  Lisp_Object charset_info, coding_system = Qnil;
-  struct coding_system coding;
+  Str31 foundry, weight;
+  int point_size, avgwidth;
+  char slant[2], *p;
 
-  strcpy (mf, "");
+  if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
+              foundry, family, weight, slant, size,
+             &point_size, &avgwidth, charset) != 8
+      && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
+                foundry, family, weight, slant, size,
+                &point_size, &avgwidth, charset) != 8)
+    return 0;
 
-  if (sscanf (xf, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
-              foundry, family, weight, slant, cs) != 5 &&
-      sscanf (xf, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
-              foundry, family, weight, slant, cs) != 5)
-    return;
+  if (*size == 0)
+    {
+      if (point_size > 0)
+       *size = point_size / 10;
+      else if (avgwidth > 0)
+       *size = avgwidth / 10;
+    }
+  if (*size == 0)
+    *size = kDefaultFontSize;
 
   *style = normal;
   if (strcmp (weight, "bold") == 0)
@@ -6253,35 +7084,31 @@ x_font_name_to_mac_font_name (xf, mf, mf_decoded, style, cs)
   if (*slant == 'i')
     *style |= italic;
 
-  charset_info = Fassoc (build_string (cs), Vmac_charset_info_alist);
-  if (!NILP (charset_info))
+  if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
     {
-      strcpy (mf_decoded, family);
-      coding_system = Fcar (Fcdr (Fcdr (charset_info)));
+      int foundry_len = strlen (foundry), family_len = strlen (family);
+
+      if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
+       {
+         /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
+            but take overlap into account.  */
+         memmove (family + foundry_len + 1, family, family_len);
+         memcpy (family, foundry, foundry_len);
+         family[foundry_len] = '-';
+         family[foundry_len + 1 + family_len] = '-';
+         strcpy (family + foundry_len + 1 + family_len + 1, charset);
+       }
+      else
+       return 0;
     }
-  else
-    sprintf (mf_decoded, "%s-%s-%s", foundry, family, cs);
 
-  for (p = mf_decoded; *p; p++)
-    if (!isascii (*p) || iscntrl (*p))
-      break;
+  for (p = family; *p; p++)
+    /* On Mac OS X 10.3, tolower also converts non-ASCII characters
+       for some locales.  */
+    if (isascii (*p))
+      *p = tolower (*p);
 
-  if (*p == '\0'
-      || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
-    strcpy (mf, mf_decoded);
-#if 0
-  /* MAC_TODO: Fix coding system to use objects */
-  else
-    {
-      setup_coding_system (coding_system, &coding);
-      coding.src_multibyte = 1;
-      coding.dst_multibyte = 1;
-      coding.mode |= CODING_MODE_LAST_BLOCK;
-      encode_coding (&coding, mf_decoded, mf,
-                    strlen (mf_decoded), sizeof (Str255) - 1);
-      mf[coding.produced] = '\0';
-    }
-#endif
+  return 1;
 }
 
 
@@ -6290,13 +7117,13 @@ add_font_name_table_entry (char *font_name)
 {
   if (font_name_table_size == 0)
     {
-      font_name_table_size = 16;
+      font_name_table_size = 256;
       font_name_table = (char **)
        xmalloc (font_name_table_size * sizeof (char *));
     }
   else if (font_name_count + 1 >= font_name_table_size)
     {
-      font_name_table_size += 16;
+      font_name_table_size *= 2;
       font_name_table = (char **)
        xrealloc (font_name_table,
                  font_name_table_size * sizeof (char *));
@@ -6305,6 +7132,25 @@ add_font_name_table_entry (char *font_name)
   font_name_table[font_name_count++] = font_name;
 }
 
+static void
+add_mac_font_name (name, size, style, charset)
+     char *name;
+     int size;
+     Style style;
+     char *charset;
+{
+  if (size > 0)
+    add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
+  else
+    {
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
+                                                   charset));
+    }
+}
+
 /* Sets up the table font_name_table to contain the list of all fonts
    in the system the first time the table is used so that the Resource
    Manager need not be accessed every time this information is
@@ -6320,6 +7166,83 @@ init_font_name_table ()
   Lisp_Object text_encoding_info_alist;
   struct gcpro gcpro1;
 
+  text_encoding_info_alist = create_text_encoding_info_alist ();
+
+#if USE_ATSUI
+#if USE_CG_TEXT_DRAWING
+  init_cg_text_anti_aliasing_threshold ();
+#endif
+  if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
+                          text_encoding_info_alist)))
+    {
+      OSErr err;
+      struct Lisp_Hash_Table *h;
+      unsigned hash_code;
+      ItemCount nfonts, i;
+      ATSUFontID *font_ids = NULL;
+      Ptr name;
+      ByteCount name_len;
+      Lisp_Object family;
+
+      atsu_font_id_hash =
+       make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
+                        make_float (DEFAULT_REHASH_SIZE),
+                        make_float (DEFAULT_REHASH_THRESHOLD),
+                        Qnil, Qnil, Qnil);;
+      h = XHASH_TABLE (atsu_font_id_hash);
+
+      err = ATSUFontCount (&nfonts);
+      if (err == noErr)
+       {
+         font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
+         err = ATSUGetFontIDs (font_ids, nfonts, NULL);
+       }
+      if (err == noErr)
+       for (i = 0; i < nfonts; i++)
+         {
+           err = ATSUFindFontName (font_ids[i], kFontFamilyName,
+                                   kFontMacintoshPlatform, kFontNoScript,
+                                   kFontNoLanguage, 0, NULL, &name_len, NULL);
+           if (err != noErr)
+             continue;
+           name = xmalloc (name_len + 1);
+           name[name_len] = '\0';
+           err = ATSUFindFontName (font_ids[i], kFontFamilyName,
+                                   kFontMacintoshPlatform, kFontNoScript,
+                                   kFontNoLanguage, name_len, name,
+                                   NULL, NULL);
+           if (err == noErr)
+             {
+               FMFontFamily ff;
+               FMFontStyle style = normal;
+
+               decode_mac_font_name (name, name_len + 1, Qnil);
+               family = make_unibyte_string (name, name_len);
+               FMGetFontFamilyInstanceFromFont (font_ids[i], &ff, &style);
+               Fputhash (make_unibyte_string ((char *)(font_ids + i),
+                                              sizeof (ATSUFontID)),
+                         Fcons (QCfamily,
+                                list5 (family,
+                                       QCweight,
+                                       style & bold ? Qbold : Qnormal,
+                                       QCslant,
+                                       style & italic ? Qitalic : Qnormal)),
+                         Vmac_atsu_font_table);
+               if (*name != '.'
+                   && hash_lookup (h, family, &hash_code) < 0)
+                 {
+                   add_mac_font_name (name, 0, normal, "iso10646-1");
+                   hash_put (h, family, long_to_cons (font_ids[i]),
+                             hash_code);
+                 }
+             }
+           xfree (name);
+         }
+      if (font_ids)
+       xfree (font_ids);
+    }
+#endif
+
   /* Create a dummy instance iterator here to avoid creating and
      destroying it in the loop.  */
   if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
@@ -6332,8 +7255,6 @@ init_font_name_table ()
       return;
     }
 
-  text_encoding_info_alist = create_text_encoding_info_alist ();
-
   GCPRO1 (text_encoding_info_alist);
 
   while (FMGetNextFontFamily (&ffi, &ff) == noErr)
@@ -6344,57 +7265,42 @@ init_font_name_table ()
       FMFontSize size;
       TextEncoding encoding;
       TextEncodingBase sc;
-      Lisp_Object text_encoding_info;
+      Lisp_Object text_encoding_info, family;
 
       if (FMGetFontFamilyName (ff, name) != noErr)
-       break;
+       continue;
       p2cstr (name);
       if (*name == '.')
        continue;
 
       if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
-       break;
+       continue;
       sc = GetTextEncodingBase (encoding);
       text_encoding_info = assq_no_quit (make_number (sc),
                                         text_encoding_info_alist);
-      if (!NILP (text_encoding_info))
-       decode_mac_font_name (name, sizeof (name),
-                             XCAR (XCDR (text_encoding_info)));
-      else
+      if (NILP (text_encoding_info))
        text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
                                           text_encoding_info_alist);
+      decode_mac_font_name (name, sizeof (name),
+                           XCAR (XCDR (text_encoding_info)));
+      family = build_string (name);
+      if (!NILP (Fassoc (family, fm_font_family_alist)))
+       continue;
+      fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
+                                   fm_font_family_alist);
 
       /* Point the instance iterator at the current font family.  */
       if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
-       break;
+       continue;
 
       while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
             == noErr)
        {
          Lisp_Object rest = XCDR (XCDR (text_encoding_info));
 
-         for (; !NILP (rest); rest = XCDR (rest))
-           {
-             char *cs = SDATA (XCAR (rest));
-
-             if (size == 0)
-               {
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               style, cs));
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               italic, cs));
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               bold, cs));
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               italic | bold,
-                                                               cs));
-               }
-             else
-               {
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               style, cs));
-               }
-           }
+         if (size > 0 || style == normal)
+           for (; !NILP (rest); rest = XCDR (rest))
+             add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
        }
     }
 
@@ -6414,7 +7320,7 @@ init_font_name_table ()
   Str255 name;
   struct FontAssoc *fat;
   struct AsscEntry *assc_entry;
-  Lisp_Object text_encoding_info_alist, text_encoding_info;
+  Lisp_Object text_encoding_info_alist, text_encoding_info, family;
   struct gcpro gcpro1;
 
   GetPort (&port);  /* save the current font number used */
@@ -6433,19 +7339,23 @@ init_font_name_table ()
       GetResInfo (font_handle, &id, &type, name);
       GetFNum (name, &fontnum);
       p2cstr (name);
-      if (fontnum == 0)
+      if (fontnum == 0 || *name == '.')
        continue;
 
       TextFont (fontnum);
       scriptcode = FontToScript (fontnum);
       text_encoding_info = assq_no_quit (make_number (scriptcode),
                                         text_encoding_info_alist);
-      if (!NILP (text_encoding_info))
-       decode_mac_font_name (name, sizeof (name),
-                             XCAR (XCDR (text_encoding_info)));
-      else
+      if (NILP (text_encoding_info))
        text_encoding_info = assq_no_quit (make_number (smRoman),
                                           text_encoding_info_alist);
+      decode_mac_font_name (name, sizeof (name),
+                           XCAR (XCDR (text_encoding_info)));
+      family = build_string (name);
+      if (!NILP (Fassoc (family, fm_font_family_alist)))
+       continue;
+      fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
+                                   fm_font_family_alist);
       do
        {
          HLock (font_handle);
@@ -6465,14 +7375,9 @@ init_font_name_table ()
                  Lisp_Object rest = XCDR (XCDR (text_encoding_info));
 
                  for (; !NILP (rest); rest = XCDR (rest))
-                   {
-                     char *cs = SDATA (XCAR (rest));
-
-                     add_font_name_table_entry (mac_to_x_fontname (name,
-                                                                   assc_entry->fontSize,
-                                                                   assc_entry->fontStyle,
-                                                                   cs));
-                   }
+                   add_mac_font_name (name, assc_entry->fontSize,
+                                      assc_entry->fontStyle,
+                                      SDATA (XCAR (rest)));
                }
            }
 
@@ -6501,6 +7406,7 @@ mac_clear_font_name_table ()
   xfree (font_name_table);
   font_name_table = NULL;
   font_name_table_size = font_name_count = 0;
+  fm_font_family_alist = Qnil;
 }
 
 
@@ -6520,40 +7426,17 @@ static int xlfd_scalable_fields[] =
     -1
   };
 
-static Lisp_Object
-mac_c_string_match (regexp, string, nonspecial, exact)
-     Lisp_Object regexp;
-     const char *string, *nonspecial;
-     int exact;
-{
-  if (exact)
-    {
-      if (strcmp (string, nonspecial) == 0)
-       return build_string (string);
-    }
-  else if (strstr (string, nonspecial))
-    {
-      Lisp_Object str = build_string (string);
-
-      if (fast_string_match (regexp, str) >= 0)
-       return str;
-    }
-
-  return Qnil;
-}
-
 static Lisp_Object
 mac_do_list_fonts (pattern, maxnames)
      char *pattern;
      int maxnames;
 {
   int i, n_fonts = 0;
-  Lisp_Object font_list = Qnil, pattern_regex, fontname;
-  char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
+  Lisp_Object font_list = Qnil;
+  struct xlfdpat *pat;
   char *scaled, *ptr;
   int scl_val[XLFD_SCL_LAST], *field, *val;
-  char *longest_start, *cur_start, *nonspecial;
-  int longest_len, exact;
+  int exact;
 
   if (font_name_table == NULL)  /* Initialize when first used.  */
     init_font_name_table ();
@@ -6611,62 +7494,18 @@ mac_do_list_fonts (pattern, maxnames)
   else
     scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
 
-  ptr = regex;
-  *ptr++ = '^';
-
-  longest_start = cur_start = ptr;
-  longest_len = 0;
-  exact = 1;
-
-  /* Turn pattern into a regexp and do a regexp match.  Also find the
-     longest substring containing no special characters.  */
-  for (; *pattern; pattern++)
-    {
-      if (*pattern == '?' || *pattern == '*')
-       {
-         if (ptr - cur_start > longest_len)
-           {
-             longest_start = cur_start;
-             longest_len = ptr - cur_start;
-           }
-         exact = 0;
-
-         if (*pattern == '?')
-           *ptr++ = '.';
-         else /* if (*pattern == '*') */
-           {
-             *ptr++ = '.';
-             *ptr++ = '*';
-           }
-         cur_start = ptr;
-       }
-      else
-       *ptr++ = tolower (*pattern);
-    }
-
-  if (ptr - cur_start > longest_len)
-    {
-      longest_start = cur_start;
-      longest_len = ptr - cur_start;
-    }
-
-  *ptr = '$';
-  *(ptr + 1) = '\0';
-
-  nonspecial = xmalloc (longest_len + 1);
-  strncpy (nonspecial, longest_start, longest_len);
-  nonspecial[longest_len] = '\0';
+  pat = xlfdpat_create (pattern);
+  if (pat == NULL)
+    return Qnil;
 
-  pattern_regex = build_string (regex);
+  exact = xlfdpat_exact_p (pat);
 
   for (i = 0; i < font_name_count; i++)
     {
-      fontname = mac_c_string_match (pattern_regex, font_name_table[i],
-                                    nonspecial, exact);
-      if (!NILP (fontname))
+      if (xlfdpat_match (pat, font_name_table[i]))
        {
-         font_list = Fcons (fontname, font_list);
-         if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+         font_list = Fcons (build_string (font_name_table[i]), font_list);
+         if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
            break;
        }
       else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
@@ -6677,24 +7516,25 @@ mac_do_list_fonts (pattern, maxnames)
          scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
          memcpy (scaled, font_name_table[i], former_len);
          sprintf (scaled + former_len,
-                  "-%d-%d-75-75-m-%d-%s",
+                  "-%d-%d-72-72-m-%d-%s",
                   scl_val[XLFD_SCL_PIXEL_SIZE],
                   scl_val[XLFD_SCL_POINT_SIZE],
                   scl_val[XLFD_SCL_AVGWIDTH],
                   ptr + sizeof ("-0-0-0-0-m-0-") - 1);
-         fontname = mac_c_string_match (pattern_regex, scaled,
-                                        nonspecial, exact);
-         xfree (scaled);
-         if (!NILP (fontname))
+
+         if (xlfdpat_match (pat, scaled))
            {
-             font_list = Fcons (fontname, font_list);
-             if (exact || maxnames > 0 && ++n_fonts >= maxnames)
-               break;
+             font_list = Fcons (build_string (scaled), font_list);
+             xfree (scaled);
+             if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
+                 break;
            }
+         else
+           xfree (scaled);
        }
     }
 
-  xfree (nonspecial);
+  xlfdpat_destroy (pat);
 
   return font_list;
 }
@@ -6873,9 +7713,6 @@ is_fully_specified_xlfd (char *p)
 }
 
 
-const int kDefaultFontSize = 12;
-
-
 /* XLoadQueryFont creates and returns an internal representation for a
    font in a MacFontStruct struct.  There is really no concept
    corresponding to "loading" a font on the Mac.  But we check its
@@ -6885,14 +7722,15 @@ const int kDefaultFontSize = 12;
 static MacFontStruct *
 XLoadQueryFont (Display *dpy, char *fontname)
 {
-  int i, size, point_size, avgwidth, is_two_byte_font, char_width;
+  int size;
   char *name;
-  GrafPtr port;
-  SInt16 old_fontnum, old_fontsize;
-  Style old_fontface;
-  Str255 mfontname, mfontname_decoded;
+  Str255 family;
   Str31 charset;
   SInt16 fontnum;
+#if USE_ATSUI
+  static ATSUFontID font_id;
+  ATSUStyle mac_style = NULL;
+#endif
   Style fontface;
 #if TARGET_API_MAC_CARBON
   TextEncoding encoding;
@@ -6901,10 +7739,7 @@ XLoadQueryFont (Display *dpy, char *fontname)
   short scriptcode;
 #endif
   MacFontStruct *font;
-  FontInfo the_fontinfo;
-#ifdef MAC_OSX
-  UInt32 old_flags, new_flags;
-#endif
+  XCharStruct *space_bounds = NULL, *pcm;
 
   if (is_fully_specified_xlfd (fontname))
     name = fontname;
@@ -6918,45 +7753,68 @@ XLoadQueryFont (Display *dpy, char *fontname)
       name = SDATA (XCAR (matched_fonts));
     }
 
-  GetPort (&port);  /* save the current font number used */
-#if TARGET_API_MAC_CARBON
-  old_fontnum = GetPortTextFont (port);
-  old_fontsize = GetPortTextSize (port);
-  old_fontface = GetPortTextFace (port);
-#else
-  old_fontnum = port->txFont;
-  old_fontsize = port->txSize;
-  old_fontface = port->txFace;
-#endif
+  if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
+    return NULL;
+
+#if USE_ATSUI
+  if (strcmp (charset, "iso10646-1") == 0) /* XXX */
+    {
+      OSErr err;
+      ATSUAttributeTag tags[] = {kATSUFontTag, kATSUSizeTag,
+                                kATSUQDBoldfaceTag, kATSUQDItalicTag};
+      ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed),
+                          sizeof (Boolean), sizeof (Boolean)};
+      static Fixed size_fixed;
+      static Boolean bold_p, italic_p;
+      ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
+                                       &bold_p, &italic_p};
+      ATSUFontFeatureType types[] = {kAllTypographicFeaturesType,
+                                    kDiacriticsType};
+      ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector,
+                                            kDecomposeDiacriticsSelector};
+      Lisp_Object font_id_cons;
+      FMFontStyle style;
 
-  if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size, &point_size, &avgwidth) != 3)
-    size = 0;
+      font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
+                              atsu_font_id_hash, Qnil);
+      if (NILP (font_id_cons))
+       return NULL;
+      font_id = cons_to_long (font_id_cons);
+      size_fixed = Long2Fix (size);
+      bold_p = (fontface & bold) != 0;
+      italic_p = (fontface & italic) != 0;
+      err = ATSUCreateStyle (&mac_style);
+      if (err != noErr)
+       return NULL;
+      err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
+                                types, selectors);
+      if (err != noErr)
+       return NULL;
+      err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
+                              tags, sizes, values);
+      if (err != noErr)
+       return NULL;
+      err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
+      if (err != noErr)
+       fontnum = -1;
+      scriptcode = kTextEncodingMacUnicode;
+    }
   else
+#endif
     {
-      if (size == 0)
-       if (point_size > 0)
-         size = point_size / 10;
-       else if (avgwidth > 0)
-         size = avgwidth / 10;
-    }
-  if (size == 0)
-    size = kDefaultFontSize;
+      Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
 
-  x_font_name_to_mac_font_name (name, mfontname, mfontname_decoded,
-                               &fontface, charset);
-  c2pstr (mfontname);
+      if (NILP (tmp))
+       return NULL;
+      fontnum = XINT (XCDR (tmp));
 #if TARGET_API_MAC_CARBON
-  fontnum = FMGetFontFamilyFromName (mfontname);
-  if (fontnum == kInvalidFontFamily
-      || FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
-    return NULL;
-  scriptcode = GetTextEncodingBase (encoding);
+      if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
+       return NULL;
+      scriptcode = GetTextEncodingBase (encoding);
 #else
-  GetFNum (mfontname, &fontnum);
-  if (fontnum == 0)
-    return NULL;
-  scriptcode = FontToScript (fontnum);
+      scriptcode = FontToScript (fontnum);
 #endif
+    }
 
   font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
 
@@ -6964,6 +7822,13 @@ XLoadQueryFont (Display *dpy, char *fontname)
   font->mac_fontsize = size;
   font->mac_fontface = fontface;
   font->mac_scriptcode = scriptcode;
+#if USE_ATSUI
+  font->mac_style = mac_style;
+#if USE_CG_TEXT_DRAWING
+  font->cg_font = NULL;
+  font->cg_glyphs = NULL;
+#endif
+#endif
 
   /* Apple Japanese (SJIS) font is listed as both
      "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
@@ -6972,121 +7837,257 @@ XLoadQueryFont (Display *dpy, char *fontname)
   if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
     font->mac_scriptcode = smRoman;
 
-  font->full_name = mac_to_x_fontname (mfontname_decoded, size, fontface, charset);
+  font->full_name = mac_to_x_fontname (family, size, fontface, charset);
 
-  is_two_byte_font = font->mac_scriptcode == smJapanese ||
-                     font->mac_scriptcode == smTradChinese ||
-                     font->mac_scriptcode == smSimpChinese ||
-                     font->mac_scriptcode == smKorean;
+#if USE_ATSUI
+  if (font->mac_style)
+    {
+      OSErr err;
+      UniChar c;
 
-  TextFont (fontnum);
-  TextSize (size);
-  TextFace (fontface);
+      font->min_byte1 = 0;
+      font->max_byte1 = 0xff;
+      font->min_char_or_byte2 = 0;
+      font->max_char_or_byte2 = 0xff;
 
-  GetFontInfo (&the_fontinfo);
+      font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
+      bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
+      font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
+      pcm_init (font->bounds.rows[0], 0x100);
 
-  font->ascent = the_fontinfo.ascent;
-  font->descent = the_fontinfo.descent;
+#if USE_CG_TEXT_DRAWING
+      if (fontnum != -1)
+       {
+         FMFontStyle style;
+         ATSFontRef ats_font;
 
-  font->min_byte1 = 0;
-  if (is_two_byte_font)
-    font->max_byte1 = 1;
-  else
-    font->max_byte1 = 0;
-  font->min_char_or_byte2 = 0x20;
-  font->max_char_or_byte2 = 0xff;
+         err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
+                                                &font_id, &style);
+         /* Use CG text drawing if italic/bold is not synthesized.  */
+         if (err == noErr && style == fontface)
+           {
+             ats_font = FMGetATSFontRefFromFont (font_id);
+             font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
+           }
+       }
 
-  if (is_two_byte_font)
-    {
-      /* Use the width of an "ideographic space" of that font because
-         the_fontinfo.widMax returns the wrong width for some fonts.  */
-      switch (font->mac_scriptcode)
-        {
-        case smJapanese:
-          char_width = StringWidth("\p\x81\x40");
-          break;
-        case smTradChinese:
-          char_width = StringWidth("\p\xa1\x40");
-          break;
-        case smSimpChinese:
-          char_width = StringWidth("\p\xa1\xa1");
-          break;
-        case smKorean:
-          char_width = StringWidth("\p\xa1\xa1");
-          break;
-        }
+      if (font->cg_font)
+       {
+         font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
+         bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
+       }
+#endif
+      space_bounds = font->bounds.rows[0] + 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;
+       }
+
+      pcm = font->bounds.rows[0];
+      for (c = 0x21; c <= 0xff; c++)
+       {
+         if (c == 0xad)
+           /* Soft hyphen is not supported in ATSUI.  */
+           continue;
+         else if (c == 0x7f)
+           {
+             c = 0x9f;
+             continue;
+           }
+
+         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
+                                   NULL
+#endif
+                                 );
+
+#if USE_CG_TEXT_DRAWING
+         if (font->cg_glyphs && font->cg_glyphs[c] == 0)
+           {
+             /* 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
+       }
     }
   else
-    /* 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)
+#endif
     {
-      font->per_char = NULL;
+      GrafPtr port;
+      SInt16 old_fontnum, old_fontsize;
+      Style old_fontface;
+      FontInfo the_fontinfo;
+      int is_two_byte_font;
+
+      /* Save the current font number used.  */
+      GetPort (&port);
+#if TARGET_API_MAC_CARBON
+      old_fontnum = GetPortTextFont (port);
+      old_fontsize = GetPortTextSize (port);
+      old_fontface = GetPortTextFace (port);
+#else
+      old_fontnum = port->txFont;
+      old_fontsize = port->txSize;
+      old_fontface = port->txFace;
+#endif
+
+      TextFont (fontnum);
+      TextSize (size);
+      TextFace (fontface);
+
+      GetFontInfo (&the_fontinfo);
+
+      font->ascent = the_fontinfo.ascent;
+      font->descent = the_fontinfo.descent;
+
+      is_two_byte_font = (font->mac_scriptcode == smJapanese
+                         || font->mac_scriptcode == smTradChinese
+                         || font->mac_scriptcode == smSimpChinese
+                         || font->mac_scriptcode == smKorean);
+
+      if (is_two_byte_font)
+       {
+         int char_width;
+
+         font->min_byte1 = 0xa1;
+         font->max_byte1 = 0xfe;
+         font->min_char_or_byte2 = 0xa1;
+         font->max_char_or_byte2 = 0xfe;
+
+         /* Use the width of an "ideographic space" of that font
+            because the_fontinfo.widMax returns the wrong width for
+            some fonts.  */
+         switch (font->mac_scriptcode)
+           {
+           case smJapanese:
+             font->min_byte1 = 0x81;
+             font->max_byte1 = 0xfc;
+             font->min_char_or_byte2 = 0x40;
+             font->max_char_or_byte2 = 0xfc;
+             char_width = StringWidth("\p\x81\x40");
+             break;
+           case smTradChinese:
+             font->min_char_or_byte2 = 0x40;
+             char_width = StringWidth("\p\xa1\x40");
+             break;
+           case smSimpChinese:
+             char_width = StringWidth("\p\xa1\xa1");
+             break;
+           case smKorean:
+             char_width = StringWidth("\p\xa1\xa1");
+             break;
+           }
+
+         font->bounds.per_char = NULL;
 
-      if (fontface & italic)
-       font->max_bounds.rbearing = char_width + 1;
+         if (fontface & italic)
+           font->max_bounds.rbearing = char_width + 1;
+         else
+           font->max_bounds.rbearing = char_width;
+         font->max_bounds.lbearing = 0;
+         font->max_bounds.width = char_width;
+         font->max_bounds.ascent = the_fontinfo.ascent;
+         font->max_bounds.descent = the_fontinfo.descent;
+
+         font->min_bounds = font->max_bounds;
+       }
       else
-       font->max_bounds.rbearing = char_width;
-      font->max_bounds.lbearing = 0;
-      font->max_bounds.width = char_width;
-      font->max_bounds.ascent = the_fontinfo.ascent;
-      font->max_bounds.descent = the_fontinfo.descent;
+       {
+         int c;
 
-      font->min_bounds = font->max_bounds;
+         font->min_byte1 = font->max_byte1 = 0;
+         font->min_char_or_byte2 = 0x20;
+         font->max_char_or_byte2 = 0xff;
+
+         font->bounds.per_char =
+           xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
+         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.  */
+      TextFont (old_fontnum);
+      TextSize (old_fontsize);
+      TextFace (old_fontface);
     }
-  else
+
+  if (space_bounds)
     {
-      font->per_char = (XCharStruct *)
-       xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
-      {
-       int c, min_width, max_width;
-       Rect char_bounds, min_bounds, max_bounds;
-       char ch;
-
-       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++)
-          {
-           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);
-             }
-         }
-       STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
-       STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
-       if (min_width == max_width
-           && max_bounds.left >= 0 && max_bounds.right <= max_width)
+      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)
          {
-           /* Fixed width and no overhangs.  */
-           xfree (font->per_char);
-           font->per_char = NULL;
+           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;
+       }
     }
 
-  TextFont (old_fontnum);  /* restore previous font number, size and face */
-  TextSize (old_fontsize);
-  TextFace (old_fontface);
+#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
+     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
 
   return font;
 }
@@ -7098,8 +8099,27 @@ 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)
+    {
+      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
   xfree (font);
 }
 
@@ -7142,10 +8162,8 @@ x_load_font (f, fontname, size)
 
   /* Load the font and add it to the table.  */
   {
-    char *full_name;
     struct MacFontStruct *font;
     struct font_info *fontp;
-    unsigned long value;
     int i;
 
     fontname = (char *) SDATA (XCAR (font_names));
@@ -7181,6 +8199,7 @@ x_load_font (f, fontname, size)
     bzero (fontp, sizeof (*fontp));
     fontp->font = font;
     fontp->font_idx = i;
+    fontp->charset = -1;       /* fs_load_font sets it.  */
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
     bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
@@ -7226,22 +8245,20 @@ x_load_font (f, fontname, size)
        fontp->height = max_height;
     }
 
-#if 0 /* MAC_TODO: fill these out with more reasonably values */
-
     /* MAC_TODO: The script encoding is irrelevant in unicode? */
     /* The slot `encoding' specifies how to map a character
        code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
        the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
        (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
        2:0xA020..0xFF7F).  For the moment, we don't know which charset
-       uses this font.  So, we set information in fontp->encoding[1]
+       uses this font.  So, we set information in fontp->encoding_type
        which is never used by any charset.  If mapping can't be
        decided, set FONT_ENCODING_NOT_DECIDED.  */
     if (font->mac_scriptcode == smJapanese)
-      fontp->encoding[1] = 4;
+      fontp->encoding_type = 4;
     else
       {
-        fontp->encoding[1]
+        fontp->encoding_type
            = (font->max_byte1 == 0
              /* 1-byte font */
              ? (font->min_char_or_byte2 < 0x80
@@ -7265,6 +8282,7 @@ x_load_font (f, fontname, size)
                    : 1)));             /* 0xA0A0..0xFFFF */
       }
 
+#if 0 /* MAC_TODO: fill these out with more reasonably values */
     fontp->baseline_offset
       = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
         ? (long) value : 0);
@@ -7342,30 +8360,102 @@ x_find_ccl_program (fontp)
     }
 }
 
+#if USE_MAC_FONT_PANEL
+/* Whether Font Panel has been shown before.  The first call to font
+   panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
+   slow.  This variable is used for deferring such a call as much as
+   possible.  */
+static int font_panel_shown_p = 0;
 
-\f
-/* The Mac Event loop code */
+int
+mac_font_panel_visible_p ()
+{
+  return font_panel_shown_p && FPIsFontPanelVisible ();
+}
 
-#if !TARGET_API_MAC_CARBON
-#include <Events.h>
-#include <Quickdraw.h>
-#include <Balloons.h>
-#include <Devices.h>
-#include <Fonts.h>
-#include <Gestalt.h>
-#include <Menus.h>
-#include <Processes.h>
-#include <Sound.h>
-#include <ToolUtils.h>
-#include <TextUtils.h>
-#include <Dialogs.h>
-#include <Script.h>
-#include <Types.h>
-#include <Resources.h>
+OSStatus
+mac_show_hide_font_panel ()
+{
+  font_panel_shown_p = 1;
 
-#if __MWERKS__
-#include <unix.h>
-#endif
+  return FPShowHideFontPanel ();
+}
+
+OSStatus
+mac_set_font_info_for_selection (f, face_id, c)
+     struct frame *f;
+     int face_id, c;
+{
+  OSStatus err;
+  EventTargetRef target = NULL;
+  XFontStruct *font = NULL;
+
+  if (!mac_font_panel_visible_p ())
+    return noErr;
+
+  if (f)
+    {
+      target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
+
+      if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
+       {
+         struct face *face;
+
+         face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
+         face = FACE_FROM_ID (f, face_id);
+         font = face->font;
+       }
+    }
+
+  if (font == NULL)
+    err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
+  else
+    {
+      if (font->mac_fontnum != -1)
+       {
+         FontSelectionQDStyle qd_style;
+
+         qd_style.version = kFontSelectionQDStyleVersionZero;
+         qd_style.instance.fontFamily = font->mac_fontnum;
+         qd_style.instance.fontStyle = font->mac_fontface;
+         qd_style.size = font->mac_fontsize;
+         qd_style.hasColor = false;
+
+         err = SetFontInfoForSelection (kFontSelectionQDType,
+                                        1, &qd_style, target);
+       }
+      else
+       err = SetFontInfoForSelection (kFontSelectionATSUIType,
+                                      1, &font->mac_style, target);
+    }
+
+  return err;
+}
+#endif
+
+\f
+/* The Mac Event loop code */
+
+#if !TARGET_API_MAC_CARBON
+#include <Events.h>
+#include <Quickdraw.h>
+#include <Balloons.h>
+#include <Devices.h>
+#include <Fonts.h>
+#include <Gestalt.h>
+#include <Menus.h>
+#include <Processes.h>
+#include <Sound.h>
+#include <ToolUtils.h>
+#include <TextUtils.h>
+#include <Dialogs.h>
+#include <Script.h>
+#include <Types.h>
+#include <Resources.h>
+
+#if __MWERKS__
+#include <unix.h>
+#endif
 #endif /* ! TARGET_API_MAC_CARBON */
 
 #define M_APPLE 128
@@ -7388,31 +8478,35 @@ x_find_ccl_program (fontp)
 /* Contains the string "reverse", which is a constant for mouse button emu.*/
 Lisp_Object Qreverse;
 
-/* True if using command key as meta key.  */
-Lisp_Object Vmac_command_key_is_meta;
 
-/* Modifier associated with the option key, or nil for normal behavior. */
+/* Modifier associated with the control key, or nil to ignore. */
+Lisp_Object Vmac_control_modifier;
+
+/* Modifier associated with the option key, or nil to ignore. */
 Lisp_Object Vmac_option_modifier;
 
-/* True if the ctrl and meta keys should be reversed.  */
-Lisp_Object Vmac_reverse_ctrl_meta;
+/* Modifier associated with the command key, or nil to ignore. */
+Lisp_Object Vmac_command_modifier;
+
+/* Modifier associated with the function key, or nil to ignore. */
+Lisp_Object Vmac_function_modifier;
 
 /* True if the option and command modifiers should be used to emulate
    a three button mouse */
 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
@@ -7420,34 +8514,43 @@ 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;
+#ifdef MAC_OSX
+extern Lisp_Object Qwindow;
+static Lisp_Object Qtoolbar_switch_mode;
+#endif
+#if USE_MAC_FONT_PANEL
+extern Lisp_Object Qfont;
+static Lisp_Object Qpanel_closed, Qselection;
+#endif
+#if USE_MAC_TSM
+static TSMDocumentID tsm_document_id;
+static Lisp_Object Qtext_input;
+static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
+static Lisp_Object Vmac_ts_active_input_overlay;
+extern Lisp_Object Qbefore_string;
+#endif
+#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 */
-static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
-static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
-static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL;
-static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
-#endif
+OSErr install_drag_handler P_ ((WindowRef));
+void remove_drag_handler P_ ((WindowRef));
 
-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 Qservice, Qpaste, Qperform;
 #endif
 /* Window Event Handler */
 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
@@ -7469,20 +8572,42 @@ mac_to_emacs_modifiers (EventModifiers mods)
 #endif
 {
   unsigned int result = 0;
-  if (mods & macShiftKey)
+  if (mods & shiftKey)
     result |= shift_modifier;
-  if (mods & macCtrlKey)
-    result |= ctrl_modifier;
-  if (mods & macMetaKey)
-    result |= meta_modifier;
-  if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
-    result |= alt_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
+     is pressed. That way the system may convert the character to a
+     composed one.
+     if ((mods & optionKey) &&
+      (( !NILP(Vmac_option_modifier) ||
+      ((mods & cmdKey) || (mods & controlKey))))) */
+
   if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
-      Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
-      if (!NILP(val))
-          result |= XUINT(val);
+    Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+  if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
+    Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+  if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
+    Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
   }
 
+#ifdef MAC_OSX
+  if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
+    Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+#endif
+
   return result;
 }
 
@@ -7503,7 +8628,7 @@ mac_get_emulated_btn ( UInt32 modifiers )
 #if USE_CARBON_EVENTS
 /* Obtains the event modifiers from the event ref and then calls
    mac_to_emacs_modifiers.  */
-static int
+static UInt32
 mac_event_to_emacs_modifiers (EventRef eventRef)
 {
   UInt32 mods = 0;
@@ -7537,10 +8662,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;
     }
@@ -7555,6 +8680,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)
@@ -7588,13 +8714,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;
 
@@ -7610,7 +8742,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);
@@ -7628,6 +8760,7 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
 
 #endif
 
+#ifdef MAC_OS8
 static void
 do_get_menus (void)
 {
@@ -7689,6 +8822,7 @@ do_check_ram_size (void)
       exit (1);
     }
 }
+#endif /* MAC_OS8 */
 
 static void
 do_window_update (WindowPtr win)
@@ -7751,13 +8885,17 @@ is_emacs_window (WindowPtr win)
 static void
 do_app_resume ()
 {
-  /* Window-activate events will do the job. */
+#if USE_MAC_TSM
+  ActivateTSMDocument (tsm_document_id);
+#endif
 }
 
 static void
 do_app_suspend ()
 {
-  /* Window-deactivate events will do the job. */
+#if USE_MAC_TSM
+  DeactivateTSMDocument (tsm_document_id);
+#endif
 }
 
 
@@ -7870,42 +9008,41 @@ do_grow_window (WindowPtr w, EventRecord *e)
 static void
 do_zoom_window (WindowPtr w, int zoom_in_or_out)
 {
-  GrafPtr save_port;
   Rect zoom_rect, port_rect;
-  Point top_left;
-  int w_title_height, columns, rows, width, height;
+  int columns, rows, width, height;
   struct frame *f = mac_window_to_frame (w);
   struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
 #if TARGET_API_MAC_CARBON
-  {
-    Point standard_size;
+  Point standard_size;
 
-    standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-    standard_size.v = dpyinfo->height;
+  standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+  standard_size.v = dpyinfo->height;
 
-    if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
-      zoom_in_or_out = inZoomIn;
-    else
-      {
-       /* Adjust the standard size according to character boundaries.  */
-
-       columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
-       rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
-       standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
-       standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
-       GetWindowBounds (w, kWindowContentRgn, &port_rect);
-       if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
-           && port_rect.left == zoom_rect.left
-           && port_rect.top == zoom_rect.top)
-         zoom_in_or_out = inZoomIn;
-       else
-         zoom_in_or_out = inZoomOut;
-      }
+  if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
+    zoom_in_or_out = inZoomIn;
+  else
+    {
+      /* Adjust the standard size according to character boundaries.  */
 
-    ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
-  }
+      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
+      standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
+      standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+      GetWindowBounds (w, kWindowContentRgn, &port_rect);
+      if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
+         && port_rect.left == zoom_rect.left
+         && port_rect.top == zoom_rect.top)
+       zoom_in_or_out = inZoomIn;
+      else
+       zoom_in_or_out = inZoomOut;
+    }
+
+  ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
 #else /* not TARGET_API_MAC_CARBON */
+  GrafPtr save_port;
+  Point top_left;
+  int w_title_height;
+
   GetPort (&save_port);
 
   SetPortWindowPort (w);
@@ -7968,180 +9105,87 @@ 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 ()
+mac_store_apple_event (class, id, desc)
+     Lisp_Object class, id;
+     const AEDesc *desc;
 {
-  OSErr err;
-  long result;
-
-  /* Make sure we have apple events before starting.  */
-  err = Gestalt (gestaltAppleEventsAttr, &result);
-  if (err != noErr)
-    abort ();
+  struct input_event buf;
 
-  if (!(result & (1 << gestaltAppleEventsPresent)))
-    abort ();
+  EVENT_INIT (buf);
 
-#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 ();
+  buf.kind = MAC_APPLE_EVENT;
+  buf.x = class;
+  buf.y = id;
+  XSETFRAME (buf.frame_or_window,
+            mac_focus_frame (&one_mac_display_info));
+  /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
+     is safe to use them during read_socket_hook.  */
+  buf.arg = mac_aedesc_to_lisp (desc);
+  kbd_buffer_store_event (&buf);
+}
 
 #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 ();
+static OSStatus
+mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
+                                   event, num_params, names, types)
+     AEEventClass class;
+     AEEventID id;
+     Lisp_Object class_key, id_key;
+     EventRef event;
+     UInt32 num_params;
+     EventParamName *names;
+     EventParamType *types;
+{
+  OSStatus err = eventNotHandledErr;
+  Lisp_Object binding;
 
-#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 ();
+  mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
+  if (!NILP (binding) && !EQ (binding, Qundefined))
+    {
+      if (INTEGERP (binding))
+       err = XINT (binding);
+      else
+       {
+         AppleEvent apple_event;
+         err = create_apple_event_from_event_ref (event, num_params,
+                                                  names, types,
+                                                  &apple_event);
+         if (err == noErr)
+           {
+             mac_store_apple_event (class_key, id_key, &apple_event);
+             AEDisposeDesc (&apple_event);
+             /* Post a harmless event so as to wake up from
+                ReceiveNextEvent.  */
+             mac_post_mouse_moved_event ();
+           }
+       }
+    }
 
-#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 ();
+  return err;
 }
 
 void
-mac_store_application_menu_event (event)
-#if USE_CARBON_EVENTS
-     EventRef event;
-#else
-     UInt32 event;
-#endif
+mac_store_drag_event (window, mouse_pos, modifiers, desc)
+     WindowRef window;
+     Point mouse_pos;
+     SInt16 modifiers;
+     const AEDesc *desc;
 {
   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);
-
-#if USE_CARBON_EVENTS
-  switch (GetEventClass (event))
-    {
-#ifdef MAC_OSX
-    case kEventClassService:
-      buf.arg = Qservices;
-      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;
-
-       default:
-         abort ();
-       }
-      break;
-#endif /* MAC_OSX */
-    case kEventClassCommand:
-      {
-       HICommand command;
-
-       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;
-
-    default:
-      abort ();
-    }
-#else  /* USE_CARBON_EVENTS */
-  switch (event)
-    {
-    case kHICommandAbout:
-      entry = Qabout;
-      break;
-    case kHICommandQuit:
-      entry = Qquit;
-      break;
-    default:
-      abort ();
-    }
-#endif
-
-  buf.arg = entry;
+  buf.kind = DRAG_N_DROP_EVENT;
+  buf.modifiers = mac_to_emacs_modifiers (modifiers);
+  buf.timestamp = TickCount () * (1000 / 60);
+  XSETINT (buf.x, mouse_pos.h);
+  XSETINT (buf.y, mouse_pos.v);
+  XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
+  buf.arg = mac_aedesc_to_lisp (desc);
   kbd_buffer_store_event (&buf);
 }
+#endif
 
 #if USE_CARBON_EVENTS
 static pascal OSStatus
@@ -8150,36 +9194,35 @@ mac_handle_command_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
+  OSStatus result, err;
   HICommand command;
-  OSErr result;
-
-  GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL,
-                   sizeof (HICommand), NULL, &command);
-
-  switch (command.commandID)
-    {
-    case kHICommandAbout:
-#ifdef MAC_OSX
-    case kHICommandPreferences:
-#endif /* MAC_OSX */
-      result = CallNextEventHandler (next_handler, event);
-      if (result != eventNotHandledErr)
-       return result;
+  static EventParamName names[] = {kEventParamDirectObject,
+                                  kEventParamKeyModifiers};
+  static EventParamType types[] = {typeHICommand,
+                                  typeUInt32};
+  int num_params = sizeof (names) / sizeof (names[0]);
+
+  result = CallNextEventHandler (next_handler, event);
+  if (result != eventNotHandledErr)
+    return result;
 
-      mac_store_application_menu_event (event);
-      return noErr;
+  err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
+                          NULL, sizeof (HICommand), NULL, &command);
 
-    default:
-      break;
-    }
+  if (err != noErr || command.commandID == 0)
+    return eventNotHandledErr;
 
-  return eventNotHandledErr;
+  /* A HICommand event is mapped to an Apple event whose event class
+     symbol is `hicommand' and event ID is its command ID.  */
+  err = mac_store_event_ref_as_apple_event (0, command.commandID,
+                                           Qhicommand, Qnil,
+                                           event, num_params, names, types);
+  return err == noErr ? noErr : eventNotHandledErr;
 }
 
 static OSErr
 init_command_handler ()
 {
-  OSErr err = noErr;
   EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
   static EventHandlerUPP handle_command_eventUPP = NULL;
 
@@ -8197,12 +9240,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))
     {
@@ -8219,8 +9264,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))
@@ -8229,9 +9277,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;
 
@@ -8269,6 +9320,45 @@ mac_handle_window_event (next_handler, event, data)
       return noErr;
 
       break;
+
+#ifdef MAC_OSX
+    case kEventWindowToolbarSwitchMode:
+      result = CallNextEventHandler (next_handler, event);
+      {
+       static EventParamName names[] = {kEventParamDirectObject,
+                                        kEventParamWindowMouseLocation,
+                                        kEventParamKeyModifiers,
+                                        kEventParamMouseButton,
+                                        kEventParamClickCount,
+                                        kEventParamMouseChord};
+       static EventParamType types[] = {typeWindowRef,
+                                        typeQDPoint,
+                                        typeUInt32,
+                                        typeMouseButton,
+                                        typeUInt32,
+                                        typeUInt32};
+       int num_params = sizeof (names) / sizeof (names[0]);
+
+       err = mac_store_event_ref_as_apple_event (0, 0,
+                                                 Qwindow,
+                                                 Qtoolbar_switch_mode,
+                                                 event, num_params,
+                                                 names, types);
+      }
+      return err == noErr ? noErr : result;
+#endif
+
+#if USE_MAC_TSM
+    case kEventWindowFocusAcquired:
+      result = CallNextEventHandler (next_handler, event);
+      err = ActivateTSMDocument (tsm_document_id);
+      return err == noErr ? noErr : result;
+
+    case kEventWindowFocusRelinquish:
+      result = CallNextEventHandler (next_handler, event);
+      err = DeactivateTSMDocument (tsm_document_id);
+      return err == noErr ? noErr : result;
+#endif
     }
 
   return eventNotHandledErr;
@@ -8280,7 +9370,7 @@ mac_handle_mouse_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  OSStatus result;
+  OSStatus result, err;
 
   switch (GetEventKind (event))
     {
@@ -8296,22 +9386,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 =
@@ -8333,406 +9432,362 @@ mac_handle_mouse_event (next_handler, event, data)
 
   return eventNotHandledErr;
 }
-#endif /* USE_CARBON_EVENTS */
-
 
-OSErr
-install_window_handler (window)
-     WindowPtr window;
+#if USE_MAC_FONT_PANEL
+static pascal OSStatus
+mac_handle_font_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
 {
-  OSErr err = noErr;
-#if USE_CARBON_EVENTS
-  EventTypeSpec specs_window[] =
-    {{kEventClassWindow, kEventWindowUpdate},
-     {kEventClassWindow, kEventWindowBoundsChanging},
-     {kEventClassWindow, kEventWindowShown},
-     {kEventClassWindow, kEventWindowHidden},
-     {kEventClassWindow, kEventWindowExpanded},
-     {kEventClassWindow, kEventWindowCollapsed}};
-  EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
-  static EventHandlerUPP handle_window_eventUPP = NULL;
-  static EventHandlerUPP handle_mouse_eventUPP = NULL;
+  OSStatus result, err;
+  Lisp_Object id_key;
+  int num_params;
+  EventParamName *names;
+  EventParamType *types;
+  static EventParamName names_sel[] = {kEventParamATSUFontID,
+                                      kEventParamATSUFontSize,
+                                      kEventParamFMFontFamily,
+                                      kEventParamFMFontSize,
+                                      kEventParamFontColor};
+  static EventParamType types_sel[] = {typeATSUFontID,
+                                      typeATSUSize,
+                                      typeFMFontFamily,
+                                      typeFMFontSize,
+                                      typeFontColor};
+
+  result = CallNextEventHandler (next_handler, event);
+  if (result != eventNotHandledErr)
+    return result;
 
-  if (handle_window_eventUPP == NULL)
-    handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
-  if (handle_mouse_eventUPP == NULL)
-    handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
-  err = InstallWindowEventHandler (window, handle_window_eventUPP,
-                                  GetEventTypeCount (specs_window),
-                                  specs_window, NULL, NULL);
-  if (err == noErr)
-    err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
-                                    GetEventTypeCount (specs_mouse),
-                                    specs_mouse, NULL, NULL);
-#endif
-#if TARGET_API_MAC_CARBON
-  if (mac_do_track_dragUPP == NULL)
-    mac_do_track_dragUPP = NewDragTrackingHandlerUPP (mac_do_track_drag);
-  if (mac_do_receive_dragUPP == NULL)
-    mac_do_receive_dragUPP = NewDragReceiveHandlerUPP (mac_do_receive_drag);
+  switch (GetEventKind (event))
+    {
+    case kEventFontPanelClosed:
+      id_key = Qpanel_closed;
+      num_params = 0;
+      names = NULL;
+      types = NULL;
+      break;
 
-  if (err == noErr)
-    err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL);
-  if (err == noErr)
-    err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
-#endif
-  return err;
-}
+    case kEventFontSelection:
+      id_key = Qselection;
+      num_params = sizeof (names_sel) / sizeof (names_sel[0]);
+      names = names_sel;
+      types = types_sel;
+      break;
+    }
 
-void
-remove_window_handler (window)
-     WindowPtr window;
-{
-#if TARGET_API_MAC_CARBON
-  if (mac_do_track_dragUPP)
-    RemoveTrackingHandler (mac_do_track_dragUPP, window);
-  if (mac_do_receive_dragUPP)
-    RemoveReceiveHandler (mac_do_receive_dragUPP, window);
-#endif
-}
+  err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
+                                           event, num_params,
+                                           names, types);
 
-/* Open Application Apple Event */
-static pascal OSErr
-do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
-{
-  return noErr;
+  return err == noErr ? noErr : eventNotHandledErr;
 }
+#endif
 
-
-/* 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)
+#if USE_MAC_TSM
+static pascal OSStatus
+mac_handle_text_input_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
 {
-  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);
+  OSStatus result, err = noErr;
+  Lisp_Object id_key = Qnil;
+  int num_params;
+  EventParamName *names;
+  EventParamType *types;
+  static UInt32 seqno_uaia = 0;
+  static EventParamName names_uaia[] =
+    {kEventParamTextInputSendComponentInstance,
+     kEventParamTextInputSendRefCon,
+     kEventParamTextInputSendSLRec,
+     kEventParamTextInputSendFixLen,
+     kEventParamTextInputSendText,
+     kEventParamTextInputSendUpdateRng,
+     kEventParamTextInputSendHiliteRng,
+     kEventParamTextInputSendClauseRng,
+     kEventParamTextInputSendPinRng,
+     kEventParamTextInputSendTextServiceEncoding,
+     kEventParamTextInputSendTextServiceMacEncoding,
+     EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
+  static EventParamType types_uaia[] =
+    {typeComponentInstance,
+     typeLongInteger,
+     typeIntlWritingCode,
+     typeLongInteger,
+     typeUnicodeText,
+     typeTextRangeArray,
+     typeTextRangeArray,
+     typeOffsetArray,
+     typeTextRange,
+     typeUInt32,
+     typeUInt32,
+     typeUInt32};
+  static EventParamName names_ufke[] =
+    {kEventParamTextInputSendComponentInstance,
+     kEventParamTextInputSendRefCon,
+     kEventParamTextInputSendSLRec,
+     kEventParamTextInputSendText};
+  static EventParamType types_ufke[] =
+    {typeComponentInstance,
+     typeLongInteger,
+     typeIntlWritingCode,
+     typeUnicodeText};
+
+  result = CallNextEventHandler (next_handler, event);
 
-  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;
+  switch (GetEventKind (event))
+    {
+    case kEventTextInputUpdateActiveInputArea:
+      id_key = Qupdate_active_input_area;
+      num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
+      names = names_uaia;
+      types = types_uaia;
+      SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
+                        typeUInt32, sizeof (UInt32), &seqno_uaia);
+      seqno_uaia++;
+      break;
 
-    err = AECountItems (&the_desc, &num_files_to_open);
-    if (err == noErr)
+    case kEventTextInputUnicodeForKeyEvent:
       {
-        int i;
-
-        /* AE file list is one based so just use that for indexing here.  */
-        for (i = 1; i <= num_files_to_open; i++)
+       EventRef kbd_event;
+       UInt32 actual_size, modifiers, mapped_modifiers;
+       UniChar code;
+
+       err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
+                                typeEventRef, NULL, sizeof (EventRef), NULL,
+                                &kbd_event);
+       if (err == noErr)
+         err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
+                                  typeUInt32, NULL,
+                                  sizeof (UInt32), NULL, &modifiers);
+       if (err == noErr)
          {
-           char unix_path_name[MAXPATHLEN];
+           mapped_modifiers =
+             (NILP (Vmac_control_modifier) ? 0 : controlKey)
+             | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+             | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
 #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)
+           mapped_modifiers |=
+             (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
 #endif
-             /* x-dnd functions expect undecoded filenames.  */
-             file_list = Fcons (make_unibyte_string (unix_path_name,
-                                                     strlen (unix_path_name)),
-                                file_list);
+           if (modifiers & mapped_modifiers)
+             /* There're mapped modifier keys.  Process it in
+                XTread_socket.  */
+             return eventNotHandledErr;
          }
-      }
-
-    /* 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
+       if (err == noErr)
+         err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
+                                  typeUnicodeText, NULL, 0, &actual_size,
+                                  NULL);
+       if (err == noErr)
          {
-           Rect r;
-
-           GetWindowPortBounds (wp, &r);
-           InvalWindowRect (wp, &r);
+           if (actual_size == sizeof (UniChar))
+             err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
+                                      typeUnicodeText, NULL,
+                                      sizeof (UniChar), NULL, &code);
+           if (err == noErr && code < 0x80)
+             {
+               /* ASCII character.  Process it in XTread_socket.  */
+               if (read_socket_inev && code >= 0x20 && code <= 0x7e)
+                 {
+                   struct frame *f = mac_focus_frame (&one_mac_display_info);
+
+                   read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
+                   read_socket_inev->code = code;
+                   read_socket_inev->modifiers =
+                     (extra_keyboard_modifiers
+                      & (meta_modifier | alt_modifier
+                         | hyper_modifier | super_modifier));
+                   XSETFRAME (read_socket_inev->frame_or_window, f);
+                 }
+               return eventNotHandledErr;
+             }
          }
-#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,
-                  void *handlerRefCon, DragReference theDrag)
-{
-  static int can_accept;
-  short items;
-  short index;
-  ItemReference theItem;
-  FlavorFlags theFlags;
-  OSErr result;
-
-  if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
-    return dragNotAcceptedErr;
-
-  switch (message)
-    {
-    case kDragTrackingEnterHandler:
-      CountDragItems (theDrag, &items);
-      can_accept = 0;
-      for (index = 1; index <= items; index++)
-       {
-         GetDragItemReferenceNumber (theDrag, index, &theItem);
-         result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
-         if (result == noErr)
-           {
-             can_accept = 1;
-             break;
-           }
-       }
+      /* Non-ASCII keystrokes without mapped modifiers are processed
+        at the Lisp level.  */
+      id_key = Qunicode_for_key_event;
+      num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
+      names = names_ufke;
+      types = types_ufke;
       break;
 
-    case kDragTrackingEnterWindow:
-      if (can_accept)
-       {
-         RgnHandle hilite_rgn = NewRgn ();
-         Rect r;
-         struct frame *f = mac_window_to_frame (window);
-
-         GetWindowPortBounds (window, &r);
-         OffsetRect (&r, -r.left, -r.top);
-         RectRgn (hilite_rgn, &r);
-         ShowDragHilite (theDrag, hilite_rgn, true);
-         DisposeRgn (hilite_rgn);
-         SetThemeCursor (kThemeCopyArrowCursor);
-       }
-      break;
+    case kEventTextInputOffsetToPos:
+      {
+       struct frame *f;
+       struct window *w;
+       Point p;
 
-    case kDragTrackingInWindow:
-      break;
+       if (!OVERLAYP (Vmac_ts_active_input_overlay))
+         return eventNotHandledErr;
 
-    case kDragTrackingLeaveWindow:
-      if (can_accept)
-       {
-         struct frame *f = mac_window_to_frame (window);
+       /* Strictly speaking, this is not always correct because
+          previous events may change some states about display.  */
+       if (NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
+         {
+           /* Active input area is displayed in the echo area.  */
+           w = XWINDOW (echo_area_window);
+           f = WINDOW_XFRAME (w);
+         }
+       else
+         {
+           /* Active input area is displayed around the current point.  */
+           f = SELECTED_FRAME ();
+           w = XWINDOW (f->selected_window);
+         }
 
-         HideDragHilite (theDrag);
-         SetThemeCursor (kThemeArrowCursor);
-       }
+       p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
+              + WINDOW_LEFT_FRINGE_WIDTH (w));
+       p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
+              + FONT_BASE (FRAME_FONT (f)));
+       SetPortWindowPort (FRAME_MAC_WINDOW (f));
+       LocalToGlobal (&p);
+       err = SetEventParameter (event, kEventParamTextInputReplyPoint,
+                                typeQDPoint, sizeof (typeQDPoint), &p);
+      }
       break;
 
-    case kDragTrackingLeaveHandler:
-      break;
+    default:
+      abort ();
     }
 
-  return noErr;
+  if (!NILP (id_key))
+    err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
+                                             event, num_params,
+                                             names, types);
+
+  return err == noErr ? noErr : result;
 }
+#endif
 
-static pascal OSErr
-mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
-                    DragReference theDrag)
+#ifdef MAC_OSX
+OSStatus
+mac_store_service_event (event)
+     EventRef event;
 {
-  short items;
-  short index;
-  FlavorFlags theFlags;
-  Point mouse;
-  OSErr result;
-  ItemReference theItem;
-  HFSFlavor data;
-  Size size = sizeof (HFSFlavor);
-  Lisp_Object file_list;
-
-  if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
-    return dragNotAcceptedErr;
+  OSStatus err;
+  Lisp_Object id_key;
+  int num_params;
+  EventParamName *names;
+  EventParamType *types;
+  static EventParamName names_pfm[] = {kEventParamServiceMessageName,
+                                      kEventParamServiceUserData};
+  static EventParamType types_pfm[] = {typeCFStringRef,
+                                      typeCFStringRef};
 
-  file_list = Qnil;
-  GetDragMouse (theDrag, &mouse, 0L);
-  CountDragItems (theDrag, &items);
-  for (index = 1; index <= items; index++)
+  switch (GetEventKind (event))
     {
-      /* Only handle file references.  */
-      GetDragItemReferenceNumber (theDrag, index, &theItem);
-      result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
-      if (result == noErr)
-       {
-#ifdef MAC_OSX
-         FSRef fref;
-#endif
-         char unix_path_name[MAXPATHLEN];
+    case kEventServicePaste:
+      id_key = Qpaste;
+      num_params = 0;
+      names = NULL;
+      types = NULL;
+      break;
 
-         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);
-       }
-    }
-  /* If there are items in the list, construct an event and post it to
-     the queue like an interrupt using kbd_buffer_store_event.  */
-  if (!NILP (file_list))
-    {
-      struct input_event event;
-      Lisp_Object frame;
-      struct frame *f = mac_window_to_frame (window);
-      SInt16 modifiers;
-
-      GlobalToLocal (&mouse);
-      GetDragModifiers (theDrag, NULL, NULL, &modifiers);
-
-      event.kind = DRAG_N_DROP_EVENT;
-      event.code = 0;
-      event.modifiers = mac_to_emacs_modifiers (modifiers);
-      event.timestamp = TickCount () * (1000 / 60);
-      XSETINT (event.x, mouse.h);
-      XSETINT (event.y, mouse.v);
-      XSETFRAME (frame, f);
-      event.frame_or_window = Fcons (frame, file_list);
-      event.arg = Qnil;
-      /* Post to the interrupt queue */
-      kbd_buffer_store_event (&event);
-      /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
-      {
-       ProcessSerialNumber psn;
-       GetCurrentProcess (&psn);
-       SetFrontProcess (&psn);
-      }
+    case kEventServicePerform:
+      id_key = Qperform;
+      num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
+      names = names_pfm;
+      types = types_pfm;
+      break;
 
-      return noErr;
+    default:
+      abort ();
     }
-  else
-    return dragNotAcceptedErr;
-}
-#endif
 
+  err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
+                                           event, num_params,
+                                           names, types);
 
-/* Print Document Apple Event */
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
-{
-  return errAEEventNotHandled;
+  return err;
 }
+#endif /* MAC_OSX */
+#endif /* USE_CARBON_EVENTS */
 
 
-static pascal OSErr
-do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
+OSErr
+install_window_handler (window)
+     WindowPtr window;
 {
+  OSErr err = noErr;
 #if USE_CARBON_EVENTS
-  OSErr err;
-  EventRef event = NULL;
-  static const HICommand quit_command = {kEventAttributeNone, kHICommandQuit};
+  EventTypeSpec specs_window[] =
+    {{kEventClassWindow, kEventWindowUpdate},
+     {kEventClassWindow, kEventWindowBoundsChanging},
+     {kEventClassWindow, kEventWindowShown},
+     {kEventClassWindow, kEventWindowHidden},
+     {kEventClassWindow, kEventWindowExpanded},
+     {kEventClassWindow, kEventWindowCollapsed},
+#ifdef MAC_OSX
+     {kEventClassWindow, kEventWindowToolbarSwitchMode},
+#endif
+#if USE_MAC_TSM
+     {kEventClassWindow, kEventWindowFocusAcquired},
+     {kEventClassWindow, kEventWindowFocusRelinquish},
+#endif
+  };
+  EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
+  static EventHandlerUPP handle_window_eventUPP = NULL;
+  static EventHandlerUPP handle_mouse_eventUPP = NULL;
+#if USE_MAC_FONT_PANEL
+  EventTypeSpec specs_font[] = {{kEventClassFont, kEventFontPanelClosed},
+                               {kEventClassFont, kEventFontSelection}};
+  static EventHandlerUPP handle_font_eventUPP = NULL;
+#endif
+#if USE_MAC_TSM
+  EventTypeSpec specs_text_input[] =
+    {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
+     {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
+     {kEventClassTextInput, kEventTextInputOffsetToPos}};
+  static EventHandlerUPP handle_text_input_eventUPP = NULL;
+#endif
 
-  err = CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 0,
-                    kEventAttributeUserEvent, &event);
+  if (handle_window_eventUPP == NULL)
+    handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
+  if (handle_mouse_eventUPP == NULL)
+    handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
+#if USE_MAC_FONT_PANEL
+  if (handle_font_eventUPP == NULL)
+    handle_font_eventUPP = NewEventHandlerUPP (mac_handle_font_event);
+#endif
+#if USE_MAC_TSM
+  if (handle_text_input_eventUPP == NULL)
+    handle_text_input_eventUPP =
+      NewEventHandlerUPP (mac_handle_text_input_event);
+#endif
+  err = InstallWindowEventHandler (window, handle_window_eventUPP,
+                                  GetEventTypeCount (specs_window),
+                                  specs_window, NULL, NULL);
   if (err == noErr)
-    err = SetEventParameter (event, kEventParamDirectObject, typeHICommand,
-                            sizeof (HICommand), &quit_command);
+    err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
+                                    GetEventTypeCount (specs_mouse),
+                                    specs_mouse, NULL, NULL);
+#if USE_MAC_FONT_PANEL
   if (err == noErr)
-    mac_store_application_menu_event (event);
-  if (event)
-    ReleaseEvent (event);
-
+    err = InstallWindowEventHandler (window, handle_font_eventUPP,
+                                    GetEventTypeCount (specs_font),
+                                    specs_font, NULL, NULL);
+#endif
+#if USE_MAC_TSM
   if (err == noErr)
-    return noErr;
-  else
-    return errAEEventNotHandled;
-#else
-  mac_store_application_menu_event (kHICommandQuit);
-
-  return noErr;
+    err = InstallWindowEventHandler (window, handle_text_input_eventUPP,
+                                    GetEventTypeCount (specs_text_input),
+                                    specs_text_input, window, NULL);
 #endif
+#endif
+  if (err == noErr)
+    err = install_drag_handler (window);
+
+  return err;
+}
+
+void
+remove_window_handler (window)
+     WindowPtr window;
+{
+  remove_drag_handler (window);
 }
 
 
@@ -8787,9 +9842,11 @@ main (void)
 
   init_environ ();
 
+  init_coercion_handler ();
+
   initialize_applescript ();
 
-  init_required_apple_events ();
+  init_apple_event_handler ();
 
   {
     char **argv;
@@ -8844,7 +9901,7 @@ static unsigned char keycode_to_xkeysym_table[] = {
 
   /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
   /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
-  /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
+  /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
   /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
 
   /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
@@ -8853,6 +9910,7 @@ static unsigned char keycode_to_xkeysym_table[] = {
   /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
 };
 
+
 static int
 keycode_to_xkeysym (int keyCode, int *xKeySym)
 {
@@ -8860,6 +9918,44 @@ keycode_to_xkeysym (int keyCode, int *xKeySym)
   return *xKeySym != 0;
 }
 
+#ifdef MAC_OSX
+/* Table for translating Mac keycode with the laptop `fn' key to that
+   without it.  Destination symbols in comments are keys on US
+   keyboard, and they may not be the same on other types of keyboards.
+   If the destination is identical to the source (f1 ... f12), it
+   doesn't map `fn' key to a modifier.  */
+static unsigned char fn_keycode_to_keycode_table[] = {
+  /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+  /*0x30*/ 0, 0, 0, 0,
+  /*0x34*/ 0, 0, 0, 0,
+  /*0x38*/ 0, 0, 0, 0,
+  /*0x3C*/ 0, 0, 0, 0,
+
+  /*0x40*/ 0, 0x2f /*kp-. -> '.'*/, 0, 0x23 /*kp-* -> 'p'*/,
+  /*0x44*/ 0, 0x2c /*kp-+ -> '/'*/, 0, 0x16 /*clear -> '6'*/,
+  /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
+  /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-- -> ';'*/, 0,
+
+  /*0x50*/ 0, 0x1b /*kp-= -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
+  /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
+  /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
+  /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
+
+  /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
+  /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
+  /*0x68*/ 0, 0, 0, 0,
+  /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
+
+  /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
+  /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
+  /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
+  /*0x7C*/ 0, 0, 0, 0
+};
+#endif /* MAC_OSX */
+
 #if !USE_CARBON_EVENTS
 static RgnHandle mouse_region = NULL;
 
@@ -8877,7 +9973,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 ();
@@ -8899,6 +9995,79 @@ mac_wait_next_event (er, sleep_time, dequeue)
 }
 #endif /* not USE_CARBON_EVENTS */
 
+#if TARGET_API_MAC_CARBON
+OSStatus
+mac_post_mouse_moved_event ()
+{
+  EventRef event = NULL;
+  OSStatus err;
+
+  err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
+                    kEventAttributeNone, &event);
+  if (err == noErr)
+    {
+      Point mouse_pos;
+
+      GetMouse (&mouse_pos);
+      LocalToGlobal (&mouse_pos);
+      err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
+                              sizeof (Point), &mouse_pos);
+    }
+  if (err == noErr)
+    {
+      UInt32 modifiers = GetCurrentKeyModifiers ();
+
+      err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
+                              sizeof (UInt32), &modifiers);
+    }
+  if (err == noErr)
+    err = PostEventToQueue (GetCurrentEventQueue (), event,
+                           kEventPriorityStandard);
+  if (event)
+    ReleaseEvent (event);
+
+  return err;
+}
+
+static void
+mac_set_unicode_keystroke_event (code, buf)
+     UniChar code;
+     struct input_event *buf;
+{
+  int charset_id, c1, c2;
+
+  if (code < 0x80)
+    {
+      buf->kind = ASCII_KEYSTROKE_EVENT;
+      buf->code = code;
+    }
+  else if (code < 0x100)
+    {
+      if (code < 0xA0)
+       charset_id = CHARSET_8_BIT_CONTROL;
+      else
+       charset_id = charset_latin_iso8859_1;
+      buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+      buf->code = MAKE_CHAR (charset_id, code, 0);
+    }
+  else
+    {
+      if (code < 0x2500)
+       charset_id = charset_mule_unicode_0100_24ff,
+         code -= 0x100;
+      else if (code < 0x33FF)
+       charset_id = charset_mule_unicode_2500_33ff,
+         code -= 0x2500;
+      else if (code >= 0xE000)
+       charset_id = charset_mule_unicode_e000_ffff,
+         code -= 0xE000;
+      c1 = (code / 96) + 32, c2 = (code % 96) + 32;
+      buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+      buf->code = MAKE_CHAR (charset_id, c1, c2);
+    }
+}
+#endif
+
 /* Emacs calls this whenever it wants to read an input event from the
    user. */
 int
@@ -8927,10 +10096,16 @@ XTread_socket (sd, expected, hold_quit)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
+  ++handling_signal;
+
 #if USE_CARBON_EVENTS
   toolbox_dispatcher = GetEventDispatcherTarget ();
 
-  while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
+  while (
+#if USE_CG_DRAWING
+        mac_prepare_for_quickdraw (NULL),
+#endif
+        !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
                            kEventRemoveFromQueue, &eventRef))
 #else /* !USE_CARBON_EVENTS */
   while (mac_wait_next_event (&er, 0, true))
@@ -8940,10 +10115,6 @@ XTread_socket (sd, expected, hold_quit)
       struct frame *f;
       unsigned long timestamp;
 
-      /* It is necessary to set this (additional) argument slot of an
-        event to nil because keyboard.c protects incompletely
-        processed event from being garbage collected by placing them
-        in the kbd_buffer_gcpro vector.  */
       EVENT_INIT (inev);
       inev.kind = NO_EVENT;
       inev.arg = Qnil;
@@ -8988,6 +10159,7 @@ XTread_socket (sd, expected, hold_quit)
                != eventNotHandledErr)
              break;
 #endif
+           last_mouse_glyph_frame = 0;
 
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
@@ -9005,7 +10177,8 @@ XTread_socket (sd, expected, hold_quit)
                  }
              }
 
-           if (er.what != mouseDown && part_code != inContent)
+           if (er.what != mouseDown &&
+               (part_code != inContent || dpyinfo->grabbed == 0))
              break;
 
            switch (part_code)
@@ -9018,7 +10191,13 @@ XTread_socket (sd, expected, hold_quit)
                break;
 
              case inContent:
-               if (window_ptr != FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo)))
+               if (
+#if TARGET_API_MAC_CARBON
+                   FrontNonFloatingWindow ()
+#else
+                   FrontWindow ()
+#endif
+                   != window_ptr)
                  SelectWindow (window_ptr);
                else
                  {
@@ -9056,18 +10235,18 @@ XTread_socket (sd, expected, hold_quit)
                    XSETINT (inev.x, mouse_loc.h);
                    XSETINT (inev.y, mouse_loc.v);
 
-                   if (dpyinfo->grabbed && tracked_scroll_bar
-                       || ch != 0
+                   if ((dpyinfo->grabbed && tracked_scroll_bar)
+                       || (ch != 0
 #ifndef USE_TOOLKIT_SCROLL_BARS
-                       /* control_part_code becomes kControlNoPart if
-                          a progress indicator is clicked.  */
-                       && control_part_code != kControlNoPart
+                           /* control_part_code becomes kControlNoPart if
+                              a progress indicator is clicked.  */
+                           && control_part_code != kControlNoPart
 #else  /* USE_TOOLKIT_SCROLL_BARS */
 #ifdef MAC_OSX
-                       && control_kind.kind == kControlKindScrollBar
+                           && control_kind.kind == kControlKindScrollBar
 #endif /* MAC_OSX */
 #endif /* USE_TOOLKIT_SCROLL_BARS */
-                       )
+                           ))
                      {
                        struct scroll_bar *bar;
 
@@ -9128,12 +10307,6 @@ XTread_socket (sd, expected, hold_quit)
                      {
                        dpyinfo->grabbed |= (1 << inev.code);
                        last_mouse_frame = f;
-                       /* Ignore any mouse motion that happened
-                          before this event; any subsequent
-                          mouse-movement Emacs events should reflect
-                          only motion after the ButtonPress.  */
-                       if (f != 0)
-                         f->mouse_moved = 0;
 
                        if (!tool_bar_p)
                          last_tool_bar_item = -1;
@@ -9149,6 +10322,13 @@ XTread_socket (sd, expected, hold_quit)
                          dpyinfo->grabbed &= ~(1 << inev.code);
                      }
 
+                   /* Ignore any mouse motion that happened before
+                      this event; any subsequent mouse-movement Emacs
+                      events should reflect only motion after the
+                      ButtonPress.  */
+                   if (f != 0)
+                     f->mouse_moved = 0;
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
                    if (inev.kind == MOUSE_CLICK_EVENT)
 #endif
@@ -9166,6 +10346,16 @@ XTread_socket (sd, expected, hold_quit)
 
              case inDrag:
 #if TARGET_API_MAC_CARBON
+             case inProxyIcon:
+               if (IsWindowPathSelectClick (window_ptr, &er))
+                 {
+                   WindowPathSelect (window_ptr, NULL, NULL);
+                   break;
+                 }
+               if (part_code == inProxyIcon
+                   && (TrackWindowProxyDrag (window_ptr, er.where)
+                       != errUserWantsToDragWindow))
+                 break;
                DragWindow (window_ptr, er.where, NULL);
 #else /* not TARGET_API_MAC_CARBON */
                DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
@@ -9237,8 +10427,7 @@ XTread_socket (sd, expected, hold_quit)
                          er.where.h + 1, er.where.v + 1);
 #endif
              previous_help_echo_string = help_echo_string;
-             help_echo_string = help_echo_object = help_echo_window = Qnil;
-             help_echo_pos = -1;
+             help_echo_string = Qnil;
 
              if (dpyinfo->grabbed && last_mouse_frame
                  && FRAME_LIVE_P (last_mouse_frame))
@@ -9297,7 +10486,8 @@ XTread_socket (sd, expected, hold_quit)
 
                          last_window=window;
                        }
-                     note_mouse_movement (f, &mouse_pos);
+                     if (!note_mouse_movement (f, &mouse_pos))
+                       help_echo_string = previous_help_echo_string;
                    }
                }
 
@@ -9386,10 +10576,29 @@ XTread_socket (sd, expected, hold_quit)
          break;
 
        case keyDown:
+       case keyUp:
        case autoKey:
          {
            int keycode = (er.message & keyCodeMask) >> 8;
            int xkeysym;
+           static SInt16 last_key_script = -1;
+           SInt16 current_key_script;
+           UInt32 modifiers = er.modifiers, mapped_modifiers;
+
+           mapped_modifiers =
+             (NILP (Vmac_control_modifier) ? 0 : controlKey)
+             | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+             | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+
+#if USE_CARBON_EVENTS && defined (MAC_OSX)
+           mapped_modifiers |=
+             (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
+
+           GetEventParameter (eventRef, kEventParamKeyModifiers,
+                              typeUInt32, NULL,
+                              sizeof (UInt32), NULL, &modifiers);
+#endif
+           mapped_modifiers &= modifiers;
 
 #if USE_CARBON_EVENTS && defined (MAC_OSX)
            /* When using Carbon Events, we need to pass raw keyboard
@@ -9397,65 +10606,111 @@ 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)
-                || !(er.modifiers & cmdKey))
-               && (!NILP (Vmac_pass_control_to_system)
-                   || !(er.modifiers & controlKey))
-               && (!NILP (Vmac_command_key_is_meta)
-                   && NILP (Vmac_option_modifier)
-                   || !(er.modifiers & optionKey)))
-             if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
-                 != eventNotHandledErr)
-               break;
-#endif
-
-#if 0
-           if (dpyinfo->x_focus_frame == NULL)
+           if (!(mapped_modifiers
+                 & ~(mac_pass_command_to_system ? cmdKey : 0)
+                 & ~(mac_pass_control_to_system ? controlKey : 0)))
              {
-               /* Beep if keyboard input occurs when all the frames
-                  are invisible.  */
-               SysBeep (1);
-               break;
+               OSStatus err;
+
+               read_socket_inev = &inev;
+               err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
+               read_socket_inev = NULL;
+               if (err != eventNotHandledErr)
+                 break;
              }
 #endif
-
-           {
-             static SInt16 last_key_script = -1;
-             SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
-
-             if (last_key_script != current_key_script)
-               {
-                 struct input_event event;
-
-                 EVENT_INIT (event);
-                 event.kind = LANGUAGE_CHANGE_EVENT;
-                 event.arg = Qnil;
-                 event.code = current_key_script;
-                 event.timestamp = timestamp;
-                 kbd_buffer_store_event (&event);
-                 count++;
-               }
-             last_key_script = current_key_script;
-           }
+           if (er.what == keyUp)
+             break;
 
            ObscureCursor ();
 
-           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+           f = mac_focus_frame (dpyinfo);
+
+           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+               && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
              {
                clear_mouse_face (dpyinfo);
                dpyinfo->mouse_face_hidden = 1;
              }
 
+           current_key_script = GetScriptManagerVariable (smKeyScript);
+           if (last_key_script != current_key_script)
+             {
+               struct input_event event;
+
+               EVENT_INIT (event);
+               event.kind = LANGUAGE_CHANGE_EVENT;
+               event.arg = Qnil;
+               event.code = current_key_script;
+               event.timestamp = timestamp;
+               kbd_buffer_store_event (&event);
+               count++;
+               last_key_script = current_key_script;
+             }
+
+#if USE_MAC_TSM
+           if (inev.kind != NO_EVENT)
+             break;
+#endif
+
+#ifdef MAC_OSX
+           if (mapped_modifiers & kEventKeyModifierFnMask
+               && keycode <= 0x7f
+               && fn_keycode_to_keycode_table[keycode])
+             keycode = fn_keycode_to_keycode_table[keycode];
+#endif
            if (keycode_to_xkeysym (keycode, &xkeysym))
              {
-               inev.code = 0xff00 | xkeysym;
                inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+               inev.code = 0xff00 | xkeysym;
+#ifdef MAC_OSX
+               if (modifiers & kEventKeyModifierFnMask
+                   && keycode <= 0x7f
+                   && fn_keycode_to_keycode_table[keycode] == keycode)
+                 modifiers &= ~kEventKeyModifierFnMask;
+#endif
              }
-           else
+           else if (mapped_modifiers)
              {
-               if (er.modifiers & (controlKey |
-                                   (NILP (Vmac_command_key_is_meta) ? optionKey
-                                    : cmdKey)))
+               /* translate the keycode back to determine the
+                  original key */
+#ifdef MAC_OSX
+               static SInt16 last_key_layout_id = 0;
+               static Handle uchr_handle = (Handle)-1;
+               SInt16 current_key_layout_id =
+                 GetScriptVariable (current_key_script, smScriptKeys);
+
+               if (uchr_handle == (Handle)-1
+                   || last_key_layout_id != current_key_layout_id)
+                 {
+                   uchr_handle = GetResource ('uchr', current_key_layout_id);
+                   last_key_layout_id = current_key_layout_id;
+                 }
+
+               if (uchr_handle)
+                 {
+                   OSStatus status;
+                   UInt16 key_action = er.what - keyDown;
+                   UInt32 modifier_key_state =
+                     (modifiers & ~mapped_modifiers) >> 8;
+                   UInt32 keyboard_type = LMGetKbdType ();
+                   SInt32 dead_key_state = 0;
+                   UniChar code;
+                   UniCharCount actual_length;
+
+                   status = UCKeyTranslate ((UCKeyboardLayout *)*uchr_handle,
+                                            keycode, key_action,
+                                            modifier_key_state,
+                                            keyboard_type,
+                                            kUCKeyTranslateNoDeadKeysMask,
+                                            &dead_key_state,
+                                            1, &actual_length, &code);
+                   if (status == noErr && actual_length == 1)
+                     mac_set_unicode_keystroke_event (code, &inev);
+                 }
+#endif /* MAC_OSX */
+
+               if (inev.kind == NO_EVENT)
                  {
                    /* This code comes from Keyboard Resource,
                       Appendix C of IM - Text.  This is necessary
@@ -9463,49 +10718,78 @@ XTread_socket (sd, expected, hold_quit)
                       translation when option or command is pressed.
                       It also does not translate correctly
                       control-shift chars like C-% so mask off shift
-                      here also */
-                   int new_modifiers = er.modifiers & 0xe600;
-                   /* mask off option and command */
-                   int new_keycode = keycode | new_modifiers;
-                   Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-                   unsigned long some_state = 0;
-                   inev.code = KeyTranslate (kchr_ptr, new_keycode,
-                                             &some_state) & 0xff;
-                 }
-               else if (!NILP (Vmac_option_modifier)
-                        && (er.modifiers & optionKey))
-                 {
-                   /* When using the option key as an emacs modifier,
-                      convert the pressed key code back to one
-                      without the Mac option modifier applied. */
-                   int new_modifiers = er.modifiers & ~optionKey;
+                      here also.  */
+                   /* Mask off modifier keys that are mapped to some
+                      Emacs modifiers.  */
+                   int new_modifiers = er.modifiers & ~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;
-                   inev.code = KeyTranslate (kchr_ptr, new_keycode,
-                                             &some_state) & 0xff;
+                   UInt32 new_char_code;
+
+                   new_char_code = KeyTranslate (kchr_ptr, new_keycode,
+                                                 &some_state);
+                   if (new_char_code == 0)
+                     /* Seems like a dead key.  Append up-stroke.  */
+                     new_char_code = KeyTranslate (kchr_ptr,
+                                                   new_keycode | 0x80,
+                                                   &some_state);
+                   if (new_char_code)
+                     {
+                       inev.kind = ASCII_KEYSTROKE_EVENT;
+                       inev.code = new_char_code & 0xff;
+                     }
                  }
-               else
-                 inev.code = er.message & charCodeMask;
+             }
+
+           if (inev.kind == NO_EVENT)
+             {
                inev.kind = ASCII_KEYSTROKE_EVENT;
+               inev.code = er.message & charCodeMask;
              }
-         }
 
-#if USE_CARBON_EVENTS
-         inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-         inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+           inev.modifiers = mac_to_emacs_modifiers (modifiers);
+           inev.modifiers |= (extra_keyboard_modifiers
+                              & (meta_modifier | alt_modifier
+                                 | hyper_modifier | super_modifier));
+           XSETFRAME (inev.frame_or_window, f);
+
+#if TARGET_API_MAC_CARBON
+           if (inev.kind == ASCII_KEYSTROKE_EVENT
+               && inev.code >= 0x80 && inev.modifiers)
+             {
+               OSStatus err;
+               TextEncoding encoding = kTextEncodingMacRoman;
+               TextToUnicodeInfo ttu_info;
+
+               UpgradeScriptInfoToTextEncoding (current_key_script,
+                                                kTextLanguageDontCare,
+                                                kTextRegionDontCare,
+                                                NULL, &encoding);
+               err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
+               if (err == noErr)
+                 {
+                   UniChar code;
+                   Str255 pstr;
+                   ByteCount unicode_len;
+
+                   pstr[0] = 1;
+                   pstr[1] = inev.code;
+                   err = ConvertFromPStringToUnicode (ttu_info, pstr,
+                                                      sizeof (UniChar),
+                                                      &unicode_len, &code);
+                   if (err == noErr && unicode_len == sizeof (UniChar))
+                     mac_set_unicode_keystroke_event (code, &inev);
+                   DisposeTextToUnicodeInfo (&ttu_info);
+                 }
+             }
 #endif
-         inev.modifiers |= (extra_keyboard_modifiers
-                            & (meta_modifier | alt_modifier
-                               | hyper_modifier | super_modifier));
-         XSETFRAME (inev.frame_or_window, mac_focus_frame (dpyinfo));
+         }
          break;
 
        case kHighLevelEvent:
-         read_socket_inev = &inev;
          AEProcessAppleEvent (&er);
-         read_socket_inev = NULL;
          break;
 
        default:
@@ -9580,6 +10864,7 @@ XTread_socket (sd, expected, hold_quit)
   }
 #endif
 
+  --handling_signal;
   UNBLOCK_INPUT;
   return count;
 }
@@ -9715,8 +11000,8 @@ mac_initialize_display_info ()
   main_device_handle = LMGetMainDevice();
 
   dpyinfo->reference_count = 0;
-  dpyinfo->resx = 75.0;
-  dpyinfo->resy = 75.0;
+  dpyinfo->resx = 72.0;
+  dpyinfo->resy = 72.0;
   dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
 #ifdef MAC_OSX
   /* HasDepth returns true if it is possible to have a 32 bit display,
@@ -9878,7 +11163,6 @@ mac_check_bundle()
   extern int inhibit_window_system;
   extern int noninteractive;
   CFBundleRef appsBundle;
-  pid_t child;
 
   /* No need to test if already -nw*/
   if (inhibit_window_system || noninteractive)
@@ -9928,10 +11212,9 @@ mac_determine_quit_char_modifiers()
 
   /* Map modifiers */
   mac_quit_char_modifiers = 0;
-  if (qc_modifiers & ctrl_modifier)  mac_quit_char_modifiers |= macCtrlKey;
-  if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
-  if (qc_modifiers & meta_modifier)  mac_quit_char_modifiers |= macMetaKey;
-  if (qc_modifiers & alt_modifier)   mac_quit_char_modifiers |= macAltKey;
+  if (qc_modifiers & ctrl_modifier)  mac_quit_char_modifiers |= controlKey;
+  if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
+  if (qc_modifiers & alt_modifier)   mac_quit_char_modifiers |= optionKey;
 }
 
 static void
@@ -9944,75 +11227,6 @@ init_quit_char_handler ()
 
   mac_determine_quit_char_modifiers();
 }
-
-static Boolean
-quit_char_comp (EventRef inEvent, void *inCompData)
-{
-  if (GetEventClass(inEvent) != kEventClassKeyboard)
-    return false;
-  if (GetEventKind(inEvent) != kEventRawKeyDown)
-    return false;
-  {
-    UInt32 keyCode;
-    UInt32 keyModifiers;
-    GetEventParameter(inEvent, kEventParamKeyCode,
-                     typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
-    if (keyCode != mac_quit_char_keycode)
-      return false;
-    GetEventParameter(inEvent, kEventParamKeyModifiers,
-                     typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
-    if (keyModifiers != mac_quit_char_modifiers)
-      return false;
-  }
-  return true;
-}
-
-void
-mac_check_for_quit_char ()
-{
-  EventRef event;
-  static EMACS_TIME last_check_time = { 0, 0 };
-  static EMACS_TIME one_second = { 1, 0 };
-  EMACS_TIME now, t;
-
-  /* If windows are not initialized, return immediately (keep it bouncin').  */
-  if (!mac_quit_char_modifiers)
-    return;
-
-  /* Don't check if last check is less than a second ago.  */
-  EMACS_GET_TIME (now);
-  EMACS_SUB_TIME (t, now, last_check_time);
-  if (EMACS_TIME_LT (t, one_second))
-    return;
-  last_check_time = now;
-
-  /* Redetermine modifiers because they are based on lisp variables */
-  mac_determine_quit_char_modifiers ();
-
-  /* Fill the queue with events */
-  BLOCK_INPUT;
-  ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
-  event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
-                                   NULL);
-  UNBLOCK_INPUT;
-  if (event)
-    {
-      struct input_event e;
-
-      /* Use an input_event to emulate what the interrupt handler does. */
-      EVENT_INIT (e);
-      e.kind = ASCII_KEYSTROKE_EVENT;
-      e.code = quit_char;
-      e.arg = Qnil;
-      e.modifiers = NULL;
-      e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
-      XSETFRAME (e.frame_or_window, mac_focus_frame (&one_mac_display_info));
-      /* Remove event from queue to prevent looping. */
-      RemoveEventFromQueue (GetMainEventQueue (), event);
-      ReleaseEvent (event);
-      kbd_buffer_store_event (&e);
-    }
-}
 #endif /* MAC_OSX */
 
 static void
@@ -10047,6 +11261,16 @@ init_menu_bar ()
 #endif
 }
 
+#if USE_MAC_TSM
+static void
+init_tsm ()
+{
+  static InterfaceTypeList types = {kUnicodeDocument};
+
+  NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
+                 &tsm_document_id, 0);
+}
+#endif
 
 /* Set up use of X before we make the first connection.  */
 
@@ -10070,8 +11294,13 @@ static struct redisplay_interface x_redisplay_interface =
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
   x_draw_fringe_bitmap,
+#if USE_CG_DRAWING
+  mac_define_fringe_bitmap,
+  mac_destroy_fringe_bitmap,
+#else
   0, /* define_fringe_bitmap */
   0, /* destroy_fringe_bitmap */
+#endif
   mac_per_char_metric,
   mac_encode_char,
   mac_compute_glyph_string_overhangs,
@@ -10125,7 +11354,6 @@ mac_initialize ()
   BLOCK_INPUT;
 
 #if TARGET_API_MAC_CARBON
-  init_required_apple_events ();
 
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
@@ -10137,13 +11365,26 @@ mac_initialize ()
   init_command_handler ();
 
   init_menu_bar ();
+
+#if USE_MAC_TSM
+  init_tsm ();
+#endif
 #endif /* USE_CARBON_EVENTS */
 
 #ifdef MAC_OSX
+  init_coercion_handler ();
+
+  init_apple_event_handler ();
+
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
 #endif
+
+#if USE_CG_DRAWING
+  mac_init_fringe ();
+#endif
+
   UNBLOCK_INPUT;
 }
 
@@ -10156,23 +11397,42 @@ 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");
-  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));
+  staticpro (&Qmodifier_value);
 
-  Qapplication = intern ("application");  staticpro (&Qapplication);
-  Qabout       = intern ("about");       staticpro (&Qabout);
+  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 && defined (MAC_OSX)
-  Qpreferences = intern ("preferences");  staticpro (&Qpreferences);
-  Qservices    = intern ("services");    staticpro (&Qservices);
+#if USE_CARBON_EVENTS
+  Qhicommand   = intern ("hicommand");    staticpro (&Qhicommand);
+#ifdef MAC_OSX
+  Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
+  staticpro (&Qtoolbar_switch_mode);
+#if USE_MAC_FONT_PANEL
+  Qpanel_closed = intern ("panel-closed");  staticpro (&Qpanel_closed);
+  Qselection    = intern ("selection");     staticpro (&Qselection);
+#endif
+
+  Qservice     = intern ("service");     staticpro (&Qservice);
   Qpaste       = intern ("paste");       staticpro (&Qpaste);
   Qperform     = intern ("perform");     staticpro (&Qperform);
 #endif
+#if USE_MAC_TSM
+  Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
+  Qupdate_active_input_area = intern ("update-active-input-area");
+  staticpro (&Qupdate_active_input_area);
+  Qunicode_for_key_event = intern ("unicode-for-key-event");
+  staticpro (&Qunicode_for_key_event);
+#endif
+#endif
 
 #ifdef MAC_OSX
   Fprovide (intern ("mac-carbon"), Qnil);
@@ -10187,11 +11447,28 @@ syms_of_macterm ()
   staticpro (&last_mouse_scroll_bar);
   last_mouse_scroll_bar = Qnil;
 
-  Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
-  staticpro (&Qmac_ready_for_drag_n_drop);
+  staticpro (&fm_font_family_alist);
+  fm_font_family_alist = Qnil;
+
+#if USE_ATSUI
+  staticpro (&atsu_font_id_hash);
+  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.  */);
+    doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
 #ifdef USE_TOOLKIT_SCROLL_BARS
   Vx_toolkit_scroll_bars = Qt;
 #else
@@ -10201,73 +11478,107 @@ syms_of_macterm ()
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 
-  DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
-    doc: /* Non-nil means that the command key is used as the Emacs meta key.
-Otherwise the option key is used.  */);
-  Vmac_command_key_is_meta = Qt;
+/* 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 `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 to use for the Mac alt/option key.  The value can
-be alt, hyper, or super for the respective modifier.  If the value is
-nil then the key will act as the normal Mac option modifier.  */);
+    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-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
-    doc: /* Non-nil means that the control and meta keys are reversed.  This is
-useful for non-standard keyboard layouts.  */);
-  Vmac_reverse_ctrl_meta = Qnil;
+  DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
+    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 `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;
+#if USE_CG_DRAWING
+  mac_use_core_graphics = 1;
+#else
+  mac_use_core_graphics = 0;
+#endif
 
   /* 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);
+
+#if USE_ATSUI
+  DEFVAR_LISP ("mac-atsu-font-table", &Vmac_atsu_font_table,
+    doc: /* Hash table of ATSU font IDs vs plist of attributes and values.
+Each font ID is represented as a four-byte string in native byte
+order.  */);
+  Vmac_atsu_font_table =
+    make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
+                    make_float (DEFAULT_REHASH_SIZE),
+                    make_float (DEFAULT_REHASH_THRESHOLD),
+                    Qnil, Qnil, Qnil);
+#endif
+#if USE_MAC_TSM
+  DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
+    doc: /* Overlay used to display Mac TSM active input area.  */);
+  Vmac_ts_active_input_overlay = Qnil;
+#endif
 }
 
 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b