(version): New variable, set by configure.
[bpt/emacs.git] / src / macterm.c
index 5fd80b7..e36fafa 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"
@@ -110,6 +108,10 @@ static Lisp_Object last_window;
    (Not yet supported.)  */
 int x_use_underline_position_properties;
 
+/* Non-zero means to draw the underline at the same place as the descent line.  */
+
+int x_underline_at_descent_line;
+
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
@@ -198,6 +200,8 @@ static int input_signal_count;
 
 extern Lisp_Object Vsystem_name;
 
+extern Lisp_Object Qeql;
+
 /* A mask of extra modifier bits to put into every keyboard char.  */
 
 extern EMACS_INT extra_keyboard_modifiers;
@@ -216,7 +220,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 *));
@@ -241,7 +244,8 @@ static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
 static void mac_focus_changed P_ ((int, struct mac_display_info *,
                                   struct frame *, struct input_event *));
 static void x_detect_focus_change P_ ((struct mac_display_info *,
-                                      EventRecord *, struct input_event *));
+                                      const EventRecord *,
+                                      struct input_event *));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
@@ -259,23 +263,90 @@ 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.  */
-extern void menubar_selection_callback (FRAME_PTR, int);
-
 #define GC_FORE_COLOR(gc)      (&(gc)->fore_color)
 #define GC_BACK_COLOR(gc)      (&(gc)->back_color)
 #define GC_FONT(gc)            ((gc)->xgcv.font)
-#define GC_CLIP_REGION(gc)     ((gc)->clip_region)
 #define FRAME_NORMAL_GC(f)     ((f)->output_data.mac->normal_gc)
+#define CG_SET_FILL_COLOR(context, color)                      \
+  CGContextSetRGBFillColor (context,                                   \
+                           RED_FROM_ULONG (color) / 255.0f,            \
+                           GREEN_FROM_ULONG (color) / 255.0f,          \
+                           BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
+#define CG_SET_STROKE_COLOR(context, color)            \
+  CGContextSetRGBStrokeColor (context,                                 \
+                             RED_FROM_ULONG (color) / 255.0f,          \
+                             GREEN_FROM_ULONG (color) / 255.0f,        \
+                             BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
+#if USE_CG_DRAWING
+#define FRAME_CG_CONTEXT(f)    ((f)->output_data.mac->cg_context)
+
+/* Fringe bitmaps.  */
+
+static int max_fringe_bmp = 0;
+static CGImageRef *fringe_bmp = 0;
+
+static CGContextRef
+mac_begin_cg_clip (f, gc)
+     struct frame *f;
+     GC gc;
+{
+  CGContextRef context = FRAME_CG_CONTEXT (f);
+
+  if (!context)
+    {
+      QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
+      FRAME_CG_CONTEXT (f) = context;
+    }
+
+  CGContextSaveGState (context);
+  CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
+  CGContextScaleCTM (context, 1, -1);
+  if (gc && gc->n_clip_rects)
+    CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+
+  return context;
+}
+
+static void
+mac_end_cg_clip (f)
+     struct frame *f;
+{
+  CGContextRestoreGState (FRAME_CG_CONTEXT (f));
+}
+
+void
+mac_prepare_for_quickdraw (f)
+     struct frame *f;
+{
+  if (f == NULL)
+    {
+      Lisp_Object rest, frame;
+      FOR_EACH_FRAME (rest, frame)
+       if (FRAME_MAC_P (XFRAME (frame)))
+         mac_prepare_for_quickdraw (XFRAME (frame));
+    }
+  else
+    {
+      CGContextRef context = FRAME_CG_CONTEXT (f);
+
+      if (context)
+       {
+         CGContextSynchronize (context);
+         QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
+                         &FRAME_CG_CONTEXT (f));
+       }
+    }
+}
+#endif
 
 static RgnHandle saved_port_clip_region = NULL;
 
 static void
-mac_begin_clip (region)
-     RgnHandle region;
+mac_begin_clip (gc)
+     GC gc;
 {
   static RgnHandle new_region = NULL;
 
@@ -284,19 +355,19 @@ mac_begin_clip (region)
   if (new_region == NULL)
     new_region = NewRgn ();
 
-  if (region)
+  if (gc->n_clip_rects)
     {
       GetClip (saved_port_clip_region);
-      SectRgn (saved_port_clip_region, region, new_region);
+      SectRgn (saved_port_clip_region, gc->clip_region, new_region);
       SetClip (new_region);
     }
 }
 
 static void
-mac_end_clip (region)
-     RgnHandle region;
+mac_end_clip (gc)
+     GC gc;
 {
-  if (region)
+  if (gc->n_clip_rects)
     SetClip (saved_port_clip_region);
 }
 
@@ -320,14 +391,48 @@ mac_draw_line (f, gc, x1, y1, x2, y2)
      GC gc;
      int x1, y1, x2, y2;
 {
+#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_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   MoveTo (x1, y1);
   LineTo (x2, y2);
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
+#endif
 }
 
 void
@@ -340,6 +445,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);
 
@@ -361,6 +481,14 @@ mac_erase_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
@@ -368,11 +496,12 @@ mac_erase_rectangle (f, gc, x, y, width, height)
   RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   EraseRect (&r);
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+#endif
 }
 
 
@@ -393,6 +522,16 @@ static void
 mac_clear_window (f)
      struct frame *f;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+  GC gc = FRAME_NORMAL_GC (f);
+
+  context = mac_begin_cg_clip (f, NULL);
+  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
+                                         FRAME_PIXEL_HEIGHT (f)));
+  mac_end_cg_clip (f);
+#else
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
@@ -407,11 +546,50 @@ mac_clear_window (f)
 #else /* not TARGET_API_MAC_CARBON */
   EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
 #endif /* not TARGET_API_MAC_CARBON */
+#endif
 }
 
 
 /* Mac replacement for XCopyArea.  */
 
+#if USE_CG_DRAWING
+static void
+mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
+                  dest_x, dest_y, overlay_p)
+     CGImageRef image;
+     struct frame *f;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y, overlay_p;
+{
+  CGContextRef context;
+  float port_height = FRAME_PIXEL_HEIGHT (f);
+  CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
+
+  context = mac_begin_cg_clip (f, gc);
+  if (!overlay_p)
+    {
+      CG_SET_FILL_COLOR (context, gc->xgcv.background);
+      CGContextFillRect (context, dest_rect);
+    }
+  CGContextClipToRect (context, dest_rect);
+  CGContextScaleCTM (context, 1, -1);
+  CGContextTranslateCTM (context, 0, -port_height);
+  if (CGImageIsMask (image))
+    CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextDrawImage (context,
+                     CGRectMake (dest_x - src_x,
+                                 port_height - (dest_y - src_y
+                                                + CGImageGetHeight (image)),
+                                 CGImageGetWidth (image),
+                                 CGImageGetHeight (image)),
+                     image);
+  mac_end_cg_clip (f);
+}
+
+#else  /* !USE_CG_DRAWING */
+
 static void
 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
      struct frame *f;
@@ -433,7 +611,7 @@ mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
   RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
 #if TARGET_API_MAC_CARBON
   {
     CGrafPtr port;
@@ -448,10 +626,11 @@ mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
   CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
            overlay_p ? srcOr : srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCreateBitmapFromBitmapData.  */
@@ -462,7 +641,7 @@ mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
      char *bits;
      int w, h;
 {
-  static unsigned char swap_nibble[16]
+  static const unsigned char swap_nibble[16]
     = { 0x0, 0x8, 0x4, 0xc,    /* 0000 1000 0100 1100 */
        0x2, 0xa, 0x6, 0xe,    /* 0010 1010 0110 1110 */
        0x1, 0x9, 0x5, 0xd,    /* 0001 1001 0101 1101 */
@@ -512,7 +691,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;
@@ -573,6 +760,14 @@ mac_fill_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
@@ -580,9 +775,10 @@ mac_fill_rectangle (f, gc, x, y, width, height)
   RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   PaintRect (&r); /* using foreground color of gc */
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
+#endif
 }
 
 
@@ -595,6 +791,15 @@ mac_draw_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CGContextStrokeRect (context,
+                      CGRectMake (x + 0.5f, y + 0.5f, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
@@ -602,9 +807,10 @@ mac_draw_rectangle (f, gc, x, y, width, height)
   RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width + 1, y + height + 1);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   FrameRect (&r); /* using foreground color of gc */
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
+#endif
 }
 
 
@@ -621,17 +827,18 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
 
   if (saved_text_layout == NULL)
     {
-      UniCharCount lengths[] = {kATSUToTextEnd};
-      ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
-      ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
+      static const UniCharCount lengths[] = {kATSUToTextEnd};
+      static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
+      static const 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};
+      static const ATSUAttributeValuePtr values[] = {&line_layout};
 
       err = ATSUCreateTextLayoutWithTextPtr (text,
                                             kATSUFromTextBeginning,
@@ -673,6 +880,9 @@ mac_invert_rectangle (f, x, y, width, height)
 {
   Rect r;
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   SetRect (&r, x, y, x + width, y + height);
@@ -682,31 +892,20 @@ mac_invert_rectangle (f, x, y, width, height)
 
 
 static void
-mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char)
+mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
+                       overstrike_p, bytes_per_char)
      struct frame *f;
      GC gc;
      int x, y;
      char *buf;
-     int nchars, mode, bytes_per_char;
+     int nchars, bg_width, overstrike_p, bytes_per_char;
 {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-  UInt32 textFlags, savedFlags;
-  if (mac_use_core_graphics) {
-    textFlags = kQDUseCGTextRendering;
-    savedFlags = SwapQDTextFlags(textFlags);
-  }
-#endif
-
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  RGBForeColor (GC_FORE_COLOR (gc));
-  if (mode != srcOr)
-    RGBBackColor (GC_BACK_COLOR (gc));
-
 #if USE_ATSUI
   if (GC_FONT (gc)->mac_style)
     {
-      OSErr err;
+      OSStatus err;
       ATSUTextLayout text_layout;
 
       xassert (bytes_per_char == 2);
@@ -724,173 +923,384 @@ mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char)
                                                nchars,
                                                GC_FONT (gc)->mac_style,
                                                &text_layout);
-      if (err == noErr)
-       {
+      if (err != noErr)
+       return;
 #ifdef MAC_OSX
-         if (!mac_use_core_graphics)
-           {
+      if (!mac_use_core_graphics)
+       {
+#endif
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
 #endif
-             mac_begin_clip (GC_CLIP_REGION (gc));
-             MoveTo (x, y);
+         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);
+         if (overstrike_p)
+           {
+             MoveTo (x + 1, y);
              ATSUDrawText (text_layout,
                            kATSUFromTextBeginning, kATSUToTextEnd,
                            kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
-             mac_end_clip (GC_CLIP_REGION (gc));
-#ifdef MAC_OSX
            }
-         else
+         mac_end_clip (gc);
+#ifdef MAC_OSX
+       }
+      else
+       {
+         CGrafPtr port;
+         static CGContextRef context;
+         float port_height = FRAME_PIXEL_HEIGHT (f);
+         static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
+         static const ByteCount sizes[] = {sizeof (CGContextRef)};
+         static const ATSUAttributeValuePtr values[] = {&context};
+
+#if USE_CG_DRAWING
+         context = mac_begin_cg_clip (f, gc);
+#else
+         GetPort (&port);
+         QDBeginCGContext (port, &context);
+         if (gc->n_clip_rects || bg_width)
            {
-             CGrafPtr port;
-             CGContextRef context;
-             float port_height = FRAME_PIXEL_HEIGHT (f);
-             ATSUAttributeTag tags[] = {kATSUCGContextTag};
-             ByteCount sizes[] = {sizeof (CGContextRef)};
-             ATSUAttributeValuePtr values[] = {&context};
-
-             GetPort (&port);
-             QDBeginCGContext (port, &context);
+             CGContextTranslateCTM (context, 0, port_height);
+             CGContextScaleCTM (context, 1, -1);
              if (gc->n_clip_rects)
+               CGContextClipToRects (context, gc->clip_rects,
+                                     gc->n_clip_rects);
+#endif
+             if (bg_width)
                {
-                 CGContextTranslateCTM (context, 0, port_height);
-                 CGContextScaleCTM (context, 1, -1);
-                 CGContextClipToRects (context, gc->clip_rects,
-                                       gc->n_clip_rects);
-                 CGContextScaleCTM (context, 1, -1);
-                 CGContextTranslateCTM (context, 0, -port_height);
+                 CG_SET_FILL_COLOR (context, gc->xgcv.background);
+                 CGContextFillRect
+                   (context,
+                    CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
+                                bg_width, FONT_HEIGHT (GC_FONT (gc))));
                }
-             CGContextSetRGBFillColor
-               (context,
-                RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                1.0);
-             err = ATSUSetLayoutControls (text_layout,
-                                          sizeof (tags) / sizeof (tags[0]),
-                                          tags, sizes, values);
-             if (err == noErr)
+             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 (overstrike_p)
                ATSUDrawText (text_layout,
                              kATSUFromTextBeginning, kATSUToTextEnd,
-                             Long2Fix (x), Long2Fix (port_height - y));
-             CGContextSynchronize (context);
-             QDEndCGContext (port, &context);
-#if 0
-             /* This doesn't work on Mac OS X 10.1.  */
-             ATSUClearLayoutControls (text_layout,
-                                      sizeof (tags) / sizeof (tags[0]),
-                                      tags);
+                             Long2Fix (x + 1), Long2Fix (port_height - y));
+           }
+#if USE_CG_DRAWING
+         mac_end_cg_clip (f);
+         context = NULL;
 #else
-             ATSUSetLayoutControls (text_layout,
-                                    sizeof (tags) / sizeof (tags[0]),
-                                    tags, sizes, values);
+         CGContextSynchronize (context);
+         QDEndCGContext (port, &context);
 #endif
-           }
+#if 0
+         /* This doesn't work on Mac OS X 10.1.  */
+         ATSUClearLayoutControls (text_layout,
+                                  sizeof (tags) / sizeof (tags[0]), tags);
+#else
+         ATSUSetLayoutControls (text_layout,
+                                sizeof (tags) / sizeof (tags[0]),
+                                tags, sizes, values);
 #endif
        }
+#endif /* MAC_OSX */
     }
   else
+#endif /* USE_ATSUI */
     {
-#endif
-  TextFont (GC_FONT (gc)->mac_fontnum);
-  TextSize (GC_FONT (gc)->mac_fontsize);
-  TextFace (GC_FONT (gc)->mac_fontface);
-  TextMode (mode);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+      UInt32 savedFlags;
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
-  MoveTo (x, y);
-  DrawText (buf, 0, nchars * bytes_per_char);
-  mac_end_clip (GC_CLIP_REGION (gc));
-#if USE_ATSUI
-    }
+      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;
+
+         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 (overstrike_p)
+       {
+         TextMode (srcOr);
+         MoveTo (x + 1, y);
+         DrawText (buf, 0, nchars * bytes_per_char);
+       }
+      if (bg_width)
+       RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+      mac_end_clip (gc);
 
-  if (mode != srcOr)
-    RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-  if (mac_use_core_graphics)
-    SwapQDTextFlags(savedFlags);
+      if (mac_use_core_graphics)
+       SwapQDTextFlags(savedFlags);
 #endif
+    }
 }
 
 
-/* Mac replacement for XDrawString.  */
+/* Mac replacement for XDrawImageString.  */
 
 static void
-mac_draw_string (f, gc, x, y, buf, nchars)
+mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
      struct frame *f;
      GC gc;
      int x, y;
      char *buf;
-     int nchars;
+     int nchars, bg_width, overstrike_p;
 {
-  mac_draw_string_common (f, gc, x, y, buf, nchars, srcOr, 1);
+  mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
+                         overstrike_p, 1);
 }
 
 
-/* Mac replacement for XDrawString16. */
+/* Mac replacement for XDrawImageString16.  */
 
 static void
-mac_draw_string_16 (f, gc, x, y, buf, nchars)
+mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
      struct frame *f;
      GC gc;
      int x, y;
      XChar2b *buf;
-     int nchars;
+     int nchars, bg_width, overstrike_p;
 {
-  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcOr, 2);
+  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
+                         overstrike_p, 2);
 }
 
 
-/* Mac replacement for XDrawImageString.  */
+/* 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 void
-mac_draw_image_string (f, gc, x, y, buf, nchars)
-     struct frame *f;
-     GC gc;
-     int x, y;
-     char *buf;
-     int nchars;
+static OSStatus
+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
 {
-  mac_draw_string_common (f, gc, x, y, buf, nchars, srcCopy, 1);
+  OSStatus 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)
+           {
+             OSStatus 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
+                 /* Make sure that we don't have to make layout
+                    adjustments.  */
+                 && glyph_info_array.glyphs[0].deltaY == 0.0f
+                 && glyph_info_array.glyphs[0].idealX == 0.0f
+                 && glyph_info_array.glyphs[0].screenX == 0)
+               {
+                 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 XDrawString16.  */
+/* Mac replacement for XTextExtents16.  Only sets horizontal metrics.  */
 
-static void
-mac_draw_image_string_16 (f, gc, x, y, buf, nchars)
-     struct frame *f;
-     GC gc;
-     int x, y;
-     XChar2b *buf;
+static int
+mac_text_extents_16 (font_struct, string, nchars, overall_return)
+     XFontStruct *font_struct;
+     XChar2b *string;
      int nchars;
+     XCharStruct *overall_return;
 {
-  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcCopy, 2);
+  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 XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
-
 static int cg_text_anti_aliasing_threshold = 8;
 
 static void
 init_cg_text_anti_aliasing_threshold ()
 {
-  Lisp_Object val =
-    Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"),
-                        Qnil, Qnil, Qnil);
+  int threshold;
+  Boolean valid_p;
 
-  if (INTEGERP (val))
-    cg_text_anti_aliasing_threshold = XINT (val);
+  threshold =
+    CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
+                                    kCFPreferencesCurrentApplication,
+                                    &valid_p);
+  if (valid_p)
+    cg_text_anti_aliasing_threshold = threshold;
 }
 
 static int
-mac_draw_string_cg (f, gc, x, y, buf, nchars)
+mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
      struct frame *f;
      GC gc;
      int x, y;
      XChar2b *buf;
-     int nchars;
+     int nchars, bg_width, overstrike_p;
 {
   CGrafPtr port;
   float port_height, gx, gy;
@@ -907,53 +1317,89 @@ mac_draw_string_cg (f, gc, x, y, buf, nchars)
   gx = x;
   gy = port_height - y;
   glyphs = (CGGlyph *)buf;
-  advances = xmalloc (sizeof (CGSize) * nchars);
+  advances = alloca (sizeof (CGSize) * nchars);
+  if (advances == NULL)
+    return 0;
   for (i = 0; i < nchars; i++)
     {
-      advances[i].width = x_per_char_metric (GC_FONT (gc), buf)->width;
+      XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
+
+      advances[i].width = pcm->width;
       advances[i].height = 0;
       glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
       buf++;
     }
 
+#if USE_CG_DRAWING
+  context = mac_begin_cg_clip (f, gc);
+#else
   QDBeginCGContext (port, &context);
-  if (gc->n_clip_rects)
+  if (gc->n_clip_rects || bg_width)
     {
       CGContextTranslateCTM (context, 0, port_height);
       CGContextScaleCTM (context, 1, -1);
-      CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+      if (gc->n_clip_rects)
+       CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+#endif
+      if (bg_width)
+       {
+         CG_SET_FILL_COLOR (context, gc->xgcv.background);
+         CGContextFillRect
+           (context,
+            CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
+                        bg_width, FONT_HEIGHT (GC_FONT (gc))));
+       }
       CGContextScaleCTM (context, 1, -1);
       CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
     }
-  CGContextSetRGBFillColor (context,
-                           RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                           GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                           BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
-                           1.0);
+#endif
+  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
   CGContextSetFont (context, GC_FONT (gc)->cg_font);
   CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
   if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
     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++)
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGContextShowGlyphsWithAdvances != NULL)
+#endif
+    {
+      CGContextSetTextPosition (context, gx, gy);
+      CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
+      if (overstrike_p)
+       {
+         CGContextSetTextPosition (context, gx + 1.0f, gy);
+         CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
+       }
+    }
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  else
+#endif
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030  */
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
     {
-      CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
-      gx += advances[i].width;
+      for (i = 0; i < nchars; i++)
+       {
+         CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
+         if (overstrike_p)
+           CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
+         gx += advances[i].width;
+       }
     }
 #endif
+#if USE_CG_DRAWING
+  mac_end_cg_clip (f);
+#else
   CGContextSynchronize (context);
   QDEndCGContext (port, &context);
-
-  xfree (advances);
+#endif
 
   return 1;
 }
 #endif
 
 
+#if !USE_CG_DRAWING
 /* Mac replacement for XCopyArea: dest must be window.  */
 
 static void
@@ -975,7 +1421,7 @@ mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
   ForeColor (blackColor);
   BackColor (whiteColor);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
 #if TARGET_API_MAC_CARBON
   {
@@ -993,7 +1439,7 @@ mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
            &src_r, &dest_r, srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (src));
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
@@ -1019,7 +1465,7 @@ mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
   ForeColor (blackColor);
   BackColor (whiteColor);
 
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
   LockPixels (GetGWorldPixMap (mask));
 #if TARGET_API_MAC_CARBON
@@ -1039,10 +1485,11 @@ mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (mask));
   UnlockPixels (GetGWorldPixMap (src));
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCopyArea: used only for scrolling.  */
@@ -1060,6 +1507,9 @@ mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
   RgnHandle dummy = NewRgn (); /* For avoiding update events.  */
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   ScrollWindowRect (FRAME_MAC_WINDOW (f),
                    &src_r, dest_x - src_x, dest_y - src_y,
                    kScrollWindowNoOptions, dummy);
@@ -1077,9 +1527,9 @@ mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
      color mapping in CopyBits.  Otherwise, it will be slow.  */
   ForeColor (blackColor);
   BackColor (whiteColor);
-  mac_begin_clip (GC_CLIP_REGION (gc));
+  mac_begin_clip (gc);
   CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
-  mac_end_clip (GC_CLIP_REGION (gc));
+  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 #endif /* not TARGET_API_MAC_CARBON */
@@ -1115,11 +1565,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;
 }
@@ -1215,17 +1662,10 @@ mac_set_clip_rectangles (display, gc, rectangles, n)
 {
   int i;
 
-  if (n < 0 || n > MAX_CLIP_RECTS)
-    abort ();
-  if (n == 0)
-    {
-      if (gc->clip_region)
-       {
-         DisposeRgn (gc->clip_region);
-         gc->clip_region = NULL;
-       }
-    }
-  else
+  xassert (n >= 0 && n <= MAX_CLIP_RECTS);
+
+  gc->n_clip_rects = n;
+  if (n > 0)
     {
       if (gc->clip_region == NULL)
        gc->clip_region = NewRgn ();
@@ -1242,9 +1682,7 @@ mac_set_clip_rectangles (display, gc, rectangles, n)
          DisposeRgn (region);
        }
     }
-#if defined (MAC_OSX) && USE_ATSUI
-  gc->n_clip_rects = n;
-
+#if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
   for (i = 0; i < n; i++)
     {
       Rect *rect = rectangles + i;
@@ -1264,7 +1702,7 @@ mac_reset_clip_rectangles (display, gc)
      Display *display;
      GC gc;
 {
-  mac_set_clip_rectangles (display, gc, NULL, 0);
+  gc->n_clip_rects = 0;
 }
 
 
@@ -1311,14 +1749,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
@@ -1327,6 +1757,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
@@ -1657,9 +2090,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);
@@ -1668,14 +2104,63 @@ x_draw_fringe_bitmap (w, row, p)
                       ? (p->overlay_p ? face->background
                          : f->output_data.mac->cursor_pixel)
                       : face->foreground));
+#if USE_CG_DRAWING
+      mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
+                        p->wd, p->h, p->x, p->y, p->overlay_p);
+#else
       mac_draw_bitmap (f, face->gc, p->x, p->y,
-                      p->wd, p->h, bits, p->overlay_p);
+                      p->wd, p->h, p->bits + p->dh, p->overlay_p);
+#endif
       XSetForeground (display, face->gc, gcv.foreground);
     }
 
   mac_reset_clip_rectangles (display, face->gc);
 }
 
+#if USE_CG_DRAWING
+static void
+mac_define_fringe_bitmap (which, bits, h, wd)
+     int which;
+     unsigned short *bits;
+     int h, wd;
+{
+  int i;
+  CGDataProviderRef provider;
+
+  if (which >= max_fringe_bmp)
+    {
+      i = max_fringe_bmp;
+      max_fringe_bmp = which + 20;
+      fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
+      while (i < max_fringe_bmp)
+       fringe_bmp[i++] = 0;
+    }
+
+  for (i = 0; i < h; i++)
+    bits[i] = ~bits[i];
+  provider = CGDataProviderCreateWithData (NULL, bits,
+                                          sizeof (unsigned short) * h, NULL);
+  if (provider)
+    {
+      fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
+                                            sizeof (unsigned short),
+                                            provider, NULL, 0);
+      CGDataProviderRelease (provider);
+    }
+}
+
+static void
+mac_destroy_fringe_bitmap (which)
+     int which;
+{
+  if (which >= max_fringe_bmp)
+    return;
+
+  if (fringe_bmp[which])
+    CGImageRelease (fringe_bmp[which]);
+  fringe_bmp[which] = 0;
+}
+#endif
 \f
 
 /* This is called when starting Emacs and when restarting after
@@ -1708,6 +2193,29 @@ static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
 
 
+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)
+     const 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.  */
 
@@ -1724,63 +2232,27 @@ x_per_char_metric (font, char2b)
 #if USE_ATSUI
   if (font->mac_style)
     {
-      if (char2b->byte1 >= font->min_byte1
-         && char2b->byte1 <= font->max_byte1
-         && char2b->byte2 >= font->min_char_or_byte2
-         && char2b->byte2 <= font->max_char_or_byte2)
+      XCharStruct **row = font->bounds.rows + char2b->byte1;
+
+      if (*row == NULL)
        {
-         pcm = (font->per_char
-                + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
-                   * (char2b->byte1 - font->min_byte1))
-                + (char2b->byte2 - font->min_char_or_byte2));
+         *row = xmalloc (sizeof (XCharStruct) * 0x100);
+         pcm_init (*row, 0x100);
        }
-
-      if (pcm && !pcm->valid_p)
+      pcm = *row + char2b->byte2;
+      if (pcm_get_status (pcm) != PCM_VALID)
        {
-         OSErr err;
-         ATSUTextLayout text_layout;
-         UniChar c;
-         int char_width;
-         ATSTrapezoid glyph_bounds;
-         Rect char_bounds;
-
-         c = (char2b->byte1 << 8) + char2b->byte2;
          BLOCK_INPUT;
-         err = atsu_get_text_layout_with_text_ptr (&c, 1,
-                                                   font->mac_style,
-                                                   &text_layout);
-         if (err == noErr)
-           err = ATSUMeasureTextImage (text_layout,
-                                       kATSUFromTextBeginning, kATSUToTextEnd,
-                                       0, 0, &char_bounds);
-
-         if (err == noErr)
-           err = ATSUGetGlyphBounds (text_layout, 0, 0,
-                                     kATSUFromTextBeginning, kATSUToTextEnd,
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-                                     kATSUseFractionalOrigins,
-#else
-                                     kATSUseDeviceOrigins,
-#endif
-                                     1, &glyph_bounds, NULL);
+         mac_query_char_extents (font->mac_style,
+                                 (char2b->byte1 << 8) + char2b->byte2,
+                                 NULL, NULL, pcm, NULL);
          UNBLOCK_INPUT;
-         if (err != noErr)
-           pcm = NULL;
-         else
-           {
-             xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
-                      == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
-
-             char_width = Fix2Long (glyph_bounds.upperRight.x
-                                    - glyph_bounds.upperLeft.x);
-             STORE_XCHARSTRUCT (*pcm, char_width, char_bounds);
-           }
        }
     }
   else
     {
 #endif
-  if (font->per_char != NULL)
+  if (font->bounds.per_char != NULL)
     {
       if (font->min_byte1 == 0 && font->max_byte1 == 0)
        {
@@ -1793,7 +2265,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
        {
@@ -1815,7 +2288,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));
@@ -1836,7 +2309,11 @@ x_per_char_metric (font, char2b)
 #endif
 
   return ((pcm == NULL
-          || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
+          || (pcm->width == 0
+#if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics.  */
+              && (pcm->rbearing - pcm->lbearing) == 0
+#endif
+              ))
          ? NULL : pcm);
 }
 
@@ -1954,7 +2431,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,
@@ -2155,65 +2631,37 @@ 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;
 
-#if USE_ATSUI
-      if (font->mac_style)
-       {
-         OSErr err;
-         ATSUTextLayout text_layout;
-         UniChar *buf;
-         int i;
-
-         SetRect (&r, 0, 0, 0, 0);
-         buf = xmalloc (sizeof (UniChar) * s->nchars);
-         if (buf)
-           {
-             for (i = 0; i < s->nchars; i++)
-               buf[i] = (s->char2b[i].byte1 << 8) + s->char2b[i].byte2;
-
-             err = atsu_get_text_layout_with_text_ptr (buf, s->nchars,
-                                                       font->mac_style,
-                                                       &text_layout);
-             if (err == noErr)
-               err = ATSUMeasureTextImage (text_layout,
-                                           kATSUFromTextBeginning,
-                                           kATSUToTextEnd,
-                                           0, 0, &r);
-             xfree (buf);
-           }
-       }
-      else
-       {
+#if USE_CG_DRAWING
+      mac_prepare_for_quickdraw (s->f);
 #endif
+      SetPortWindowPort (FRAME_MAC_WINDOW (s->f));
+
       TextFont (font->mac_fontnum);
       TextSize (font->mac_fontsize);
       TextFace (font->mac_fontface);
 
-      if (s->two_byte_p)
-       QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
-      else
-       {
-         int i;
-         char *buf = xmalloc (s->nchars);
-
-         if (buf == NULL)
-           SetRect (&r, 0, 0, 0, 0);
-         else
-           {
-             for (i = 0; i < s->nchars; ++i)
-               buf[i] = s->char2b[i].byte2;
-             QDTextBounds (s->nchars, buf, &r);
-             xfree (buf);
-           }
-       }
-#if USE_ATSUI
-        }
-#endif
+      QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
 
       s->right_overhang = r.right > s->width ? r.right - s->width : 0;
       s->left_overhang = r.left < 0 ? -r.left : 0;
@@ -2232,14 +2680,6 @@ x_clear_glyph_string_rect (s, x, y, w, h)
 }
 
 
-/* We prefer not to use XDrawImageString (srcCopy text transfer mode)
-   on Mac OS X because:
-   - Screen is double-buffered.  (In srcCopy mode, a text is drawn
-     into an offscreen graphics world first.  So performance gain
-     cannot be expected.)
-   - It lowers rendering quality.
-   - Some fonts leave garbage on cursor movement.  */
-
 /* Draw the background of glyph_string S.  If S->background_filled_p
    is non-zero don't draw it.  FORCE_P non-zero means draw the
    background even if it wouldn't be drawn normally.  This is used
@@ -2271,12 +2711,10 @@ x_draw_glyph_string_background (s, force_p)
        }
       else
 #endif
-#if defined (MAC_OS8) && !USE_ATSUI
         if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
               || force_p)
-#endif
        {
          x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
                                     s->background_width,
@@ -2293,7 +2731,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.  */
@@ -2332,7 +2770,6 @@ x_draw_glyph_string_foreground (s)
        for (i = 0; i < s->nchars; ++i)
          char1b[i] = s->char2b[i].byte2;
 
-#if defined (MAC_OS8) && !USE_ATSUI
       /* Draw text with XDrawString if background has already been
         filled.  Otherwise, use XDrawImageString.  (Note that
         XDrawImageString is usually faster than XDrawString.)  Always
@@ -2340,38 +2777,30 @@ x_draw_glyph_string_foreground (s)
         no chance that characters under a box cursor are invisible.  */
       if (s->for_overlaps
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
-#endif
-       {
-         /* Draw characters with 16-bit or 8-bit functions.  */
-         if (s->two_byte_p
+       bg_width = 0;           /* Corresponds to XDrawString.  */
+      else
+       bg_width = s->background_width; /* Corresponds to XDrawImageString.  */
+
+      if (s->two_byte_p
 #if USE_ATSUI
-             || GC_FONT (s->gc)->mac_style
+         || GC_FONT (s->gc)->mac_style
 #endif
-             )
+         )
 #if USE_CG_TEXT_DRAWING
-           if (!s->two_byte_p
-               && mac_draw_string_cg (s->f, s->gc, x, s->ybase - boff,
-                                      s->char2b, s->nchars))
-             ;
-           else
+       if (!s->two_byte_p
+           && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
+                                        s->char2b, s->nchars, bg_width,
+                                        s->face->overstrike))
+         ;
+       else
 #endif
-           mac_draw_string_16 (s->f, s->gc, x, s->ybase - boff,
-                               s->char2b, s->nchars);
-         else
-           mac_draw_string (s->f, s->gc, x, s->ybase - boff,
-                            char1b, s->nchars);
-       }
-#if defined (MAC_OS8) && !USE_ATSUI
+         mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
+                                   s->char2b, s->nchars, bg_width,
+                                   s->face->overstrike);
       else
-       {
-         if (s->two_byte_p)
-           mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
-                                     s->char2b, s->nchars);
-         else
-           mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
-                                  char1b, s->nchars);
-       }
-#endif
+       mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
+                              char1b, s->nchars, bg_width,
+                              s->face->overstrike);
     }
 }
 
@@ -2407,10 +2836,10 @@ x_draw_composite_glyph_string_foreground (s)
   else
     {
       for (i = 0; i < s->nchars; i++, ++s->gidx)
-       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);
+       mac_draw_image_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, 0, s->face->overstrike);
     }
 }
 
@@ -2780,13 +3209,13 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
     for (i = 0; i < width; ++i)
       mac_draw_line (f, gc,
                     left_x + i * left_p, top_y + i,
-                    right_x - i * right_p, top_y + i);
+                    right_x + 1 - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
       mac_draw_line (f, gc,
-                    left_x + i, top_y + i, left_x + i, bottom_y - i);
+                    left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
 
   mac_reset_clip_rectangles (dpy, gc);
   if (raised_p)
@@ -2800,13 +3229,13 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
     for (i = 0; i < width; ++i)
       mac_draw_line (f, gc,
                     left_x + i * left_p, bottom_y - i,
-                    right_x - i * right_p, bottom_y - i);
+                    right_x + 1 - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
       mac_draw_line (f, gc,
-                    right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
+                    right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
 
   mac_reset_clip_rectangles (dpy, gc);
 }
@@ -2934,15 +3363,26 @@ x_draw_image_foreground (s)
     {
       x_set_glyph_string_clipping (s);
 
+#if USE_CG_DRAWING
+      mac_draw_cg_image (s->img->data.ptr_val,
+                        s->f, s->gc, s->slice.x, s->slice.y,
+                        s->slice.width, s->slice.height, x, y, 1);
+#endif
       if (s->img->mask)
+#if !USE_CG_DRAWING
        mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
                                 s->f, s->gc, s->slice.x, s->slice.y,
                                 s->slice.width, s->slice.height, x, y);
+#else
+       ;
+#endif
       else
        {
+#if !USE_CG_DRAWING
          mac_copy_area (s->img->pixmap,
                         s->f, s->gc, s->slice.x, s->slice.y,
                         s->slice.width, s->slice.height, x, y);
+#endif
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -3064,7 +3504,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;
 
@@ -3119,19 +3558,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))
            {
@@ -3158,8 +3606,20 @@ x_draw_stretch_glyph_string (s)
        }
     }
   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);
+
+      /* Don't draw into left margin, fringe or scrollbar area
+         except for header line and mode line.  */
+      if (x < left_x && !s->row->mode_line_p)
+       {
+         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;
 }
@@ -3241,19 +3701,46 @@ x_draw_glyph_string (s)
       /* Draw underline.  */
       if (s->face->underline_p)
        {
-          unsigned long h = 1;
-          unsigned long dy = s->height - h;
+         unsigned long tem, h;
+         int y;
+
+#if 0
+         /* Get the underline thickness.  Default is 1 pixel.  */
+         if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
+#endif
+           h = 1;
+
+         y = s->y + s->height - h;
+         if (!x_underline_at_descent_line)
+            {
+             /* Get the underline position.  This is the recommended
+                 vertical offset in pixels from the baseline to the top of
+                 the underline.  This is a signed value according to the
+                 specs, and its default is
+
+                ROUND ((maximum descent) / 2), with
+                ROUND(x) = floor (x + 0.5)  */
+
+#if 0
+              if (x_use_underline_position_properties
+                  && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+                y = s->ybase + (long) tem;
+              else
+#endif
+             if (s->face->font)
+                y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+            }
 
          if (s->face->underline_defaulted_p)
-           mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
-                               s->width, h);
+           mac_fill_rectangle (s->f, s->gc, s->x, y,
+                               s->background_width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->underline_color);
-             mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
-                                 s->width, h);
+             mac_fill_rectangle (s->f, s->gc, s->x, y,
+                                 s->background_width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3265,14 +3752,14 @@ x_draw_glyph_string (s)
 
          if (s->face->overline_color_defaulted_p)
            mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
-                               s->width, h);
+                               s->background_width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->overline_color);
              mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
-                                 s->width, h);
+                                 s->background_width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3687,6 +4174,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);
@@ -3739,7 +4231,7 @@ mac_focus_changed (type, dpyinfo, frame, bufp)
 static void
 x_detect_focus_change (dpyinfo, event, bufp)
      struct mac_display_info *dpyinfo;
-     EventRecord *event;
+     const EventRecord *event;
      struct input_event *bufp;
 {
   struct frame *frame;
@@ -3810,142 +4302,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 *
@@ -4152,8 +4508,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 *));
@@ -4180,35 +4536,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
@@ -4274,7 +4606,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;
@@ -4416,10 +4748,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
     {
@@ -4430,10 +4764,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;
 }
@@ -4469,8 +4812,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,
@@ -4590,6 +4941,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));
 
@@ -4640,6 +4994,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;
@@ -4653,6 +5008,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
   if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
     sb_left++;
+#endif
 
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
@@ -4684,12 +5040,17 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
             for them on the frame, we have to clear "under" them.  */
          mac_clear_area (f, left, top, width, height);
 
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
+#endif
           HideControl (ch);
           MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
           SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                       disp_height);
+#ifndef USE_TOOLKIT_SCROLL_BARS
          if (sb_width < disp_height)
            ShowControl (ch);
+#endif
 
           /* Remember new settings.  */
           XSETINT (bar->left, sb_left);
@@ -4708,29 +5069,42 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 #ifdef USE_TOOLKIT_SCROLL_BARS
   if (NILP (bar->track_top))
     {
-      ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
-      Rect r0, r1;
+      if (sb_width >= disp_height)
+       {
+         XSETINT (bar->track_top, 0);
+         XSETINT (bar->track_height, 0);
+       }
+      else
+       {
+         ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+         Rect r0, r1;
 
-      BLOCK_INPUT;
+         BLOCK_INPUT;
 
-      SetControl32BitMinimum (ch, 0);
-      SetControl32BitMaximum (ch, 1);
-      SetControlViewSize (ch, 1);
+         SetControl32BitMinimum (ch, 0);
+         SetControl32BitMaximum (ch, 1);
+         SetControlViewSize (ch, 1);
 
-      /* Move the scroll bar thumb to the top.  */
-      SetControl32BitValue (ch, 0);
-      get_control_part_bounds (ch, kControlIndicatorPart, &r0);
+         /* Move the scroll bar thumb to the top.  */
+         SetControl32BitValue (ch, 0);
+         get_control_part_bounds (ch, kControlIndicatorPart, &r0);
 
-      /* Move the scroll bar thumb to the bottom.  */
-      SetControl32BitValue (ch, 1);
-      get_control_part_bounds (ch, kControlIndicatorPart, &r1);
+         /* Move the scroll bar thumb to the bottom.  */
+         SetControl32BitValue (ch, 1);
+         get_control_part_bounds (ch, kControlIndicatorPart, &r1);
 
-      UnionRect (&r0, &r1, &r0);
-      XSETINT (bar->track_top, r0.top);
-      XSETINT (bar->track_height, r0.bottom - r0.top);
+         UnionRect (&r0, &r1, &r0);
+         XSETINT (bar->track_top, r0.top);
+         XSETINT (bar->track_height, r0.bottom - r0.top);
 
-      UNBLOCK_INPUT;
-    }
+         /* Don't show the scroll bar if its height is not enough to
+            display the scroll bar thumb.  */
+         if (r0.bottom - r0.top > 0)
+           ShowControl (ch);
+
+         UNBLOCK_INPUT;
+       }
+    }
 
   x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
 #else /* not USE_TOOLKIT_SCROLL_BARS */
@@ -4870,7 +5244,7 @@ static void
 x_scroll_bar_handle_click (bar, part_code, er, bufp)
      struct scroll_bar *bar;
      ControlPartCode part_code;
-     EventRecord *er;
+     const EventRecord *er;
      struct input_event *bufp;
 {
   int win_y, top_range;
@@ -5099,8 +5473,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
@@ -5115,7 +5488,7 @@ x_draw_hollow_cursor (w, row)
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
   x_clip_to_row (w, row, TEXT_AREA, gc);
-  mac_draw_rectangle (f, gc, x, y, wd, h);
+  mac_draw_rectangle (f, gc, x, y, wd, h - 1);
   mac_reset_clip_rectangles (dpy, gc);
 }
 
@@ -5212,7 +5585,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);
 }
 
 
@@ -5483,6 +5859,57 @@ mac_get_window_bounds (f, inner, outer)
 #endif /* not TARGET_API_MAC_CARBON */
 }
 
+static void
+mac_handle_origin_change (f)
+     struct frame *f;
+{
+  x_real_positions (f, &f->left_pos, &f->top_pos);
+}
+
+static void
+mac_handle_size_change (f, pixelwidth, pixelheight)
+     struct frame *f;
+     int pixelwidth, pixelheight;
+{
+  int cols, rows;
+
+  cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
+  rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
+
+  if (cols != FRAME_COLS (f)
+      || rows != FRAME_LINES (f)
+      || pixelwidth != FRAME_PIXEL_WIDTH (f)
+      || pixelheight != FRAME_PIXEL_HEIGHT (f))
+    {
+      /* We pass 1 for DELAY since we can't run Lisp code inside of
+        a BLOCK_INPUT.  */
+      change_frame_size (f, rows, cols, 0, 1, 0);
+      FRAME_PIXEL_WIDTH (f) = pixelwidth;
+      FRAME_PIXEL_HEIGHT (f) = pixelheight;
+      SET_FRAME_GARBAGED (f);
+
+      /* If cursor was outside the new size, mark it as off.  */
+      mark_window_cursors_off (XWINDOW (f->root_window));
+
+      /* Clear out any recollection of where the mouse highlighting
+        was, since it might be in a place that's outside the new
+        frame size.  Actually checking whether it is outside is a
+        pain in the neck, so don't try--just let the highlighting be
+        done afresh with new size.  */
+      cancel_mouse_face (f);
+
+#if TARGET_API_MAC_CARBON
+      if (f->output_data.mac->hourglass_control)
+       {
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
+#endif
+         MoveControl (f->output_data.mac->hourglass_control,
+                      pixelwidth - HOURGLASS_WIDTH, 0);
+       }
+#endif
+    }
+}
 
 \f
 /* Calculate the absolute position in frame F
@@ -5563,7 +5990,10 @@ x_set_offset (f, xoff, yoff, change_gravity)
   ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
                           kWindowConstrainMoveRegardlessOfFit
                           | kWindowConstrainAllowPartial, NULL, NULL);
-  x_real_positions (f, &f->left_pos, &f->top_pos);
+#if USE_CARBON_EVENTS
+  if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
+#endif
+    mac_handle_origin_change (f);
 #else
   {
     Rect inner, outer, screen_rect, dummy;
@@ -5637,45 +6067,11 @@ x_set_window_size (f, change_gravity, cols, rows)
   x_wm_set_size_hint (f, (long) 0, 0);
 
   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);
-#endif
-
-  /* Now, strictly speaking, we can't be sure that this is accurate,
-     but the window manager will get around to dealing with the size
-     change request eventually, and we'll hear how it went when the
-     ConfigureNotify event gets here.
-
-     We could just not bother storing any of this information here,
-     and let the ConfigureNotify event set everything up, but that
-     might be kind of confusing to the Lisp code, since size changes
-     wouldn't be reported in the frame parameters until some random
-     point in the future when the ConfigureNotify event arrives.
-
-     We pass 1 for DELAY since we can't run Lisp code inside of
-     a BLOCK_INPUT.  */
-  change_frame_size (f, rows, cols, 0, 1, 0);
-  FRAME_PIXEL_WIDTH (f) = pixelwidth;
-  FRAME_PIXEL_HEIGHT (f) = pixelheight;
 
-  /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
-     receive in the ConfigureNotify event; if we get what we asked
-     for, then the event won't cause the screen to become garbaged, so
-     we have to make sure to do it here.  */
-  SET_FRAME_GARBAGED (f);
-
-  XFlush (FRAME_X_DISPLAY (f));
-
-  /* If cursor was outside the new size, mark it as off.  */
-  mark_window_cursors_off (XWINDOW (f->root_window));
-
-  /* Clear out any recollection of where the mouse highlighting was,
-     since it might be in a place that's outside the new frame size.
-     Actually checking whether it is outside is a pain in the neck,
-     so don't try--just let the highlighting be done afresh with new size.  */
-  cancel_mouse_face (f);
+#if USE_CARBON_EVENTS
+  if (!NILP (tip_frame) && f == XFRAME (tip_frame))
+#endif
+    mac_handle_size_change (f, pixelwidth, pixelheight);
 
   UNBLOCK_INPUT;
 }
@@ -5708,13 +6104,28 @@ x_set_mouse_pixel_position (f, pix_x, pix_y)
      struct frame *f;
      int pix_x, pix_y;
 {
-#if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
+#ifdef MAC_OSX
+  Point p;
+  CGPoint point;
+
+  BLOCK_INPUT;
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+  p.h = pix_x;
+  p.v = pix_y;
+  LocalToGlobal (&p);
+  point.x = p.h;
+  point.y = p.v;
+  CGWarpMouseCursorPosition (point);
+  UNBLOCK_INPUT;
+#else
+#if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
   BLOCK_INPUT;
 
   XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
                0, 0, 0, 0, pix_x, pix_y);
   UNBLOCK_INPUT;
 #endif
+#endif
 }
 \f
 /* focus shifting, raising and lowering.  */
@@ -5750,7 +6161,7 @@ x_raise_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-      SelectWindow (FRAME_MAC_WINDOW (f));
+      BringToFront (FRAME_MAC_WINDOW (f));
       UNBLOCK_INPUT;
     }
 }
@@ -5764,7 +6175,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;
     }
 }
@@ -5791,10 +6202,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)
     {
@@ -5809,6 +6222,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)))
@@ -5822,6 +6236,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);
       }
 
@@ -5840,9 +6255,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))
@@ -5853,31 +6265,35 @@ 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
+                                 );
+#if USE_CARBON_EVENTS
+             if (!NILP (tip_frame) && f == XFRAME (tip_frame))
+#endif
+               mac_handle_origin_change (f);
+           }
+         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));
     }
@@ -5970,7 +6386,7 @@ void
 x_iconify_frame (f)
      struct frame *f;
 {
-  OSErr err;
+  OSStatus err;
 
   /* A deactivate event does not occur when the last visible frame is
      iconified.  So if we clear the highlight here, it will not be
@@ -6038,7 +6454,12 @@ x_free_frame_resources (f)
   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)
@@ -6286,29 +6707,25 @@ xlfdpat_destroy (pat)
 
 static struct xlfdpat *
 xlfdpat_create (pattern)
-     char *pattern;
+     const char *pattern;
 {
   struct xlfdpat *pat;
   int nblocks, i, skip;
   unsigned char last_char, *p, *q, *anychar_head;
+  const unsigned char *ptr;
   struct xlfdpat_block *blk;
 
   pat = xmalloc (sizeof (struct xlfdpat));
-  if (pat == NULL)
-    goto error;
-
   pat->buf = xmalloc (strlen (pattern) + 1);
-  if (pat->buf == NULL)
-    goto error;
 
   /* Normalize the pattern string and store it to `pat->buf'.  */
   nblocks = 0;
   anychar_head = NULL;
   q = pat->buf;
   last_char = '\0';
-  for (p = pattern; *p; p++)
+  for (ptr = pattern; *ptr; ptr++)
     {
-      unsigned char c = *p;
+      unsigned char c = *ptr;
 
       if (c == '*')
        if (last_char == '*')
@@ -6317,15 +6734,17 @@ xlfdpat_create (pattern)
        else
          {
            if (last_char == '?')
-             if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
-               /*  ...*??* -> ...*??  */
-               continue;
-             else
-               /*  ...a??* -> ...a*??  */
-               {
-                 *anychar_head++ = '*';
-                 c = '?';
-               }
+             {
+               if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
+                 /*  ...*??* -> ...*??  */
+                 continue;
+               else
+                 /*  ...a??* -> ...a*??  */
+                 {
+                   *anychar_head++ = '*';
+                   c = '?';
+                 }
+             }
            nblocks++;
          }
       else if (c == '?')
@@ -6361,8 +6780,6 @@ xlfdpat_create (pattern)
     }
 
   pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
-  if (pat->blocks == NULL)
-    goto error;
 
   /* Divide the normalized pattern into blocks.  */
   p = pat->buf;
@@ -6399,10 +6816,6 @@ xlfdpat_create (pattern)
       }
 
   return pat;
-
- error:
-  xlfdpat_destroy (pat);
-  return NULL;
 }
 
 static INLINE int
@@ -6416,14 +6829,15 @@ xlfdpat_exact_p (pat)
    that the pattern in *BLK matches with its prefix.  Return NULL
    there is no such strings.  STRING must be lowered in advance.  */
 
-static char *
+static const char *
 xlfdpat_block_match_1 (blk, string, start_max)
      struct xlfdpat_block *blk;
-     unsigned char *string;
+     const unsigned char *string;
      int start_max;
 {
   int start, infinity;
-  unsigned char *p, *s;
+  unsigned char *p;
+  const unsigned char *s;
 
   xassert (blk->len > 0);
   xassert (start_max + blk->len <= strlen (string));
@@ -6480,17 +6894,17 @@ xlfdpat_block_match_1 (blk, string, start_max)
   ((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',
+/* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
    matches with STRING.  STRING must be lowered in advance.  */
 
 static int
 xlfdpat_match (pat, string)
      struct xlfdpat *pat;
-     unsigned char *string;
+     const unsigned char *string;
 {
   int str_len, nblocks, i, start_max;
   struct xlfdpat_block *blk;
-  unsigned char *s;
+  const unsigned char *s;
 
   xassert (pat->nblocks > 0);
 
@@ -6571,6 +6985,10 @@ 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;
+/* Alist linking Font Manager style to face attributes.  */
+static Lisp_Object fm_style_face_attributes_alist;
+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
@@ -6657,7 +7075,7 @@ decode_mac_font_name (name, size, coding_system)
 
 static char *
 mac_to_x_fontname (name, size, style, charset)
-     char *name;
+     const char *name;
      int size;
      Style style;
      char *charset;
@@ -6704,7 +7122,8 @@ const int kDefaultFontSize = 12;
 
 static int
 parse_x_font_name (xf, family, size, style, charset)
-     char *xf, *family;
+     const char *xf;
+     char *family;
      int *size;
      Style *style;
      char *charset;
@@ -6785,6 +7204,48 @@ 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)
+     const char *name;
+     int size;
+     Style style;
+     const 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));
+    }
+}
+
+#if USE_ATSUI
+static Lisp_Object
+fm_style_to_face_attributes (fm_style)
+     FMFontStyle fm_style;
+{
+  Lisp_Object tem;
+
+  fm_style &= (bold | italic);
+  tem = assq_no_quit (make_number (fm_style),
+                     fm_style_face_attributes_alist);
+  if (!NILP (tem))
+    return XCDR (tem);
+
+  tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
+              QCslant, fm_style & italic ? Qitalic : Qnormal);
+  fm_style_face_attributes_alist =
+    Fcons (Fcons (make_number (fm_style), tem),
+          fm_style_face_attributes_alist);
+
+  return tem;
+}
+#endif
+
 /* 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
@@ -6809,22 +7270,28 @@ init_font_name_table ()
   if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
                           text_encoding_info_alist)))
     {
-      OSErr err;
+      OSStatus err;
+      struct Lisp_Hash_Table *h;
+      unsigned hash_code;
       ItemCount nfonts, i;
       ATSUFontID *font_ids = NULL;
-      Ptr name, prev_name = NULL;
+      Ptr name;
       ByteCount name_len;
+      Lisp_Object family;
 
       atsu_font_id_hash =
        make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
                         make_float (DEFAULT_REHASH_SIZE),
                         make_float (DEFAULT_REHASH_THRESHOLD),
                         Qnil, Qnil, Qnil);;
+      h = XHASH_TABLE (atsu_font_id_hash);
+
       err = ATSUFontCount (&nfonts);
       if (err == noErr)
-       font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
-      if (font_ids)
-       err = ATSUGetFontIDs (font_ids, nfonts, NULL);
+       {
+         font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
+         err = ATSUGetFontIDs (font_ids, nfonts, NULL);
+       }
       if (err == noErr)
        for (i = 0; i < nfonts; i++)
          {
@@ -6834,40 +7301,36 @@ init_font_name_table ()
            if (err != noErr)
              continue;
            name = xmalloc (name_len + 1);
-           if (name == NULL)
-             continue;
            name[name_len] = '\0';
            err = ATSUFindFontName (font_ids[i], kFontFamilyName,
                                    kFontMacintoshPlatform, kFontNoScript,
                                    kFontNoLanguage, name_len, name,
                                    NULL, NULL);
            if (err == noErr)
-             decode_mac_font_name (name, name_len + 1, Qnil);
-           if (err == noErr
-               && *name != '.'
-               && (prev_name == NULL
-                   || strcmp (name, prev_name) != 0))
              {
-               static char *cs = "iso10646-1";
-
-               add_font_name_table_entry (mac_to_x_fontname (name, 0,
-                                                             normal, cs));
-               add_font_name_table_entry (mac_to_x_fontname (name, 0,
-                                                             italic, cs));
-               add_font_name_table_entry (mac_to_x_fontname (name, 0,
-                                                             bold, cs));
-               add_font_name_table_entry (mac_to_x_fontname (name, 0,
-                                                             italic | bold, cs));
-               Fputhash (make_unibyte_string (name, name_len),
-                         long_to_cons (font_ids[i]), atsu_font_id_hash);
-               xfree (prev_name);
-               prev_name = name;
+               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 ((font_ids[i] > MOST_POSITIVE_FIXNUM
+                          ? make_float (font_ids[i])
+                          : make_number (font_ids[i])),
+                         Fcons (QCfamily,
+                                Fcons (family,
+                                       fm_style_to_face_attributes (style))),
+                         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);
+                 }
              }
-           else
-             xfree (name);
+           xfree (name);
          }
-      if (prev_name)
-       xfree (prev_name);
       if (font_ids)
        xfree (font_ids);
     }
@@ -6895,16 +7358,16 @@ init_font_name_table ()
       FMFontSize size;
       TextEncoding encoding;
       TextEncodingBase sc;
-      Lisp_Object text_encoding_info;
+      Lisp_Object text_encoding_info, family;
 
       if (FMGetFontFamilyName (ff, name) != noErr)
-       break;
+       continue;
       p2cstr (name);
       if (*name == '.')
        continue;
 
       if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
-       break;
+       continue;
       sc = GetTextEncodingBase (encoding);
       text_encoding_info = assq_no_quit (make_number (sc),
                                         text_encoding_info_alist);
@@ -6913,13 +7376,15 @@ init_font_name_table ()
                                           text_encoding_info_alist);
       decode_mac_font_name (name, sizeof (name),
                            XCAR (XCDR (text_encoding_info)));
-      fm_font_family_alist = Fcons (Fcons (build_string (name),
-                                          make_number (ff)),
+      family = build_string (name);
+      if (!NILP (Fassoc (family, fm_font_family_alist)))
+       continue;
+      fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
                                    fm_font_family_alist);
 
       /* Point the instance iterator at the current font family.  */
       if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
-       break;
+       continue;
 
       while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
             == noErr)
@@ -6928,27 +7393,7 @@ init_font_name_table ()
 
          if (size > 0 || style == normal)
            for (; !NILP (rest); rest = XCDR (rest))
-             {
-               char *cs = SDATA (XCAR (rest));
-
-               if (size == 0)
-                 {
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 style, cs));
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 italic, cs));
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 bold, cs));
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 italic | bold,
-                                                                 cs));
-                 }
-               else
-                 {
-                   add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                                 style, cs));
-                 }
-             }
+             add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
        }
     }
 
@@ -6968,7 +7413,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 */
@@ -6987,7 +7432,7 @@ init_font_name_table ()
       GetResInfo (font_handle, &id, &type, name);
       GetFNum (name, &fontnum);
       p2cstr (name);
-      if (fontnum == 0)
+      if (fontnum == 0 || *name == '.')
        continue;
 
       TextFont (fontnum);
@@ -6999,8 +7444,10 @@ init_font_name_table ()
                                           text_encoding_info_alist);
       decode_mac_font_name (name, sizeof (name),
                            XCAR (XCDR (text_encoding_info)));
-      fm_font_family_alist = Fcons (Fcons (build_string (name),
-                                          make_number (fontnum)),
+      family = build_string (name);
+      if (!NILP (Fassoc (family, fm_font_family_alist)))
+       continue;
+      fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
                                    fm_font_family_alist);
       do
        {
@@ -7021,14 +7468,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)));
                }
            }
 
@@ -7069,7 +7511,7 @@ enum xlfd_scalable_field_index
     XLFD_SCL_LAST
   };
 
-static int xlfd_scalable_fields[] =
+static const int xlfd_scalable_fields[] =
   {
     6,                         /* PIXEL_SIZE */
     7,                         /* POINT_SIZE */
@@ -7079,14 +7521,16 @@ static int xlfd_scalable_fields[] =
 
 static Lisp_Object
 mac_do_list_fonts (pattern, maxnames)
-     char *pattern;
+     const char *pattern;
      int maxnames;
 {
   int i, n_fonts = 0;
   Lisp_Object font_list = Qnil;
   struct xlfdpat *pat;
-  char *scaled, *ptr;
-  int scl_val[XLFD_SCL_LAST], *field, *val;
+  char *scaled;
+  const char *ptr;
+  int scl_val[XLFD_SCL_LAST], *val;
+  const int *field;
   int exact;
 
   if (font_name_table == NULL)  /* Initialize when first used.  */
@@ -7156,7 +7600,7 @@ mac_do_list_fonts (pattern, maxnames)
       if (xlfdpat_match (pat, font_name_table[i]))
        {
          font_list = Fcons (build_string (font_name_table[i]), font_list);
-         if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+         if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
            break;
        }
       else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
@@ -7165,8 +7609,6 @@ mac_do_list_fonts (pattern, maxnames)
          int former_len = ptr - font_name_table[i];
 
          scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
-         if (scaled == NULL)
-           continue;
          memcpy (scaled, font_name_table[i], former_len);
          sprintf (scaled + former_len,
                   "-%d-%d-72-72-m-%d-%s",
@@ -7179,7 +7621,7 @@ mac_do_list_fonts (pattern, maxnames)
            {
              font_list = Fcons (build_string (scaled), font_list);
              xfree (scaled);
-             if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+             if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
                  break;
            }
          else
@@ -7338,7 +7780,8 @@ x_compute_min_glyph_bounds (f)
    fields are present, none is '*'.  */
 
 static int
-is_fully_specified_xlfd (char *p)
+is_fully_specified_xlfd (p)
+     const char *p;
 {
   int i;
   char *q;
@@ -7366,16 +7809,18 @@ is_fully_specified_xlfd (char *p)
 }
 
 
-/* XLoadQueryFont creates and returns an internal representation for a
-   font in a MacFontStruct struct.  There is really no concept
+/* mac_load_query_font 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
    existence and find the font number and all other information for it
    and store them in the returned MacFontStruct.  */
 
 static MacFontStruct *
-XLoadQueryFont (Display *dpy, char *fontname)
+mac_load_query_font (f, fontname)
+     struct frame *f;
+     char *fontname;
 {
-  int i, size, char_width;
+  int size;
   char *name;
   Str255 family;
   Str31 charset;
@@ -7392,6 +7837,7 @@ XLoadQueryFont (Display *dpy, char *fontname)
   short scriptcode;
 #endif
   MacFontStruct *font;
+  XCharStruct *space_bounds = NULL, *pcm;
 
   if (is_fully_specified_xlfd (fontname))
     name = fontname;
@@ -7411,18 +7857,24 @@ XLoadQueryFont (Display *dpy, char *fontname)
 #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)};
+      OSStatus err;
+      static const ATSUAttributeTag tags[] =
+       {kATSUFontTag, kATSUSizeTag,
+        kATSUQDBoldfaceTag, kATSUQDItalicTag};
+      static const 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};
-      ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector};
+      static const ATSUAttributeValuePtr values[] =
+       {&font_id, &size_fixed,
+        &bold_p, &italic_p};
+      static const ATSUFontFeatureType types[] =
+       {kAllTypographicFeaturesType, kDiacriticsType};
+      static const ATSUFontFeatureSelector selectors[] =
+       {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
       Lisp_Object font_id_cons;
+      FMFontStyle style;
 
       font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
                               atsu_font_id_hash, Qnil);
@@ -7441,7 +7893,11 @@ XLoadQueryFont (Display *dpy, char *fontname)
        return NULL;
       err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
                               tags, sizes, values);
-      fontnum = -1;
+      if (err != noErr)
+       return NULL;
+      err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
+      if (err != noErr)
+       fontnum = -1;
       scriptcode = kTextEncodingMacUnicode;
     }
   else
@@ -7487,167 +7943,103 @@ XLoadQueryFont (Display *dpy, char *fontname)
 #if USE_ATSUI
   if (font->mac_style)
     {
-      OSErr err;
-      ATSUTextLayout text_layout;
-      UniChar c = 0x20;
-      Rect char_bounds, min_bounds, max_bounds;
-      int min_width, max_width;
-      ATSTrapezoid glyph_bounds;
+      OSStatus err;
+      UniChar c;
 
-      font->per_char = xmalloc (sizeof (XCharStruct) * 0x10000);
-      if (font->per_char == NULL)
-       {
-         mac_unload_font (&one_mac_display_info, font);
-         return NULL;
-       }
-      bzero (font->per_char, sizeof (XCharStruct) * 0x10000);
+      font->min_byte1 = 0;
+      font->max_byte1 = 0xff;
+      font->min_char_or_byte2 = 0;
+      font->max_char_or_byte2 = 0xff;
+
+      font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
+      bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
+      font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
+      pcm_init (font->bounds.rows[0], 0x100);
 
 #if USE_CG_TEXT_DRAWING
-      {
-       FMFontFamily font_family;
-       FMFontStyle style;
-       ATSFontRef ats_font;
+      if (fontnum != -1)
+       {
+         FMFontStyle style;
+         ATSFontRef ats_font;
 
-       err = FMGetFontFamilyInstanceFromFont (font_id, &font_family, &style);
-       if (err == noErr)
-         err = FMGetFontFromFontFamilyInstance (font_family, fontface,
+         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);
-         }
-      }
+         /* 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 (font->cg_font)
-       font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
-      if (font->cg_glyphs)
-       bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
+       {
+         font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
+         bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
+       }
 #endif
-
-      err = atsu_get_text_layout_with_text_ptr (&c, 1,
-                                               font->mac_style,
-                                               &text_layout);
-      if (err != noErr)
+      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
+         || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
        {
          mac_unload_font (&one_mac_display_info, font);
          return NULL;
        }
 
-      for (c = 0x20; c <= 0xff; c++)
+      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)
            {
-             STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
-             STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
              c = 0x9f;
              continue;
            }
 
-         err = ATSUClearLayoutCache (text_layout, kATSUFromTextBeginning);
-         if (err == noErr)
-           err = ATSUMeasureTextImage (text_layout,
-                                       kATSUFromTextBeginning, kATSUToTextEnd,
-                                       0, 0, &char_bounds);
-         if (err == noErr)
-           err = ATSUGetGlyphBounds (text_layout, 0, 0,
-                                     kATSUFromTextBeginning, kATSUToTextEnd,
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-                                     kATSUseFractionalOrigins,
+         mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
+#if USE_CG_TEXT_DRAWING
+                                 (font->cg_glyphs ? font->cg_glyphs + c
+                                  : NULL)
 #else
-                                     kATSUseDeviceOrigins,
+                                   NULL
 #endif
-                                     1, &glyph_bounds, NULL);
-         if (err == noErr)
-           {
-             xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
-                      == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
+                                 );
 
-             char_width = Fix2Long (glyph_bounds.upperRight.x
-                                    - glyph_bounds.upperLeft.x);
-             STORE_XCHARSTRUCT (font->per_char[c],
-                                char_width, char_bounds);
-             if (c == 0x20)
-               {
-                 min_width = max_width = char_width;
-                 min_bounds = max_bounds = char_bounds;
-                 font->ascent = -Fix2Long (glyph_bounds.upperLeft.y);
-                 font->descent = Fix2Long (glyph_bounds.lowerLeft.y);
-               }
-             else
-               {
-                 if (char_width > 0)
-                   {
-                     min_width = min (min_width, char_width);
-                     max_width = max (max_width, char_width);
-                   }
-                 if (!EmptyRect (&char_bounds))
-                   {
-                     SetRect (&min_bounds,
-                              max (min_bounds.left, char_bounds.left),
-                              max (min_bounds.top, char_bounds.top),
-                              min (min_bounds.right, char_bounds.right),
-                              min (min_bounds.bottom, char_bounds.bottom));
-                     UnionRect (&max_bounds, &char_bounds, &max_bounds);
-                   }
-               }
-           }
 #if USE_CG_TEXT_DRAWING
-         if (err == noErr && char_width > 0 && font->cg_font)
+         if (font->cg_glyphs && font->cg_glyphs[c] == 0)
            {
-             ATSUGlyphInfoArray glyph_info_array;
-             ByteCount count = sizeof (ATSUGlyphInfoArray);
-
-             err = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
-                                         kATSUToTextEnd, NULL, NULL, NULL);
-             if (err == noErr)
-               err = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
-                                       kATSUToTextEnd, &count,
-                                       &glyph_info_array);
-             if (err == noErr)
-               font->cg_glyphs[c] = glyph_info_array.glyphs[0].glyphID;
-             else
-               {
-                 /* Don't use CG text drawing if font substitution
-                    occurs in ASCII or Latin-1 characters.  */
-                 CGFontRelease (font->cg_font);
-                 font->cg_font = NULL;
-                 xfree (font->cg_glyphs);
-                 font->cg_glyphs = NULL;
-               }
+             /* Don't use CG text drawing if font substitution occurs in
+                ASCII or Latin-1 characters.  */
+             CGFontRelease (font->cg_font);
+             font->cg_font = NULL;
+             xfree (font->cg_glyphs);
+             font->cg_glyphs = NULL;
            }
 #endif
        }
-
-      font->min_byte1 = 0;
-      font->max_byte1 = 0xff;
-      font->min_char_or_byte2 = 0;
-      font->max_char_or_byte2 = 0xff;
     }
   else
 #endif
     {
-      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;
+#if USE_CG_DRAWING
+      mac_prepare_for_quickdraw (f);
 #endif
+      SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
       TextFont (fontnum);
       TextSize (size);
@@ -7665,6 +8057,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
 
       if (is_two_byte_font)
        {
+         int char_width;
+
          font->min_byte1 = 0xa1;
          font->max_byte1 = 0xfe;
          font->min_char_or_byte2 = 0xa1;
@@ -7693,21 +8087,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
              char_width = StringWidth("\p\xa1\xa1");
              break;
            }
-       }
-      else
-       {
-         font->min_byte1 = font->max_byte1 = 0;
-         font->min_char_or_byte2 = 0x20;
-         font->max_char_or_byte2 = 0xff;
-
-         /* Do this instead of use the_fontinfo.widMax, which
-            incorrectly returns 15 for 12-point Monaco! */
-         char_width = CharWidth ('m');
-       }
 
-      if (is_two_byte_font)
-       {
-         font->per_char = NULL;
+         font->bounds.per_char = NULL;
 
          if (fontface & italic)
            font->max_bounds.rbearing = char_width + 1;
@@ -7722,68 +8103,80 @@ XLoadQueryFont (Display *dpy, char *fontname)
        }
       else
        {
-         int c, min_width, max_width;
-         Rect char_bounds, min_bounds, max_bounds;
-         char ch;
+         int c;
 
-         font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
-         bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1));
+         font->min_byte1 = font->max_byte1 = 0;
+         font->min_char_or_byte2 = 0x20;
+         font->max_char_or_byte2 = 0xff;
 
-         min_width = max_width = char_width;
-         SetRect (&min_bounds, -32767, -32767, 32767, 32767);
-         SetRect (&max_bounds, 0, 0, 0, 0);
-         for (c = 0x20; c <= 0xff; c++)
-           {
-             if (c == 0x7f)
-               {
-                 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
-                 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
-                 continue;
-               }
+         font->bounds.per_char =
+           xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
+         bzero (font->bounds.per_char,
+                sizeof (XCharStruct) * (0xff - 0x20 + 1));
 
-             ch = c;
-             char_width = CharWidth (ch);
-             QDTextBounds (1, &ch, &char_bounds);
-             STORE_XCHARSTRUCT (font->per_char[c - 0x20],
-                                char_width, char_bounds);
-             /* Some Japanese fonts (in SJIS encoding) return 0 as
-                the character width of 0x7f.  */
-             if (char_width > 0)
-               {
-                 min_width = min (min_width, char_width);
-                 max_width = max (max_width, char_width);
-               }
-             if (!EmptyRect (&char_bounds))
-               {
-                 SetRect (&min_bounds,
-                          max (min_bounds.left, char_bounds.left),
-                          max (min_bounds.top, char_bounds.top),
-                          min (min_bounds.right, char_bounds.right),
-                          min (min_bounds.bottom, char_bounds.bottom));
-                 UnionRect (&max_bounds, &char_bounds, &max_bounds);
-               }
-           }
-         if (min_width == max_width
-             && max_bounds.left >= 0 && max_bounds.right <= max_width)
-           {
-             /* Fixed width and no overhangs.  */
-             xfree (font->per_char);
-             font->per_char = NULL;
-           }
+         space_bounds = font->bounds.per_char;
+         mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
+                                 space_bounds, NULL);
+
+         for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
+           mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
        }
+    }
+
+  if (space_bounds)
+    {
+      int c;
 
-      /* Restore previous font number, size and face.  */
-      TextFont (old_fontnum);
-      TextSize (old_fontsize);
-      TextFace (old_fontface);
+      font->min_bounds = font->max_bounds = *space_bounds;
+      for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
+       if (pcm->width > 0)
+         {
+           font->min_bounds.lbearing = min (font->min_bounds.lbearing,
+                                            pcm->lbearing);
+           font->min_bounds.rbearing = min (font->min_bounds.rbearing,
+                                            pcm->rbearing);
+           font->min_bounds.width    = min (font->min_bounds.width,
+                                            pcm->width);
+           font->min_bounds.ascent   = min (font->min_bounds.ascent,
+                                            pcm->ascent);
+           font->min_bounds.descent  = min (font->min_bounds.descent,
+                                            pcm->descent);
+
+           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);
+           font->max_bounds.descent  = max (font->max_bounds.descent,
+                                            pcm->descent);
+         }
+      if (
+#if USE_ATSUI
+         font->mac_style == NULL &&
+#endif
+         font->max_bounds.width == font->min_bounds.width
+         && font->min_bounds.lbearing >= 0
+         && font->max_bounds.rbearing <= font->max_bounds.width)
+       {
+         /* Fixed width and no overhangs.  */
+         xfree (font->bounds.per_char);
+         font->bounds.per_char = NULL;
+       }
     }
 
 #if !defined (MAC_OS8) || USE_ATSUI
   /* AppKit and WebKit do some adjustment to the heights of Courier,
      Helvetica, and Times.  This only works on the environments where
-     the XDrawImageString counterpart is never used.  */
-  if (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
-      || strcmp (family, "times") == 0)
+     srcCopy text transfer mode is never used.  */
+  if (
+#ifdef MAC_OS8                 /* implies USE_ATSUI */
+      font->mac_style &&
+#endif
+      (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
+       || strcmp (family, "times") == 0))
     font->ascent += (font->ascent + font->descent) * .15 + 0.5;
 #endif
 
@@ -7797,17 +8190,26 @@ mac_unload_font (dpyinfo, font)
      XFontStruct *font;
 {
   xfree (font->full_name);
-  if (font->per_char)
-    xfree (font->per_char);
 #if USE_ATSUI
   if (font->mac_style)
-    ATSUDisposeStyle (font->mac_style);
+    {
+      int i;
+
+      for (i = font->min_byte1; i <= font->max_byte1; i++)
+       if (font->bounds.rows[i])
+         xfree (font->bounds.rows[i]);
+      xfree (font->bounds.rows);
+      ATSUDisposeStyle (font->mac_style);
+    }
+  else
+#endif
+    if (font->bounds.per_char)
+      xfree (font->bounds.per_char);
 #if USE_CG_TEXT_DRAWING
   if (font->cg_font)
     CGFontRelease (font->cg_font);
   if (font->cg_glyphs)
     xfree (font->cg_glyphs);
-#endif
 #endif
   xfree (font);
 }
@@ -7851,16 +8253,14 @@ 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));
 
     BLOCK_INPUT;
-    font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
+    font = mac_load_query_font (f, fontname);
     UNBLOCK_INPUT;
     if (!font)
       return NULL;
@@ -8012,8 +8412,8 @@ x_query_font (f, fontname)
 
   for (i = 0; i < dpyinfo->n_fonts; i++)
     if (dpyinfo->font_table[i].name
-       && (!strcmp (dpyinfo->font_table[i].name, fontname)
-           || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
+       && (!xstricmp (dpyinfo->font_table[i].name, fontname)
+           || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
       return (dpyinfo->font_table + i);
   return NULL;
 }
@@ -8049,16 +8449,88 @@ 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>
+OSStatus
+mac_show_hide_font_panel ()
+{
+  font_panel_shown_p = 1;
+
+  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>
@@ -8075,7 +8547,7 @@ x_find_ccl_program (fontp)
 #endif
 #endif /* ! TARGET_API_MAC_CARBON */
 
-#define M_APPLE 128
+#define M_APPLE 234
 #define I_ABOUT 1
 
 #define WINDOW_RESOURCE 128
@@ -8135,7 +8607,26 @@ Point saved_menu_event_location;
 
 /* Apple Events */
 #if USE_CARBON_EVENTS
-static Lisp_Object Qhicommand;
+static Lisp_Object Qhi_command;
+#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;
+static Lisp_Object Vmac_ts_script_language_on_focus;
+static Lisp_Object saved_ts_script_language_on_focus;
+static ScriptLanguageRecord saved_ts_language;
+static Component saved_ts_component;
+#endif
 #endif
 extern int mac_ready_for_apple_events;
 extern Lisp_Object Qundefined;
@@ -8143,25 +8634,22 @@ 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));
 
 #if USE_CARBON_EVENTS
 #ifdef MAC_OSX
 extern void init_service_handler ();
-static Lisp_Object Qservices, Qpaste, Qperform;
+static Lisp_Object Qservice, Qpaste, Qperform;
 #endif
 /* Window Event Handler */
 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
                                                EventRef, void *);
 #endif
-OSErr install_window_handler (WindowPtr);
+OSStatus install_window_handler (WindowPtr);
 
 extern void init_emacs_passwd_dir ();
 extern int emacs_main (int, char **, char **);
@@ -8169,6 +8657,81 @@ extern int emacs_main (int, char **, char **);
 extern void initialize_applescript();
 extern void terminate_applescript();
 
+/* Table for translating Mac keycode to X keysym values.  Contributed
+   by Sudhir Shenoy.
+   Mapping for special keys is now identical to that in Apple X11
+   except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
+   on the right of the Cmd key on laptops, and fn + `enter' (->
+   <linefeed>). */
+static const unsigned char keycode_to_xkeysym_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, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+  /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
+  /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
+  /*0x38*/ 0, 0, 0, 0,
+  /*0x3C*/ 0, 0, 0, 0,
+
+  /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
+  /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
+  /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
+  /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
+
+  /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
+  /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
+  /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
+  /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
+
+  /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
+  /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
+  /*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*/,
+  /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
+  /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
+  /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 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 const 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-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
+  /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
+  /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
+  /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
+
+  /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 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 */
+
 static unsigned int
 #if USE_CARBON_EVENTS
 mac_to_emacs_modifiers (UInt32 mods)
@@ -8285,6 +8848,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)
@@ -8318,13 +8882,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;
 
@@ -8340,7 +8910,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);
@@ -8358,6 +8928,7 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
 
 #endif
 
+#ifdef MAC_OS8
 static void
 do_get_menus (void)
 {
@@ -8419,6 +8990,7 @@ do_check_ram_size (void)
       exit (1);
     }
 }
+#endif /* MAC_OS8 */
 
 static void
 do_window_update (WindowPtr win)
@@ -8478,23 +9050,97 @@ is_emacs_window (WindowPtr win)
   return 0;
 }
 
-static void
-do_app_resume ()
+#if USE_MAC_TSM
+static OSStatus
+mac_tsm_resume ()
 {
-  /* Window-activate events will do the job. */
+  OSStatus err;
+  ScriptLanguageRecord slrec, *slptr = NULL;
+
+  err = ActivateTSMDocument (tsm_document_id);
+
+  if (err == noErr)
+    {
+      if (EQ (Vmac_ts_script_language_on_focus, Qt)
+         && EQ (saved_ts_script_language_on_focus, Qt))
+       slptr = &saved_ts_language;
+      else if (CONSP (Vmac_ts_script_language_on_focus)
+              && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
+              && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
+              && CONSP (saved_ts_script_language_on_focus)
+              && EQ (XCAR (saved_ts_script_language_on_focus),
+                     XCAR (Vmac_ts_script_language_on_focus))
+              && EQ (XCDR (saved_ts_script_language_on_focus),
+                     XCDR (Vmac_ts_script_language_on_focus)))
+       {
+         slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
+         slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
+         slptr = &slrec;
+       }
+    }
+
+  if (slptr)
+    {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+      err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
+                                         kKeyboardInputMethodClass);
+#else
+      err = SetDefaultInputMethod (saved_ts_component, slptr);
+#endif
+      if (err == noErr)
+       err = SetTextServiceLanguage (slptr);
+
+      /* Seems to be needed on Mac OS X 10.2.  */
+      if (err == noErr)
+       KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
+    }
+
+  return err;
 }
 
-static void
-do_app_suspend ()
+static OSStatus
+mac_tsm_suspend ()
 {
-  /* Window-deactivate events will do the job. */
-}
+  OSStatus err;
+  ScriptLanguageRecord slrec, *slptr = NULL;
 
+  saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
 
-static void
+  if (EQ (Vmac_ts_script_language_on_focus, Qt))
+    {
+      err = GetTextServiceLanguage (&saved_ts_language);
+      if (err == noErr)
+       slptr = &saved_ts_language;
+    }
+  else if (CONSP (Vmac_ts_script_language_on_focus)
+          && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
+          && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
+    {
+      slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
+      slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
+      slptr = &slrec;
+    }
+
+  if (slptr)
+    {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+      GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
+                                   kKeyboardInputMethodClass);
+#else
+      GetDefaultInputMethod (&saved_ts_component, slptr);
+#endif
+    }
+
+  err = DeactivateTSMDocument (tsm_document_id);
+
+  return err;
+}
+#endif
+
+#if !TARGET_API_MAC_CARBON
+void
 do_apple_menu (SInt16 menu_item)
 {
-#if !TARGET_API_MAC_CARBON
   Str255 item_name;
   SInt16 da_driver_refnum;
 
@@ -8505,49 +9151,16 @@ do_apple_menu (SInt16 menu_item)
       GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
       da_driver_refnum = OpenDeskAcc (item_name);
     }
-#endif /* !TARGET_API_MAC_CARBON */
-}
-
-void
-do_menu_choice (SInt32 menu_choice)
-{
-  SInt16 menu_id, menu_item;
-
-  menu_id = HiWord (menu_choice);
-  menu_item = LoWord (menu_choice);
-
-  switch (menu_id)
-    {
-    case 0:
-      break;
-
-    case M_APPLE:
-      do_apple_menu (menu_item);
-      break;
-
-    default:
-      {
-        struct frame *f = mac_focus_frame (&one_mac_display_info);
-        MenuHandle menu = GetMenuHandle (menu_id);
-        if (menu)
-          {
-            UInt32 refcon;
-
-            GetMenuItemRefCon (menu, menu_item, &refcon);
-            menubar_selection_callback (f, refcon);
-          }
-      }
-    }
-
-  HiliteMenu (0);
 }
-
+#endif /* !TARGET_API_MAC_CARBON */
 
 /* Handle drags in size box.  Based on code contributed by Ben
    Mesander and IM - Window Manager A.  */
 
 static void
-do_grow_window (WindowPtr w, EventRecord *e)
+do_grow_window (w, e)
+     WindowPtr w;
+     const EventRecord *e;
 {
   Rect limit_rect;
   int rows, columns, width, height;
@@ -8592,6 +9205,32 @@ do_grow_window (WindowPtr w, EventRecord *e)
 }
 
 
+#if TARGET_API_MAC_CARBON
+static Point
+mac_get_ideal_size (f)
+     struct frame *f;
+{
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+  WindowPtr w = FRAME_MAC_WINDOW (f);
+  Point ideal_size;
+  Rect standard_rect;
+  int height, width, columns, rows;
+
+  ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+  ideal_size.v = dpyinfo->height;
+  IsWindowInStandardState (w, &ideal_size, &standard_rect);
+  /* Adjust the standard size according to character boundaries.  */
+  width = standard_rect.right - standard_rect.left;
+  height = standard_rect.bottom - standard_rect.top;
+  columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
+  rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
+  ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
+  ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+
+  return ideal_size;
+}
+#endif
+
 /* Handle clicks in zoom box.  Calculation of "standard state" based
    on code in IM - Window Manager A and code contributed by Ben
    Mesander.  The standard state of an Emacs window is 80-characters
@@ -8600,42 +9239,30 @@ 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 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;
-
-    standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-    standard_size.v = dpyinfo->height;
+  Point ideal_size = mac_get_ideal_size (f);
 
-    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;
-      }
+  GetWindowBounds (w, kWindowContentRgn, &port_rect);
+  if (IsWindowInStandardState (w, &ideal_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);
-  }
+#ifdef MAC_OS8
+  mac_clear_window (f);
+#endif
+  ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size);
 #else /* not TARGET_API_MAC_CARBON */
+  GrafPtr save_port;
+  Point top_left;
+  int w_title_height, rows;
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
   GetPort (&save_port);
 
   SetPortWindowPort (w);
@@ -8673,6 +9300,7 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   SetPort (save_port);
 #endif /* not TARGET_API_MAC_CARBON */
 
+#if !USE_CARBON_EVENTS
   /* retrieve window size and update application values */
 #if TARGET_API_MAC_CARBON
   GetWindowPortBounds (w, &port_rect);
@@ -8682,66 +9310,92 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   height = port_rect.bottom - port_rect.top;
   width = port_rect.right - port_rect.left;
 
-  if (width != FRAME_PIXEL_WIDTH (f)
-      || height != FRAME_PIXEL_HEIGHT (f))
-    {
-      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
-      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
-
-      change_frame_size (f, rows, columns, 0, 1, 0);
-      SET_FRAME_GARBAGED (f);
-      cancel_mouse_face (f);
-
-      FRAME_PIXEL_WIDTH (f) = width;
-      FRAME_PIXEL_HEIGHT (f) = height;
-    }
-  x_real_positions (f, &f->left_pos, &f->top_pos);
+  mac_handle_size_change (f, width, height);
+  mac_handle_origin_change (f);
+#endif
 }
 
-OSErr
+void
 mac_store_apple_event (class, id, desc)
      Lisp_Object class, id;
      const AEDesc *desc;
 {
-  OSErr err = noErr;
   struct input_event buf;
-  AEDesc *desc_copy;
 
-  desc_copy = xmalloc (sizeof (AEDesc));
-  if (desc_copy == NULL)
-    err = memFullErr;
-  else
-    err = AEDuplicateDesc (desc, desc_copy);
-  if (err == noErr)
-    {
-      EVENT_INIT (buf);
+  EVENT_INIT (buf);
+
+  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
+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;
+     const EventParamName *names;
+     const EventParamType *types;
+{
+  OSStatus err = eventNotHandledErr;
+  Lisp_Object binding;
 
-      buf.kind = MAC_APPLE_EVENT;
-      buf.x = class;
-      buf.y = id;
-      buf.code = (int)desc_copy;
-      XSETFRAME (buf.frame_or_window,
-                mac_focus_frame (&one_mac_display_info));
-      buf.arg = Qnil;
-      kbd_buffer_store_event (&buf);
+  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 ();
+           }
+       }
     }
 
   return err;
 }
 
-Lisp_Object
-mac_make_lispy_event_code (code)
-     int code;
+void
+mac_store_drag_event (window, mouse_pos, modifiers, desc)
+     WindowRef window;
+     Point mouse_pos;
+     SInt16 modifiers;
+     const AEDesc *desc;
 {
-  AEDesc *desc = (AEDesc *)code;
-  Lisp_Object obj;
+  struct input_event buf;
 
-  obj = mac_aedesc_to_lisp (desc);
-  AEDisposeDesc (desc);
-  xfree (desc);
+  EVENT_INIT (buf);
 
-  return obj;
+  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
@@ -8750,56 +9404,37 @@ mac_handle_command_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  OSStatus result;
-  OSErr err;
+  OSStatus result, err;
   HICommand command;
-  Lisp_Object class_key, id_key, binding;
+  static const EventParamName names[] =
+    {kEventParamDirectObject, kEventParamKeyModifiers};
+  static const EventParamType types[] =
+    {typeHICommand, typeUInt32};
+  int num_params = sizeof (names) / sizeof (names[0]);
 
   result = CallNextEventHandler (next_handler, event);
   if (result != eventNotHandledErr)
     return result;
 
-  GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL,
-                    sizeof (HICommand), NULL, &command);
+  err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
+                          NULL, sizeof (HICommand), NULL, &command);
 
-  if (command.commandID == 0)
+  if (err != noErr || command.commandID == 0)
     return eventNotHandledErr;
 
-  /* A HICommand event is mapped to an Apple event whose event class
-     symbol is `hicommand' and event ID is its command ID.  */
-  class_key = Qhicommand;
-  mac_find_apple_event_spec (0, command.commandID,
-                            &class_key, &id_key, &binding);
-  if (!NILP (binding) && !EQ (binding, Qundefined))
-    if (INTEGERP (binding))
-      return XINT (binding);
-    else
-      {
-       AppleEvent apple_event;
-       UInt32 modifiers;
-       static EventParamName names[] = {kEventParamDirectObject,
-                                        kEventParamKeyModifiers};
-       static EventParamType types[] = {typeHICommand,
-                                        typeUInt32};
-       err = create_apple_event_from_event_ref (event, 2, names, types,
-                                                &apple_event);
-       if (err == noErr)
-         {
-           err = mac_store_apple_event (class_key, id_key, &apple_event);
-           AEDisposeDesc (&apple_event);
-         }
-       if (err == noErr)
-         return noErr;
-      }
-
-  return eventNotHandledErr;
+  /* A HI command event is mapped to an Apple event whose event class
+     symbol is `hi-command' and event ID is its command ID.  */
+  err = mac_store_event_ref_as_apple_event (0, command.commandID,
+                                           Qhi_command, Qnil,
+                                           event, num_params, names, types);
+  return err == noErr ? noErr : eventNotHandledErr;
 }
 
-static OSErr
+static OSStatus
 init_command_handler ()
 {
-  OSErr err = noErr;
-  EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
+  static const EventTypeSpec specs[] =
+    {{kEventClassCommand, kEventCommandProcess}};
   static EventHandlerUPP handle_command_eventUPP = NULL;
 
   if (handle_command_eventUPP == NULL)
@@ -8816,13 +9451,17 @@ mac_handle_window_event (next_handler, event, data)
      void *data;
 {
   WindowPtr wp;
-  OSStatus result;
+  OSStatus result, err;
+  struct frame *f;
   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;
 
+  f = mac_window_to_frame (wp);
   switch (GetEventKind (event))
     {
     case kEventWindowUpdate:
@@ -8833,14 +9472,32 @@ mac_handle_window_event (next_handler, event, data)
       do_window_update (wp);
       return noErr;
 
+    case kEventWindowGetIdealSize:
+      result = CallNextEventHandler (next_handler, event);
+      if (result != eventNotHandledErr)
+       return result;
+
+      {
+       Point ideal_size = mac_get_ideal_size (f);
+
+       err = SetEventParameter (event, kEventParamDimensions,
+                                typeQDPoint, sizeof (Point), &ideal_size);
+       if (err == noErr)
+         return noErr;
+      }
+      break;
+
     case kEventWindowBoundsChanging:
       result = CallNextEventHandler (next_handler, event);
       if (result != eventNotHandledErr)
        return result;
 
-      GetEventParameter (event, kEventParamAttributes, typeUInt32,
-                        NULL, sizeof (UInt32), NULL, &attributes);
-      size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
+      err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
+                              NULL, sizeof (UInt32), NULL, &attributes);
+      if (err != noErr)
+       break;
+
+      size_hints = FRAME_SIZE_HINTS (f);
       if ((attributes & kWindowBoundsChangeUserResize)
          && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
              == (PResizeInc | PBaseSize | PMinSize)))
@@ -8848,9 +9505,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;
 
@@ -8878,16 +9538,96 @@ mac_handle_window_event (next_handler, event, data)
        }
       break;
 
+    case kEventWindowBoundsChanged:
+      err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
+                              NULL, sizeof (UInt32), NULL, &attributes);
+      if (err != noErr)
+       break;
+
+      if (attributes & kWindowBoundsChangeSizeChanged)
+       {
+         Rect bounds;
+
+         err = GetEventParameter (event, kEventParamCurrentBounds,
+                                  typeQDRectangle, NULL, sizeof (Rect),
+                                  NULL, &bounds);
+         if (err == noErr)
+           {
+             int width, height;
+
+             width = bounds.right - bounds.left;
+             height = bounds.bottom - bounds.top;
+             mac_handle_size_change (f, width, height);
+           }
+       }
+
+      if (attributes & kWindowBoundsChangeOriginChanged)
+       mac_handle_origin_change (f);
+
+      return noErr;
+
     case kEventWindowShown:
     case kEventWindowHidden:
     case kEventWindowExpanded:
     case kEventWindowCollapsed:
       result = CallNextEventHandler (next_handler, event);
 
-      mac_handle_visibility_change (mac_window_to_frame (wp));
+      mac_handle_visibility_change (f);
       return noErr;
 
       break;
+
+    case kEventWindowClose:
+      result = CallNextEventHandler (next_handler, event);
+      {
+       struct input_event buf;
+
+       EVENT_INIT (buf);
+       buf.kind = DELETE_WINDOW_EVENT;
+       XSETFRAME (buf.frame_or_window, f);
+       buf.arg = Qnil;
+       kbd_buffer_store_event (&buf);
+      }
+      return noErr;
+
+#ifdef MAC_OSX
+    case kEventWindowToolbarSwitchMode:
+      result = CallNextEventHandler (next_handler, event);
+      {
+       static const EventParamName names[] = {kEventParamDirectObject,
+                                              kEventParamWindowMouseLocation,
+                                              kEventParamKeyModifiers,
+                                              kEventParamMouseButton,
+                                              kEventParamClickCount,
+                                              kEventParamMouseChord};
+       static const 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 = mac_tsm_resume ();
+      return err == noErr ? noErr : result;
+
+    case kEventWindowFocusRelinquish:
+      result = CallNextEventHandler (next_handler, event);
+      err = mac_tsm_suspend ();
+      return err == noErr ? noErr : result;
+#endif
     }
 
   return eventNotHandledErr;
@@ -8899,7 +9639,7 @@ mac_handle_mouse_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  OSStatus result;
+  OSStatus result, err;
 
   switch (GetEventKind (event))
     {
@@ -8915,22 +9655,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 =
@@ -8953,33 +9702,235 @@ mac_handle_mouse_event (next_handler, event, data)
   return eventNotHandledErr;
 }
 
-#ifdef MAC_OSX
-OSErr
-mac_store_services_event (event)
+#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;
-  AppleEvent apple_event;
+  OSStatus result, err;
   Lisp_Object id_key;
+  int num_params;
+  const EventParamName *names;
+  const EventParamType *types;
+  static const EventParamName names_sel[] = {kEventParamATSUFontID,
+                                            kEventParamATSUFontSize,
+                                            kEventParamFMFontFamily,
+                                            kEventParamFMFontSize,
+                                            kEventParamFontColor};
+  static const EventParamType types_sel[] = {typeATSUFontID,
+                                            typeATSUSize,
+                                            typeFMFontFamily,
+                                            typeFMFontSize,
+                                            typeFontColor};
+
+  result = CallNextEventHandler (next_handler, event);
+  if (result != eventNotHandledErr)
+    return result;
 
   switch (GetEventKind (event))
     {
-    case kEventServicePaste:
-      id_key = Qpaste;
-      err = create_apple_event_from_event_ref (event, 0, NULL, NULL,
-                                              &apple_event);
+    case kEventFontPanelClosed:
+      id_key = Qpanel_closed;
+      num_params = 0;
+      names = NULL;
+      types = NULL;
       break;
 
-    case kEventServicePerform:
+    case kEventFontSelection:
+      id_key = Qselection;
+      num_params = sizeof (names_sel) / sizeof (names_sel[0]);
+      names = names_sel;
+      types = types_sel;
+      break;
+    }
+
+  err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
+                                           event, num_params,
+                                           names, types);
+
+  return err == noErr ? noErr : eventNotHandledErr;
+}
+#endif
+
+#if USE_MAC_TSM
+static pascal OSStatus
+mac_handle_text_input_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus result, err = noErr;
+  Lisp_Object id_key = Qnil;
+  int num_params;
+  const EventParamName *names;
+  const EventParamType *types;
+  static UInt32 seqno_uaia = 0;
+  static const EventParamName names_uaia[] =
+    {kEventParamTextInputSendComponentInstance,
+     kEventParamTextInputSendRefCon,
+     kEventParamTextInputSendSLRec,
+     kEventParamTextInputSendFixLen,
+     kEventParamTextInputSendText,
+     kEventParamTextInputSendUpdateRng,
+     kEventParamTextInputSendHiliteRng,
+     kEventParamTextInputSendClauseRng,
+     kEventParamTextInputSendPinRng,
+     kEventParamTextInputSendTextServiceEncoding,
+     kEventParamTextInputSendTextServiceMacEncoding,
+     EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
+  static const EventParamType types_uaia[] =
+    {typeComponentInstance,
+     typeLongInteger,
+     typeIntlWritingCode,
+     typeLongInteger,
+#ifdef MAC_OSX
+     typeUnicodeText,
+#else
+     typeChar,
+#endif
+     typeTextRangeArray,
+     typeTextRangeArray,
+     typeOffsetArray,
+     typeTextRange,
+     typeUInt32,
+     typeUInt32,
+     typeUInt32};
+  static const EventParamName names_ufke[] =
+    {kEventParamTextInputSendComponentInstance,
+     kEventParamTextInputSendRefCon,
+     kEventParamTextInputSendSLRec,
+     kEventParamTextInputSendText};
+  static const EventParamType types_ufke[] =
+    {typeComponentInstance,
+     typeLongInteger,
+     typeIntlWritingCode,
+     typeUnicodeText};
+
+  result = CallNextEventHandler (next_handler, event);
+
+  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;
+
+    case kEventTextInputUnicodeForKeyEvent:
+      {
+       EventRef kbd_event;
+       UInt32 actual_size, modifiers, mapped_modifiers;
+
+       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)
+         {
+           mapped_modifiers =
+             (NILP (Vmac_control_modifier) ? 0 : controlKey)
+             | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+             | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+#ifdef MAC_OSX
+           mapped_modifiers |=
+             (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
+#endif
+           if (modifiers & mapped_modifiers)
+             /* There're mapped modifier keys.  Process it in
+                XTread_socket.  */
+             return eventNotHandledErr;
+         }
+       if (err == noErr)
+         err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
+                                  typeUnicodeText, NULL, 0, &actual_size,
+                                  NULL);
+       if (err == noErr && actual_size == sizeof (UniChar))
+         {
+           UniChar code;
+
+           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)
+                 {
+                   UInt32 key_code;
+
+                   err = GetEventParameter (kbd_event, kEventParamKeyCode,
+                                            typeUInt32, NULL, sizeof (UInt32),
+                                            NULL, &key_code);
+                   if (!(err == noErr && key_code <= 0x7f
+                         && keycode_to_xkeysym_table [key_code]))
+                     {
+                       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 =
+                         mac_to_emacs_modifiers (modifiers);
+                       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;
+             }
+         }
+      }
+      /* 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 kEventTextInputOffsetToPos:
       {
-       static EventParamName names[] = {kEventParamServiceMessageName,
-                                        kEventParamServiceUserData};
-       static EventParamType types[] = {typeCFStringRef,
-                                        typeCFStringRef};
-
-       id_key = Qperform;
-       err = create_apple_event_from_event_ref (event, 2, names, types,
-                                                &apple_event);
+       struct frame *f;
+       struct window *w;
+       Point p;
+
+       if (!OVERLAYP (Vmac_ts_active_input_overlay))
+         return eventNotHandledErr;
+
+       /* 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);
+         }
+
+       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;
 
@@ -8987,39 +9938,115 @@ mac_store_services_event (event)
       abort ();
     }
 
-  if (err == 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
+
+#ifdef MAC_OSX
+OSStatus
+mac_store_service_event (event)
+     EventRef event;
+{
+  OSStatus err;
+  Lisp_Object id_key;
+  int num_params;
+  const EventParamName *names;
+  const EventParamType *types;
+  static const EventParamName names_pfm[] =
+    {kEventParamServiceMessageName, kEventParamServiceUserData};
+  static const EventParamType types_pfm[] =
+    {typeCFStringRef, typeCFStringRef};
+
+  switch (GetEventKind (event))
     {
-      err = mac_store_apple_event (Qservices, id_key, &apple_event);
-      AEDisposeDesc (&apple_event);
+    case kEventServicePaste:
+      id_key = Qpaste;
+      num_params = 0;
+      names = NULL;
+      types = NULL;
+      break;
+
+    case kEventServicePerform:
+      id_key = Qperform;
+      num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
+      names = names_pfm;
+      types = types_pfm;
+      break;
+
+    default:
+      abort ();
     }
 
+  err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
+                                           event, num_params,
+                                           names, types);
+
   return err;
 }
 #endif /* MAC_OSX */
 #endif /* USE_CARBON_EVENTS */
 
 
-OSErr
+OSStatus
 install_window_handler (window)
      WindowPtr window;
 {
-  OSErr err = noErr;
+  OSStatus err = noErr;
 #if USE_CARBON_EVENTS
-  EventTypeSpec specs_window[] =
+  static const EventTypeSpec specs_window[] =
     {{kEventClassWindow, kEventWindowUpdate},
+     {kEventClassWindow, kEventWindowGetIdealSize},
      {kEventClassWindow, kEventWindowBoundsChanging},
+     {kEventClassWindow, kEventWindowBoundsChanged},
      {kEventClassWindow, kEventWindowShown},
      {kEventClassWindow, kEventWindowHidden},
      {kEventClassWindow, kEventWindowExpanded},
-     {kEventClassWindow, kEventWindowCollapsed}};
-  EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
+     {kEventClassWindow, kEventWindowCollapsed},
+     {kEventClassWindow, kEventWindowClose},
+#ifdef MAC_OSX
+     {kEventClassWindow, kEventWindowToolbarSwitchMode},
+#endif
+#if USE_MAC_TSM
+     {kEventClassWindow, kEventWindowFocusAcquired},
+     {kEventClassWindow, kEventWindowFocusRelinquish},
+#endif
+  };
+  static const EventTypeSpec specs_mouse[] =
+    {{kEventClassMouse, kEventMouseWheelMoved}};
   static EventHandlerUPP handle_window_eventUPP = NULL;
   static EventHandlerUPP handle_mouse_eventUPP = NULL;
+#if USE_MAC_FONT_PANEL
+  static const EventTypeSpec specs_font[] =
+    {{kEventClassFont, kEventFontPanelClosed},
+     {kEventClassFont, kEventFontSelection}};
+  static EventHandlerUPP handle_font_eventUPP = NULL;
+#endif
+#if USE_MAC_TSM
+  static const EventTypeSpec specs_text_input[] =
+    {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
+     {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
+     {kEventClassTextInput, kEventTextInputOffsetToPos}};
+  static EventHandlerUPP handle_text_input_eventUPP = NULL;
+#endif
 
   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);
@@ -9027,185 +10054,31 @@ install_window_handler (window)
     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);
-
+#if USE_MAC_FONT_PANEL
   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;
-}
-
-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);
+    err = InstallWindowEventHandler (window, handle_font_eventUPP,
+                                    GetEventTypeCount (specs_font),
+                                    specs_font, NULL, NULL);
 #endif
-}
-
-#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;
-           }
-       }
-      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 kDragTrackingInWindow:
-      break;
-
-    case kDragTrackingLeaveWindow:
-      if (can_accept)
-       {
-         struct frame *f = mac_window_to_frame (window);
-
-         HideDragHilite (theDrag);
-         SetThemeCursor (kThemeArrowCursor);
-       }
-      break;
-
-    case kDragTrackingLeaveHandler:
-      break;
-    }
-
-  return noErr;
-}
-
-static pascal OSErr
-mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
-                    DragReference theDrag)
-{
-  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;
-
-  file_list = Qnil;
-  GetDragMouse (theDrag, &mouse, 0L);
-  CountDragItems (theDrag, &items);
-  for (index = 1; index <= items; index++)
-    {
-      /* Only handle file references.  */
-      GetDragItemReferenceNumber (theDrag, index, &theItem);
-      result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
-      if (result == noErr)
-       {
-#ifdef MAC_OSX
-         FSRef fref;
+#if USE_MAC_TSM
+  if (err == noErr)
+    err = InstallWindowEventHandler (window, handle_text_input_eventUPP,
+                                    GetEventTypeCount (specs_text_input),
+                                    specs_text_input, window, NULL);
 #endif
-         char unix_path_name[MAXPATHLEN];
-
-         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 = frame;
-      event.arg = file_list;
-      /* Post to the interrupt queue */
-      kbd_buffer_store_event (&event);
-      /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
-      {
-       ProcessSerialNumber psn;
-       GetCurrentProcess (&psn);
-       SetFrontProcess (&psn);
-      }
+  if (err == noErr)
+    err = install_drag_handler (window);
 
-      return noErr;
-    }
-  else
-    return dragNotAcceptedErr;
+  return err;
+}
+
+void
+remove_window_handler (window)
+     WindowPtr window;
+{
+  remove_drag_handler (window);
 }
-#endif
 
 
 #if __profile__
@@ -9259,6 +10132,8 @@ main (void)
 
   init_environ ();
 
+  init_coercion_handler ();
+
   initialize_applescript ();
 
   init_apple_event_handler ();
@@ -9288,169 +10163,6 @@ main (void)
 }
 #endif
 
-/* Table for translating Mac keycode to X keysym values.  Contributed
-   by Sudhir Shenoy.
-   Mapping for special keys is now identical to that in Apple X11
-   except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
-   on the right of the Cmd key on laptops, and fn + `enter' (->
-   <linefeed>). */
-static unsigned char keycode_to_xkeysym_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, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-  /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
-  /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
-  /*0x38*/ 0, 0, 0, 0,
-  /*0x3C*/ 0, 0, 0, 0,
-
-  /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
-  /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
-  /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
-  /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
-
-  /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
-  /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
-  /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
-  /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
-
-  /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
-  /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
-  /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
-  /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
-
-  /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
-  /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
-  /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
-  /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
-};
-
-
-static int
-keycode_to_xkeysym (int keyCode, int *xKeySym)
-{
-  *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
-  return *xKeySym != 0;
-}
-
-static unsigned char fn_keycode_to_xkeysym_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, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
-  /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
-  /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
-  /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
-
-  /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
-  /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
-  /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
-  /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
-
-  /*0x60*/ 0, 0, 0, 0,
-  /*0x64*/ 0, 0, 0, 0,
-  /*0x68*/ 0, 0, 0, 0,
-  /*0x6C*/ 0, 0, 0, 0,
-
-  /*0x70*/ 0, 0, 0, 0,
-  /*0x74*/ 0, 0, 0, 0,
-  /*0x78*/ 0, 0, 0, 0,
-  /*0x7C*/ 0, 0, 0, 0
-};
-static int
-convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
-{
-#ifdef MAC_OSX
-  /* Use the special map to translate keys when function modifier is
-     to be caught. KeyTranslate can't be used in that case.
-     We can't detect the function key using the input_event.modifiers,
-     because this uses the high word of an UInt32. Therefore,
-     we'll just read it out of the original eventRef.
-  */
-
-
-  /* TODO / known issues
-
-  - Fn-Shift-j is regonized as Fn-j and not Fn-J.
-  The above table always translates to lower characters. We need to use
-  the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
-
-  - The table is meant for English language keyboards, and it will work
-  for many others with the exception of key combinations like Fn-ö on
-  a German keyboard, which is currently mapped to Fn-;.
-  How to solve this without keeping separate tables for all keyboards
-  around? KeyTranslate isn't of much help here, as it only takes a 16-bit
-  value for keycode with the modifiers in he high byte, i.e. no room for the
-  Fn modifier. That's why we need the table.
-
-  */
-
-  UInt32 mods = 0;
-  if (!NILP(Vmac_function_modifier))
-    {
-      GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
-                        sizeof (UInt32), NULL, &mods);
-      if (mods & kEventKeyModifierFnMask)
-       {  *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
-
-         return (*newCode != 0);
-       }
-    }
-#endif
-  return false;
-}
-
-static int
-backtranslate_modified_keycode(int mods, int keycode, int def)
-{
-  EventModifiers mapped_modifiers =
-    (NILP (Vmac_control_modifier) ? 0 : controlKey)
-    | (NILP (Vmac_option_modifier) ? 0 : optionKey)
-    | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
-
-  if (mods & mapped_modifiers)
-    {
-      /* This code comes from Keyboard Resource,
-        Appendix C of IM - Text.  This is necessary
-        since shift is ignored in KCHR table
-        translation when option or command is pressed.
-        It also does not translate correctly
-        control-shift chars like C-% so mask off shift
-        here also.
-
-        Not done for combinations with the option key (alt)
-        unless it is to be caught by Emacs:  this is
-        to preserve key combinations translated by the OS
-        such as Alt-3.
-      */
-      /* Mask off modifier keys that are mapped to some Emacs
-        modifiers.  */
-      int new_modifiers = mods & ~mapped_modifiers;
-      /* set high byte of keycode to modifier high byte*/
-      int new_keycode = keycode | new_modifiers;
-      Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-      unsigned long some_state = 0;
-      return (int) KeyTranslate (kchr_ptr, new_keycode,
-                                &some_state) & 0xff;
-      /* TO DO: Recognize two separate resulting characters, "for
-        example, when the user presses Option-E followed by N, you
-        can map this through the KeyTranslate function using the
-        U.S. 'KCHR' resource to produce Â´n, which KeyTranslate
-        returns as two characters in the bytes labeled Character code
-        1 and Character code 2." (from Carbon API doc) */
-
-    }
-  else
-    return def;
-}
-
-
 #if !USE_CARBON_EVENTS
 static RgnHandle mouse_region = NULL;
 
@@ -9490,6 +10202,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
@@ -9518,10 +10303,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))
@@ -9531,10 +10322,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;
@@ -9611,7 +10398,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
                  {
@@ -9649,18 +10442,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;
 
@@ -9760,17 +10553,29 @@ 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);
 #endif /* not TARGET_API_MAC_CARBON */
                /* Update the frame parameters.  */
+#if !USE_CARBON_EVENTS
                {
                  struct frame *f = mac_window_to_frame (window_ptr);
 
                  if (f && !f->async_iconified)
-                   x_real_positions (f, &f->left_pos, &f->top_pos);
+                   mac_handle_origin_change (f);
                }
+#endif
                break;
 
              case inGoAway:
@@ -9819,10 +10624,12 @@ XTread_socket (sd, expected, hold_quit)
          switch ((er.message >> 24) & 0x000000FF)
            {
            case suspendResumeMessage:
-             if ((er.message & resumeFlag) == 1)
-               do_app_resume ();
+#if USE_MAC_TSM
+             if (er.message & resumeFlag)
+               mac_tsm_resume ();
              else
-               do_app_suspend ();
+               mac_tsm_suspend ();
+#endif
              break;
 
            case mouseMovedMessage:
@@ -9867,7 +10674,7 @@ XTread_socket (sd, expected, hold_quit)
                  else
                    {
                      /* Generate SELECT_WINDOW_EVENTs when needed.  */
-                     if (mouse_autoselect_window)
+                     if (!NILP (Vmouse_autoselect_window))
                        {
                          Lisp_Object window;
 
@@ -9980,110 +10787,219 @@ 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) || USE_MAC_TSM)
            /* When using Carbon Events, we need to pass raw keyboard
               events to the TSM ourselves.  If TSM handles it, it
               will pass back noErr, otherwise it will pass back
               "eventNotHandledErr" and we can process it
               normally.  */
-           if ((mac_pass_command_to_system
-                || !(er.modifiers & cmdKey))
-               && (mac_pass_control_to_system
-                   || !(er.modifiers & controlKey))
-               && (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;
              }
 
-           /* translate the keycode back to determine the original key */
-           /* Convert key code if function key is pressed.
-              Otherwise, if non-ASCII-event, take care of that
-              without re-translating the key code. */
-#if USE_CARBON_EVENTS
-           if (convert_fn_keycode (eventRef, keycode, &xkeysym))
+           current_key_script = GetScriptManagerVariable (smKeyScript);
+           if (last_key_script != current_key_script)
              {
-               inev.code = xkeysym;
-               /* this doesn't work - tried to add shift modifiers */
-                 inev.code =
-                   backtranslate_modified_keycode(er.modifiers & (~0x2200),
-                                                  xkeysym | 0x80,  xkeysym);
-               inev.kind = ASCII_KEYSTROKE_EVENT;
+               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;
              }
-           else
+
+#if USE_MAC_TSM
+           if (inev.kind != NO_EVENT)
+             break;
 #endif
-             if (keycode_to_xkeysym (keycode, &xkeysym))
-               {
-                 inev.code = 0xff00 | xkeysym;
-                 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
-               }
-             else
-               {
-                 inev.code =
-                   backtranslate_modified_keycode(er.modifiers, keycode,
-                                                  er.message & charCodeMask);
-                 inev.kind = ASCII_KEYSTROKE_EVENT;
-               }
-         }
 
-#if USE_CARBON_EVENTS
-         inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-         inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+#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 <= 0x7f && keycode_to_xkeysym_table [keycode])
+             {
+               inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+               inev.code = 0xff00 | keycode_to_xkeysym_table [keycode];
+#ifdef MAC_OSX
+               if (modifiers & kEventKeyModifierFnMask
+                   && keycode <= 0x7f
+                   && fn_keycode_to_keycode_table[keycode] == keycode)
+                 modifiers &= ~kEventKeyModifierFnMask;
+#endif
+             }
+           else if (mapped_modifiers)
+             {
+               /* 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
+                      since shift is ignored in KCHR table
+                      translation when option or command is pressed.
+                      It also does not translate correctly
+                      control-shift chars like C-% so mask off shift
+                      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;
+                   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;
+                     }
+                 }
+             }
+
+           if (inev.kind == NO_EVENT)
+             {
+               inev.kind = ASCII_KEYSTROKE_EVENT;
+               inev.code = er.message & charCodeMask;
+             }
+
+           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:
@@ -10158,6 +11074,7 @@ XTread_socket (sd, expected, hold_quit)
   }
 #endif
 
+  --handling_signal;
   UNBLOCK_INPUT;
   return count;
 }
@@ -10274,7 +11191,6 @@ void
 mac_initialize_display_info ()
 {
   struct mac_display_info *dpyinfo = &one_mac_display_info;
-  GDHandle main_device_handle;
 
   bzero (dpyinfo, sizeof (*dpyinfo));
 
@@ -10290,37 +11206,29 @@ mac_initialize_display_info ()
   strcpy (dpyinfo->mac_id_name, "Mac Display");
 #endif
 
-  main_device_handle = LMGetMainDevice();
-
   dpyinfo->reference_count = 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,
-     but this may not be what is actually used.  Mac OSX can do better.
-     CGMainDisplayID is only available on OSX 10.2 and higher, but the
-     header for CGGetActiveDisplayList says that the first display returned
-     is the active one, so we use that.  */
+     but this may not be what is actually used.  Mac OSX can do better.  */
+  dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
+  dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
+  dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
+  dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
+#else
   {
-    CGDirectDisplayID disp_id[1];
-    CGDisplayCount disp_count;
-    CGDisplayErr error_code;
+    GDHandle main_device_handle = LMGetMainDevice();
 
-    error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
-    if (error_code != 0)
-      error ("No display found, CGGetActiveDisplayList error %d", error_code);
-
-    dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
+    dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
+    for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
+      if (HasDepth (main_device_handle, dpyinfo->n_planes,
+                   gdDevType, dpyinfo->color_p))
+       break;
+    dpyinfo->height = (**main_device_handle).gdRect.bottom;
+    dpyinfo->width = (**main_device_handle).gdRect.right;
   }
-#else
-  for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
-    if (HasDepth (main_device_handle, dpyinfo->n_planes,
-                 gdDevType, dpyinfo->color_p))
-      break;
 #endif
-  dpyinfo->height = (**main_device_handle).gdRect.bottom;
-  dpyinfo->width = (**main_device_handle).gdRect.right;
   dpyinfo->grabbed = 0;
   dpyinfo->root_window = NULL;
   dpyinfo->image_cache = make_image_cache ();
@@ -10336,7 +11244,7 @@ mac_initialize_display_info ()
 
 static XrmDatabase
 mac_make_rdb (xrm_option)
-     char *xrm_option;
+     const char *xrm_option;
 {
   XrmDatabase database;
 
@@ -10435,11 +11343,14 @@ x_delete_display (dpyinfo)
        xfree (dpyinfo->font_table[i].name);
       }
 
-  if (dpyinfo->font_table->font_encoder)
-    xfree (dpyinfo->font_table->font_encoder);
-
-  xfree (dpyinfo->font_table);
-  xfree (dpyinfo->mac_id_name);
+  if (dpyinfo->font_table)
+    {
+      if (dpyinfo->font_table->font_encoder)
+       xfree (dpyinfo->font_table->font_encoder);
+      xfree (dpyinfo->font_table);
+    }
+  if (dpyinfo->mac_id_name)
+    xfree (dpyinfo->mac_id_name);
 
   if (x_display_list == 0)
     {
@@ -10456,7 +11367,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)
@@ -10527,7 +11437,7 @@ static void
 init_menu_bar ()
 {
 #ifdef MAC_OSX
-  OSErr err;
+  OSStatus err;
   MenuRef menu;
   MenuItemIndex menu_index;
 
@@ -10555,6 +11465,20 @@ init_menu_bar ()
 #endif
 }
 
+#if USE_MAC_TSM
+static void
+init_tsm ()
+{
+#ifdef MAC_OSX
+  static InterfaceTypeList types = {kUnicodeDocument};
+#else
+  static InterfaceTypeList types = {kTextService};
+#endif
+
+  NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
+                 &tsm_document_id, 0);
+}
+#endif
 
 /* Set up use of X before we make the first connection.  */
 
@@ -10578,8 +11502,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,
@@ -10644,15 +11573,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;
 }
 
@@ -10680,12 +11620,26 @@ syms_of_macterm ()
   Fput (Qsuper,   Qmodifier_value, make_number (super_modifier));
 
 #if USE_CARBON_EVENTS
-  Qhicommand   = intern ("hicommand");    staticpro (&Qhicommand);
+  Qhi_command   = intern ("hi-command");    staticpro (&Qhi_command);
 #ifdef MAC_OSX
-  Qservices    = intern ("services");    staticpro (&Qservices);
+  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
@@ -10707,6 +11661,14 @@ syms_of_macterm ()
 #if USE_ATSUI
   staticpro (&atsu_font_id_hash);
   atsu_font_id_hash = Qnil;
+
+  staticpro (&fm_style_face_attributes_alist);
+  fm_style_face_attributes_alist = Qnil;
+#endif
+
+#if USE_MAC_TSM
+  staticpro (&saved_ts_script_language_on_focus);
+  saved_ts_script_language_on_focus = Qnil;
 #endif
 
   /* We don't yet support this, but defining this here avoids whining
@@ -10721,8 +11683,16 @@ to 4.1, set this to nil.
 NOTE: Not supported on Mac yet.  */);
   x_use_underline_position_properties = 0;
 
+  DEFVAR_BOOL ("x-underline-at-descent-line",
+              &x_underline_at_descent_line,
+     doc: /* *Non-nil means to draw the underline at the same place as the descent line.
+nil means to draw the underline according to the value of the variable
+`x-use-underline-position-properties', which is usually at the baseline
+level.  The default value is nil.  */);
+  x_underline_at_descent_line = 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
@@ -10776,32 +11746,36 @@ mouse-3 and the command-key will register for mouse-2.  */);
 
 #if USE_CARBON_EVENTS
   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.
+    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_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.  */);
+    doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox.  */);
   mac_pass_command_to_system = 1;
 
   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.  */);
+    doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox.  */);
   mac_pass_control_to_system = 1;
 
 #endif
 
   DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
-   doc: /* *If non-nil, allow anti-aliasing.
+    doc: /* *If non-nil, allow anti-aliasing.
 The text will be rendered using Core Graphics text rendering which
 may anti-alias the text.  */);
+#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 of Emacs character sets vs text encodings and coding systems.
+    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)
@@ -10812,6 +11786,30 @@ 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.  */);
+  Vmac_atsu_font_table =
+    make_hash_table (Qeql, 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;
+
+  DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
+    doc: /* *How to change Mac TSM script/language when a frame gets focus.
+If the value is t, the input script and language are restored to those
+used in the last focus frame.  If the value is a pair of integers, the
+input script and language codes, which are defined in the Script
+Manager, are set to its car and cdr parts, respectively.  Otherwise,
+Emacs doesn't set them and thus follows the system default behavior.  */);
+  Vmac_ts_script_language_on_focus = Qnil;
+#endif
 }
 
 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b