]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
Merge from emacs--rel--22
[gnu-emacs] / src / macterm.c
index 985421b12c5d4781b063b64c77f515f9bca9c66e..906f946388c713bf23e6d2a60f9e1cc91f47579b 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of GUI terminal on the Mac OS.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006 Free Software Foundation, Inc.
+                 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -35,12 +35,7 @@ Boston, MA 02110-1301, USA.  */
 #include <alloca.h>
 #endif
 
-#if TARGET_API_MAC_CARBON
-/* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
-   obtain events from the event queue.  If set to 0, WaitNextEvent is
-   used instead.  */
-#define USE_CARBON_EVENTS 1
-#else /* not TARGET_API_MAC_CARBON */
+#if !TARGET_API_MAC_CARBON
 #include <Quickdraw.h>
 #include <ToolUtils.h>
 #include <Sound.h>
@@ -52,6 +47,7 @@ Boston, MA 02110-1301, USA.  */
 #include <LowMem.h>
 #include <Controls.h>
 #include <Windows.h>
+#include <Displays.h>
 #if defined (__MRC__) || (__MSL__ >= 0x6000)
 #include <ControlDefinitions.h>
 #endif
@@ -77,7 +73,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"
@@ -109,6 +104,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.  */
 
@@ -197,6 +196,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;
@@ -215,7 +216,6 @@ QDGlobals qd;  /* QuickDraw global information structure.  */
 
 struct mac_display_info *mac_display_info_for_display (Display *);
 static void x_update_window_end P_ ((struct window *, int, int));
-static int x_io_error_quitter P_ ((Display *));
 int x_catch_errors P_ ((Display *));
 void x_uncatch_errors P_ ((Display *, int));
 void x_lower_frame P_ ((struct frame *));
@@ -240,7 +240,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 *));
@@ -257,22 +258,161 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            Lisp_Object *, Lisp_Object *,
                                            unsigned long *));
 
-static int is_emacs_window P_ ((WindowPtr));
+static int is_emacs_window P_ ((WindowRef));
 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 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)
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  do {                                                                \
+    if (CGColorGetTypeID != NULL)                                     \
+      CGContextSetFillColorWithColor (context, cg_color);             \
+    else                                                              \
+      CG_SET_FILL_COLOR (context, color);                             \
+  } while (0)
+#else
+#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  CGContextSetFillColorWithColor (context, cg_color)
+#endif
+#else
+#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  CG_SET_FILL_COLOR (context, color)
+#endif
+#define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc)              \
+  CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground,        \
+                                       (gc)->cg_fore_color)
+#define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc)              \
+  CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background,        \
+                                       (gc)->cg_back_color)
+
+
+#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 && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  do {                                                                \
+    if (CGColorGetTypeID != NULL)                                     \
+      CGContextSetStrokeColorWithColor (context, cg_color);           \
+    else                                                              \
+      CG_SET_STROKE_COLOR (context, color);                           \
+  } while (0)
+#else
+#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  CGContextSetStrokeColorWithColor (context, cg_color)
+#endif
+#else
+#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \
+  CG_SET_STROKE_COLOR (context, color)
+#endif
+#define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \
+  CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \
+                                         (gc)->cg_fore_color)
+
+#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 CGColorSpaceRef mac_cg_color_space_rgb;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+static CGColorRef mac_cg_color_black;
+#endif
+
+static void
+init_cg_color ()
+{
+  mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB ();
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  /* Don't check the availability of CGColorCreate; this symbol is
+     defined even in Mac OS X 10.1.  */
+  if (CGColorGetTypeID != NULL)
+#endif
+    {
+      float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+      mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba);
+    }
+#endif
+}
+
+static CGContextRef
+mac_begin_cg_clip (f, gc)
+     struct frame *f;
+     GC gc;
+{
+  CGContextRef context = FRAME_CG_CONTEXT (f);
+
+  if (!context)
+    {
+      QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
+      FRAME_CG_CONTEXT (f) = context;
+    }
+
+  CGContextSaveGState (context);
+  CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
+  CGContextScaleCTM (context, 1, -1);
+  if (gc && gc->n_clip_rects)
+    CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+
+  return context;
+}
+
+static void
+mac_end_cg_clip (f)
+     struct frame *f;
+{
+  CGContextRestoreGState (FRAME_CG_CONTEXT (f));
+}
+
+void
+mac_prepare_for_quickdraw (f)
+     struct frame *f;
+{
+  if (f == NULL)
+    {
+      Lisp_Object rest, frame;
+      FOR_EACH_FRAME (rest, frame)
+       if (FRAME_MAC_P (XFRAME (frame)))
+         mac_prepare_for_quickdraw (XFRAME (frame));
+    }
+  else
+    {
+      CGContextRef context = FRAME_CG_CONTEXT (f);
+
+      if (context)
+       {
+         CGContextSynchronize (context);
+         QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
+                         &FRAME_CG_CONTEXT (f));
+       }
+    }
+}
+#endif
+
 static RgnHandle saved_port_clip_region = NULL;
 
 static void
-mac_begin_clip (gc)
+mac_begin_clip (f, gc)
+     struct frame *f;
      GC gc;
 {
   static RgnHandle new_region = NULL;
@@ -282,6 +422,11 @@ mac_begin_clip (gc)
   if (new_region == NULL)
     new_region = NewRgn ();
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+
   if (gc->n_clip_rects)
     {
       GetClip (saved_port_clip_region);
@@ -301,15 +446,6 @@ mac_end_clip (gc)
 
 /* X display function emulation */
 
-void
-XFreePixmap (display, pixmap)
-     Display *display;         /* not used */
-     Pixmap pixmap;
-{
-  DisposeGWorld (pixmap);
-}
-
-
 /* Mac version of XDrawLine.  */
 
 static void
@@ -318,18 +454,51 @@ mac_draw_line (f, gc, x1, y1, x2, y2)
      GC gc;
      int x1, y1, x2, y2;
 {
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+#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_WITH_GC_FOREGROUND (context, gc);
+  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--;
+    }
 
+  mac_begin_clip (f, gc);
   RGBForeColor (GC_FORE_COLOR (gc));
-
-  mac_begin_clip (gc);
   MoveTo (x1, y1);
   LineTo (x2, y2);
   mac_end_clip (gc);
+#endif
 }
 
+/* Mac version of XDrawLine (to Pixmap).  */
+
 void
-mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
+XDrawLine (display, p, gc, x1, y1, x2, y2)
      Display *display;
      Pixmap p;
      GC gc;
@@ -338,6 +507,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);
 
@@ -359,18 +543,27 @@ mac_erase_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
-  Rect r;
-
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
-  RGBBackColor (GC_BACK_COLOR (gc));
-  SetRect (&r, x, y, x + width, y + height);
+#if USE_CG_DRAWING
+    {
+      CGContextRef context;
 
-  mac_begin_clip (gc);
-  EraseRect (&r);
-  mac_end_clip (gc);
+      context = mac_begin_cg_clip (f, gc);
+      CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
+      CGContextFillRect (context, CGRectMake (x, y, width, height));
+      mac_end_cg_clip (f);
+    }
+#else
+    {
+      Rect r;
 
-  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+      mac_begin_clip (f, gc);
+      RGBBackColor (GC_BACK_COLOR (gc));
+      SetRect (&r, x, y, x + width, y + height);
+      EraseRect (&r);
+      RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+      mac_end_clip (gc);
+    }
+#endif
 }
 
 
@@ -391,6 +584,18 @@ 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_WITH_GC_BACKGROUND (context, gc);
+    CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
+                                           FRAME_PIXEL_HEIGHT (f)));
+    mac_end_cg_clip (f);
+  }
+#else  /* !USE_CG_DRAWING */
   SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
@@ -405,11 +610,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_WITH_GC_BACKGROUND (context, gc);
+      CGContextFillRect (context, dest_rect);
+    }
+  CGContextClipToRect (context, dest_rect);
+  CGContextScaleCTM (context, 1, -1);
+  CGContextTranslateCTM (context, 0, -port_height);
+  if (CGImageIsMask (image))
+    CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
+  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;
@@ -425,13 +669,10 @@ mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
   bitmap.baseAddr = (char *)bits;
   SetRect (&(bitmap.bounds), 0, 0, width, height);
 
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
+  mac_begin_clip (f, gc);
   RGBForeColor (GC_FORE_COLOR (gc));
   RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
-
-  mac_begin_clip (gc);
 #if TARGET_API_MAC_CARBON
   {
     CGrafPtr port;
@@ -446,10 +687,10 @@ 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);
-
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+  mac_end_clip (gc);
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCreateBitmapFromBitmapData.  */
@@ -460,7 +701,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 */
@@ -480,7 +721,7 @@ mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
          /* Bitswap XBM bytes to match how Mac does things.  */
          unsigned char c = *bits++;
          *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
-                                | (swap_nibble[(c>>4) & 0xf]));;
+                                | (swap_nibble[(c>>4) & 0xf]));
        }
     }
 
@@ -498,8 +739,8 @@ mac_free_bitmap (bitmap)
 
 Pixmap
 XCreatePixmap (display, w, width, height, depth)
-     Display *display;         /* not used */
-     WindowPtr w;
+     Display *display;
+     WindowRef w;
      unsigned int width, height;
      unsigned int depth;
 {
@@ -510,7 +751,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;
@@ -519,8 +768,8 @@ XCreatePixmap (display, w, width, height, depth)
 
 Pixmap
 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
-     Display *display;         /* not used */
-     WindowPtr w;
+     Display *display;
+     WindowRef w;
      char *data;
      unsigned int width, height;
      unsigned long fg, bg;
@@ -530,7 +779,7 @@ XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
   BitMap bitmap;
   CGrafPtr old_port;
   GDHandle old_gdh;
-  static GC gc = NULL;         /* not reentrant */
+  static GC gc = NULL;
 
   if (gc == NULL)
     gc = XCreateGC (display, w, 0, NULL);
@@ -562,6 +811,15 @@ XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
 }
 
 
+void
+XFreePixmap (display, pixmap)
+     Display *display;
+     Pixmap pixmap;
+{
+  DisposeGWorld (pixmap);
+}
+
+
 /* Mac replacement for XFillRectangle.  */
 
 static void
@@ -571,16 +829,22 @@ mac_fill_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
-  Rect r;
+#if USE_CG_DRAWING
+  CGContextRef context;
 
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
+  Rect r;
 
+  mac_begin_clip (f, gc);
   RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
-
-  mac_begin_clip (gc);
   PaintRect (&r); /* using foreground color of gc */
   mac_end_clip (gc);
+#endif
 }
 
 
@@ -593,16 +857,42 @@ mac_draw_rectangle (f, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
-  Rect r;
+#if USE_CG_DRAWING
+  CGContextRef context;
 
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
+  CGContextStrokeRect (context,
+                      CGRectMake (x + 0.5f, y + 0.5f, width, height));
+  mac_end_cg_clip (f);
+#else
+  Rect r;
 
+  mac_begin_clip (f, gc);
   RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width + 1, y + height + 1);
-
-  mac_begin_clip (gc);
   FrameRect (&r); /* using foreground color of gc */
   mac_end_clip (gc);
+#endif
+}
+
+
+static void
+mac_invert_rectangle (f, x, y, width, height)
+     struct frame *f;
+     int x, y;
+     unsigned int 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);
+
+  InvertRect (&r);
 }
 
 
@@ -615,13 +905,13 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
      ATSUTextLayout *text_layout;
 {
   OSStatus err;
-  static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */
+  static ATSUTextLayout saved_text_layout = NULL;
 
   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
@@ -630,7 +920,7 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
        kATSLineIsDisplayOnly | kATSLineFractDisable
 #endif
        ;
-      ATSUAttributeValuePtr values[] = {&line_layout};
+      static const ATSUAttributeValuePtr values[] = {&line_layout};
 
       err = ATSUCreateTextLayoutWithTextPtr (text,
                                             kATSUFromTextBeginning,
@@ -642,7 +932,6 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
        err = ATSUSetLayoutControls (saved_text_layout,
                                     sizeof (tags) / sizeof (tags[0]),
                                     tags, sizes, values);
-      /* XXX: Should we do this? */
       if (err == noErr)
        err = ATSUSetTransientFontMatching (saved_text_layout, true);
     }
@@ -661,250 +950,254 @@ atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
     *text_layout = saved_text_layout;
   return err;
 }
-#endif
-
-
-static void
-mac_invert_rectangle (f, x, y, width, height)
-     struct frame *f;
-     int x, y;
-     unsigned int width, height;
-{
-  Rect r;
-
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
-  SetRect (&r, x, y, x + width, y + height);
-
-  InvertRect (&r);
-}
 
 
 static void
-mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, bytes_per_char)
+mac_draw_image_string_atsui (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, bg_width, bytes_per_char;
+     int nchars, bg_width, overstrike_p, bytes_per_char;
 {
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
-#if USE_ATSUI
-  if (GC_FONT (gc)->mac_style)
-    {
-      OSErr err;
-      ATSUTextLayout text_layout;
+  OSStatus err;
+  ATSUTextLayout text_layout;
 
-      xassert (bytes_per_char == 2);
+  xassert (bytes_per_char == 2);
 
 #ifndef WORDS_BIG_ENDIAN
-      {
-       int i;
-       UniChar *text = (UniChar *)buf;
+  {
+    int i;
+    UniChar *text = (UniChar *)buf;
 
-       for (i = 0; i < nchars; i++)
-         text[i] = EndianU16_BtoN (text[i]);
-      }
+    for (i = 0; i < nchars; i++)
+      text[i] = EndianU16_BtoN (text[i]);
+  }
 #endif
-      err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
-                                               nchars,
-                                               GC_FONT (gc)->mac_style,
-                                               &text_layout);
-      if (err != noErr)
-       return;
+  err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
+                                           nchars,
+                                           GC_FONT (gc)->mac_style,
+                                           &text_layout);
+  if (err != noErr)
+    return;
 #ifdef MAC_OSX
-      if (!mac_use_core_graphics)
-       {
+  if (!mac_use_core_graphics)
+    {
 #endif
-         mac_begin_clip (gc);
-         RGBForeColor (GC_FORE_COLOR (gc));
-         if (bg_width)
-           {
-             Rect r;
+      mac_begin_clip (f, 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);
+         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);
-#ifdef MAC_OSX
        }
-      else
+      mac_end_clip (gc);
+#ifdef MAC_OSX
+    }
+  else
+    {
+      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
+      CGrafPtr port;
+
+      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);
-         if (gc->n_clip_rects || bg_width)
+         CGContextTranslateCTM (context, 0, port_height);
+         CGContextScaleCTM (context, 1, -1);
+         if (gc->n_clip_rects)
+           CGContextClipToRects (context, gc->clip_rects,
+                                 gc->n_clip_rects);
+#endif
+         if (bg_width)
            {
-             CGContextTranslateCTM (context, 0, port_height);
-             CGContextScaleCTM (context, 1, -1);
-             if (gc->n_clip_rects)
-               CGContextClipToRects (context, gc->clip_rects,
-                                     gc->n_clip_rects);
-             if (bg_width)
-               {
-                 CGContextSetRGBFillColor
-                   (context,
-                    RED_FROM_ULONG (gc->xgcv.background) / 255.0f,
-                    GREEN_FROM_ULONG (gc->xgcv.background) / 255.0f,
-                    BLUE_FROM_ULONG (gc->xgcv.background) / 255.0f,
-                    1.0);
-                 CGContextFillRect
-                   (context,
-                    CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
-                                bg_width, FONT_HEIGHT (GC_FONT (gc))));
-               }
-             CGContextScaleCTM (context, 1, -1);
-             CGContextTranslateCTM (context, 0, -port_height);
+             CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
+             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.0f,
-            GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
-            BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
-            1.0);
-         err = ATSUSetLayoutControls (text_layout,
-                                      sizeof (tags) / sizeof (tags[0]),
-                                      tags, sizes, values);
-         if (err == noErr)
+         CGContextScaleCTM (context, 1, -1);
+         CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
+       }
+#endif
+      CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
+      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);
+                         Long2Fix (x + 1), Long2Fix (port_height - y));
+       }
+#if USE_CG_DRAWING
+      mac_end_cg_clip (f);
+      context = NULL;
+#else
+      CGContextSynchronize (context);
+      QDEndCGContext (port, &context);
+#endif
 #if 0
-         /* This doesn't work on Mac OS X 10.1.  */
-         ATSUClearLayoutControls (text_layout,
-                                  sizeof (tags) / sizeof (tags[0]), tags);
+      /* 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);
+      ATSUSetLayoutControls (text_layout,
+                            sizeof (tags) / sizeof (tags[0]),
+                            tags, sizes, values);
 #endif
-       }
-#endif /* MAC_OSX */
     }
-  else
+#endif /* MAC_OSX */
+}
 #endif /* USE_ATSUI */
-    {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-      UInt32 savedFlags;
 
-      if (mac_use_core_graphics)
-       savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
+
+static void
+mac_draw_image_string_qd (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, bg_width, overstrike_p, bytes_per_char;
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+  UInt32 savedFlags;
 #endif
-      mac_begin_clip (gc);
-      RGBForeColor (GC_FORE_COLOR (gc));
+
+  mac_begin_clip (f, gc);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+  if (mac_use_core_graphics)
+    savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
+#endif
+  RGBForeColor (GC_FORE_COLOR (gc));
 #ifdef MAC_OS8
-      if (bg_width)
-       {
-         RGBBackColor (GC_BACK_COLOR (gc));
-         TextMode (srcCopy);
-       }
-      else
-       TextMode (srcOr);
+  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;
+  /* 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);
+      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);
+  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 (bg_width)
+    RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+  mac_end_clip (gc);
 
 #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.  */
-
-static void
-mac_draw_string (f, gc, x, y, buf, nchars)
+static INLINE void
+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;
-{
-  mac_draw_string_common (f, gc, x, y, buf, nchars, 0, 1);
-}
-
-
-/* Mac replacement for XDrawString16. */
-
-static void
-mac_draw_string_16 (f, gc, x, y, buf, nchars)
-     struct frame *f;
-     GC gc;
-     int x, y;
-     XChar2b *buf;
-     int nchars;
+     int nchars, bg_width, overstrike_p, bytes_per_char;
 {
-  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, 0, 2);
+#if USE_ATSUI
+  if (GC_FONT (gc)->mac_style)
+    mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
+                                overstrike_p, bytes_per_char);
+  else
+#endif /* USE_ATSUI */
+    mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
+                             overstrike_p, bytes_per_char);
 }
 
 
 /* Mac replacement for XDrawImageString.  */
 
 static void
-mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width)
+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, bg_width;
+     int nchars, bg_width, overstrike_p;
 {
-  mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, 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_image_string_16 (f, gc, x, y, buf, nchars, bg_width)
+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, bg_width;
+     int nchars, bg_width, overstrike_p;
 {
-  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width, 2);
+  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
+                         overstrike_p, 2);
 }
 
 
@@ -913,7 +1206,7 @@ mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width)
    the font of the current graphics port.  If CG_GLYPH is not NULL,
    *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained.  */
 
-static OSErr
+static OSStatus
 mac_query_char_extents (style, c,
                        font_ascent_return, font_descent_return,
                        overall_return, cg_glyph)
@@ -931,7 +1224,7 @@ mac_query_char_extents (style, c,
      void *cg_glyph;
 #endif
 {
-  OSErr err = noErr;
+  OSStatus err = noErr;
   int width;
   Rect char_bounds;
 
@@ -942,7 +1235,8 @@ mac_query_char_extents (style, c,
       UniChar ch = c;
 
       err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
-      if (err == noErr)
+      if (err == noErr
+         && (font_ascent_return || font_descent_return || overall_return))
        {
          ATSTrapezoid glyph_bounds;
 
@@ -977,7 +1271,7 @@ mac_query_char_extents (style, c,
 #if USE_CG_TEXT_DRAWING
          if (err == noErr && cg_glyph)
            {
-             OSErr err1;
+             OSStatus err1;
              ATSUGlyphInfoArray glyph_info_array;
              ByteCount count = sizeof (ATSUGlyphInfoArray);
 
@@ -987,7 +1281,12 @@ mac_query_char_extents (style, c,
                err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
                                         kATSUToTextEnd, &count,
                                         &glyph_info_array);
-             if (err1 == noErr)
+             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;
@@ -1078,14 +1377,13 @@ init_cg_text_anti_aliasing_threshold ()
 }
 
 static int
-mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width)
+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, bg_width;
+     int nchars, bg_width, overstrike_p;
 {
-  CGrafPtr port;
   float port_height, gx, gy;
   int i;
   CGContextRef context;
@@ -1095,7 +1393,6 @@ mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width)
   if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
     return 0;
 
-  port = GetWindowPort (FRAME_MAC_WINDOW (f));
   port_height = FRAME_PIXEL_HEIGHT (f);
   gx = x;
   gy = port_height - y;
@@ -1113,21 +1410,20 @@ mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width)
       buf++;
     }
 
-  QDBeginCGContext (port, &context);
+#if USE_CG_DRAWING
+  context = mac_begin_cg_clip (f, gc);
+#else
+  QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
   if (gc->n_clip_rects || bg_width)
     {
       CGContextTranslateCTM (context, 0, port_height);
       CGContextScaleCTM (context, 1, -1);
       if (gc->n_clip_rects)
        CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+#endif
       if (bg_width)
        {
-         CGContextSetRGBFillColor
-           (context,
-            RED_FROM_ULONG (gc->xgcv.background) / 255.0f,
-            GREEN_FROM_ULONG (gc->xgcv.background) / 255.0f,
-            BLUE_FROM_ULONG (gc->xgcv.background) / 255.0f,
-            1.0);
+         CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
          CGContextFillRect
            (context,
             CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
@@ -1135,34 +1431,55 @@ mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width)
        }
       CGContextScaleCTM (context, 1, -1);
       CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
     }
-  CGContextSetRGBFillColor (context,
-                           RED_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
-                           GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
-                           BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0f,
-                           1.0);
+#endif
+  CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
   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
     {
-      CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
-      gx += advances[i].width;
+      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                  /* CGContextShowGlyphsWithAdvances == NULL */
+#endif
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030  */
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+    {
+      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);
+  QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
+#endif
 
   return 1;
 }
 #endif
 
 
+#if !USE_CG_DRAWING
 /* Mac replacement for XCopyArea: dest must be window.  */
 
 static void
@@ -1176,7 +1493,7 @@ mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
 {
   Rect src_r, dest_r;
 
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+  mac_begin_clip (f, gc);
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -1184,7 +1501,6 @@ mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
   ForeColor (blackColor);
   BackColor (whiteColor);
 
-  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
 #if TARGET_API_MAC_CARBON
   {
@@ -1202,9 +1518,10 @@ 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);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+
+  mac_end_clip (gc);
 }
 
 
@@ -1220,7 +1537,7 @@ mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
 {
   Rect src_r, dest_r;
 
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
+  mac_begin_clip (f, gc);
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -1228,7 +1545,6 @@ mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
   ForeColor (blackColor);
   BackColor (whiteColor);
 
-  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
   LockPixels (GetGWorldPixMap (mask));
 #if TARGET_API_MAC_CARBON
@@ -1248,10 +1564,12 @@ 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);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+
+  mac_end_clip (gc);
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCopyArea: used only for scrolling.  */
@@ -1269,15 +1587,18 @@ 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);
   DisposeRgn (dummy);
 #else /* not TARGET_API_MAC_CARBON */
   Rect src_r, dest_r;
-  WindowPtr w = FRAME_MAC_WINDOW (f);
+  WindowRef w = FRAME_MAC_WINDOW (f);
 
-  SetPort (w);
+  mac_begin_clip (f, gc);
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -1286,11 +1607,11 @@ 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);
   CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
-  mac_end_clip (gc);
 
   RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+
+  mac_end_clip (gc);
 #endif /* not TARGET_API_MAC_CARBON */
 }
 
@@ -1316,19 +1637,26 @@ XChangeGC (display, gc, mask, xgcv)
 /* Mac replacement for XCreateGC.  */
 
 GC
-XCreateGC (display, window, mask, xgcv)
+XCreateGC (display, d, mask, xgcv)
      Display *display;
-     Window window;
+     void *d;
      unsigned long mask;
      XGCValues *xgcv;
 {
   GC gc = xmalloc (sizeof (*gc));
 
-  if (gc)
+  bzero (gc, sizeof (*gc));
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGColorGetTypeID != NULL)
+#endif
     {
-      bzero (gc, sizeof (*gc));
-      XChangeGC (display, gc, mask, xgcv);
+      gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
+      CGColorRetain (gc->cg_fore_color);
+      CGColorRetain (gc->cg_back_color);
     }
+#endif
+  XChangeGC (display, gc, mask, xgcv);
 
   return gc;
 }
@@ -1343,6 +1671,15 @@ XFreeGC (display, gc)
 {
   if (gc->clip_region)
     DisposeRgn (gc->clip_region);
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGColorGetTypeID != NULL)
+#endif
+    {
+      CGColorRelease (gc->cg_fore_color);
+      CGColorRelease (gc->cg_back_color);
+    }
+#endif
   xfree (gc);
 }
 
@@ -1379,6 +1716,29 @@ XSetForeground (display, gc, color)
       gc->fore_color.red = RED16_FROM_ULONG (color);
       gc->fore_color.green = GREEN16_FROM_ULONG (color);
       gc->fore_color.blue = BLUE16_FROM_ULONG (color);
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+      if (CGColorGetTypeID != NULL)
+#endif
+       {
+         CGColorRelease (gc->cg_fore_color);
+         if (color == 0)
+           {
+             gc->cg_fore_color = mac_cg_color_black;
+             CGColorRetain (gc->cg_fore_color);
+           }
+         else
+           {
+             float rgba[4];
+
+             rgba[0] = gc->fore_color.red / 65535.0f;
+             rgba[1] = gc->fore_color.green / 65535.0f;
+             rgba[2] = gc->fore_color.blue / 65535.0f;
+             rgba[3] = 1.0f;
+             gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
+           }
+       }
+#endif
     }
 }
 
@@ -1397,6 +1757,29 @@ XSetBackground (display, gc, color)
       gc->back_color.red = RED16_FROM_ULONG (color);
       gc->back_color.green = GREEN16_FROM_ULONG (color);
       gc->back_color.blue = BLUE16_FROM_ULONG (color);
+#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+      if (CGColorGetTypeID != NULL)
+#endif
+       {
+         CGColorRelease (gc->cg_back_color);
+         if (color == 0)
+           {
+             gc->cg_back_color = mac_cg_color_black;
+             CGColorRetain (gc->cg_back_color);
+           }
+         else
+           {
+             float rgba[4];
+
+             rgba[0] = gc->back_color.red / 65535.0f;
+             rgba[1] = gc->back_color.green / 65535.0f;
+             rgba[2] = gc->back_color.blue / 65535.0f;
+             rgba[3] = 1.0f;
+             gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
+           }
+       }
+#endif
     }
 }
 
@@ -1444,7 +1827,7 @@ mac_set_clip_rectangles (display, gc, rectangles, n)
          DisposeRgn (region);
        }
     }
-#if defined (MAC_OSX) && USE_ATSUI
+#if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
   for (i = 0; i < n; i++)
     {
       Rect *rect = rectangles + i;
@@ -1473,7 +1856,7 @@ mac_reset_clip_rectangles (display, gc)
 void
 XSetWindowBackground (display, w, color)
      Display *display;
-     WindowPtr w;
+     WindowRef w;
      unsigned long color;
 {
 #if !TARGET_API_MAC_CARBON
@@ -1511,14 +1894,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
@@ -1527,6 +1902,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
@@ -1545,18 +1923,16 @@ x_flush (f)
 
 #define XFlush(DISPLAY)        (void) 0
 
-\f
-/* Return the struct mac_display_info corresponding to DPY.  There's
-   only one.  */
-
-struct mac_display_info *
-mac_display_info_for_display (dpy)
-     Display *dpy;
+#if USE_CG_DRAWING
+static void
+mac_flush_display_optional (f)
+     struct frame *f;
 {
-  return &one_mac_display_info;
+  BLOCK_INPUT;
+  mac_prepare_for_quickdraw (f);
+  UNBLOCK_INPUT;
 }
-
-
+#endif
 \f
 /***********************************************************************
                    Starting and ending an update
@@ -1818,6 +2194,81 @@ x_draw_fringe_bitmap (w, row, p)
   Display *display = FRAME_MAC_DISPLAY (f);
   struct face *face = p->face;
   int rowY;
+  int overlay_p = p->overlay_p;
+
+#ifdef MAC_OSX
+  if (!overlay_p)
+    {
+      int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
+
+#if 0  /* MAC_TODO: stipple */
+      /* In case the same realized face is used for fringes and
+        for something displayed in the text (e.g. face `region' on
+        mono-displays, the fill style may have been changed to
+        FillSolid in x_draw_glyph_string_background.  */
+      if (face->stipple)
+       XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
+      else
+       XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
+#endif
+
+      /* If the fringe is adjacent to the left (right) scroll bar of a
+        leftmost (rightmost, respectively) window, then extend its
+        background to the gap between the fringe and the bar.  */
+      if ((WINDOW_LEFTMOST_P (w)
+          && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+         || (WINDOW_RIGHTMOST_P (w)
+             && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
+       {
+         int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
+
+         if (sb_width > 0)
+           {
+             int left = WINDOW_SCROLL_BAR_AREA_X (w);
+             int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
+                          * FRAME_COLUMN_WIDTH (f));
+
+             if (bx < 0
+                 && (left + width == p->x
+                     || p->x + p->wd == left))
+               {
+                 /* Bitmap fills the fringe and we need background
+                    extension.  */
+                 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+
+                 bx = p->x;
+                 nx = p->wd;
+                 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+                                                       row->y));
+                 ny = row->visible_height;
+               }
+
+             if (bx >= 0)
+               {
+                 if (left + width == bx)
+                   {
+                     bx = left + sb_width;
+                     nx += width - sb_width;
+                   }
+                 else if (bx + nx == left)
+                   nx += width - sb_width;
+               }
+           }
+       }
+
+      if (bx >= 0)
+       {
+         mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
+         /* The fringe background has already been filled.  */
+         overlay_p = 1;
+       }
+
+#if 0  /* MAC_TODO: stipple */
+      if (!face->stipple)
+       XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
+#endif
+    }
+#endif /* MAC_OSX */
 
   /* Must clip because of partially visible lines.  */
   rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
@@ -1836,6 +2287,7 @@ x_draw_fringe_bitmap (w, row, p)
   else
     x_clip_to_row (w, row, -1, face->gc);
 
+#ifndef MAC_OSX
   if (p->bx >= 0 && !p->overlay_p)
     {
 #if 0  /* MAC_TODO: stipple */
@@ -1856,10 +2308,14 @@ x_draw_fringe_bitmap (w, row, p)
        XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
 #endif
     }
+#endif /* !MAC_OSX */
 
-  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);
@@ -1868,14 +2324,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, 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, 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
@@ -1908,6 +2413,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.  */
 
@@ -1924,26 +2452,21 @@ x_per_char_metric (font, char2b)
 #if USE_ATSUI
   if (font->mac_style)
     {
-      XCharStructRow **row = font->bounds.rows + char2b->byte1;
+      XCharStruct **row = font->bounds.rows + char2b->byte1;
 
       if (*row == NULL)
        {
-         *row = xmalloc (sizeof (XCharStructRow));
-         if (*row)
-           bzero (*row, sizeof (XCharStructRow));
+         *row = xmalloc (sizeof (XCharStruct) * 0x100);
+         pcm_init (*row, 0x100);
        }
-      if (*row)
+      pcm = *row + char2b->byte2;
+      if (pcm_get_status (pcm) != PCM_VALID)
        {
-         pcm = (*row)->per_char + char2b->byte2;
-         if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2))
-           {
-             BLOCK_INPUT;
-             mac_query_char_extents (font->mac_style,
-                                     (char2b->byte1 << 8) + char2b->byte2,
-                                     NULL, NULL, pcm, NULL);
-             UNBLOCK_INPUT;
-             XCHARSTRUCTROW_SET_CHAR_VALID (*row, char2b->byte2);
-           }
+         BLOCK_INPUT;
+         mac_query_char_extents (font->mac_style,
+                                 (char2b->byte1 << 8) + char2b->byte2,
+                                 NULL, NULL, pcm, NULL);
+         UNBLOCK_INPUT;
        }
     }
   else
@@ -2006,7 +2529,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);
 }
 
@@ -2124,7 +2651,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,
@@ -2325,34 +2851,41 @@ static void
 mac_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-  if (s->cmp == NULL
-      && s->first_glyph->type == CHAR_GLYPH)
-    if (!s->two_byte_p
+  if (!(s->cmp == NULL
+       && s->first_glyph->type == CHAR_GLYPH))
+    return;
+
+  if (!s->two_byte_p
 #if USE_ATSUI
-       || s->font->mac_style
+      || s->font->mac_style
 #endif
-       )
-      {
-       XCharStruct cs;
+      )
+    {
+      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;
+      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_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);
+      TextFont (font->mac_fontnum);
+      TextSize (font->mac_fontsize);
+      TextFace (font->mac_fontface);
 
-       QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
+      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;
-      }
+      s->right_overhang = r.right > s->width ? r.right - s->width : 0;
+      s->left_overhang = r.left < 0 ? -r.left : 0;
+    }
 }
 
 
@@ -2476,15 +3009,18 @@ x_draw_glyph_string_foreground (s)
 #if USE_CG_TEXT_DRAWING
        if (!s->two_byte_p
            && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
-                                        s->char2b, s->nchars, bg_width))
+                                        s->char2b, s->nchars, bg_width,
+                                        s->face->overstrike))
          ;
        else
 #endif
          mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
-                                   s->char2b, s->nchars, bg_width);
+                                   s->char2b, s->nchars, bg_width,
+                                   s->face->overstrike);
       else
        mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
-                              char1b, s->nchars, bg_width);
+                              char1b, s->nchars, bg_width,
+                              s->face->overstrike);
     }
 }
 
@@ -2520,10 +3056,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);
     }
 }
 
@@ -2893,13 +3429,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)
@@ -2913,13 +3449,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);
 }
@@ -3047,15 +3583,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
@@ -3177,7 +3724,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;
 
@@ -3232,19 +3778,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))
            {
@@ -3271,8 +3826,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;
 }
@@ -3354,19 +3921,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);
            }
        }
@@ -3378,14 +3972,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);
            }
        }
@@ -3800,6 +4394,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);
@@ -3852,12 +4451,12 @@ 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;
 
-  frame = mac_window_to_frame ((WindowPtr) event->message);
+  frame = mac_window_to_frame ((WindowRef) event->message);
   if (! frame)
     return;
 
@@ -3923,142 +4522,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 *
@@ -4105,25 +4568,24 @@ note_mouse_movement (frame, pos)
   last_mouse_motion_position = *pos;
   XSETFRAME (last_mouse_motion_frame, frame);
 
+  if (frame == dpyinfo->mouse_face_mouse_frame
 #if TARGET_API_MAC_CARBON
-  if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
+      && !PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r))
 #else
-  if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
+      && !PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect)
 #endif
+      )
     {
-      if (frame == dpyinfo->mouse_face_mouse_frame)
-       /* This case corresponds to LeaveNotify in X11.  */
-       {
-         /* If we move outside the frame, then we're certainly no
-            longer on any text in the frame.  */
-         clear_mouse_face (dpyinfo);
-         dpyinfo->mouse_face_mouse_frame = 0;
-         if (!dpyinfo->grabbed)
-           rif->define_frame_cursor (frame,
-                                     frame->output_data.mac->nontext_cursor);
-       }
-      return 1;
+      /* This case corresponds to LeaveNotify in X11.  If we move
+        outside the frame, then we're certainly no longer on any text
+        in the frame.  */
+      clear_mouse_face (dpyinfo);
+      dpyinfo->mouse_face_mouse_frame = 0;
+      if (!dpyinfo->grabbed)
+       rif->define_frame_cursor (frame,
+                                 frame->output_data.mac->nontext_cursor);
     }
+
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
   if (frame != last_mouse_glyph_frame
       || !PtInRect (*pos, &last_mouse_glyph))
@@ -4234,8 +4696,14 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
             the frame are divided into.  */
          Point mouse_pos;
 
+#if TARGET_API_MAC_CARBON
+         GetGlobalMouse (&mouse_pos);
+         mouse_pos.h -= f1->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f1);
+         mouse_pos.v -= f1->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f1);
+#else
          SetPortWindowPort (FRAME_MAC_WINDOW (f1));
          GetMouse (&mouse_pos);
+#endif
          remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
                                &last_mouse_glyph);
          last_mouse_glyph_frame = f1;
@@ -4265,14 +4733,14 @@ 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 OSStatus get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
+static OSStatus get_control_part_bounds P_ ((ControlRef, ControlPartCode,
                                             Rect *));
 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
-                                          ControlPartCode,
+                                          ControlPartCode, Point,
                                           struct input_event *));
 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
                                             struct input_event *));
-static void x_scroll_bar_handle_drag P_ ((WindowPtr, struct scroll_bar *,
+static void x_scroll_bar_handle_drag P_ ((WindowRef, struct scroll_bar *,
                                          Point, struct input_event *));
 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
                                                int, int, int));
@@ -4293,35 +4761,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
@@ -4389,7 +4833,7 @@ construct_scroll_bar_click (bar, part, bufp)
 
 static OSStatus
 get_control_part_bounds (ch, part_code, rect)
-     ControlHandle ch;
+     ControlRef ch;
      ControlPartCode part_code;
      Rect *rect;
 {
@@ -4405,9 +4849,10 @@ get_control_part_bounds (ch, part_code, rect)
 }
 
 static void
-x_scroll_bar_handle_press (bar, part_code, bufp)
+x_scroll_bar_handle_press (bar, part_code, mouse_pos, bufp)
      struct scroll_bar *bar;
      ControlPartCode part_code;
+     Point mouse_pos;
      struct input_event *bufp;
 {
   int part = control_part_code_to_scroll_bar_part (part_code);
@@ -4418,12 +4863,20 @@ x_scroll_bar_handle_press (bar, part_code, bufp)
   if (part != scroll_bar_handle)
     {
       construct_scroll_bar_click (bar, part, bufp);
-      HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
+      HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
       set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
+      bar->dragging = Qnil;
+    }
+  else
+    {
+      Rect r;
+
+      get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
+                              kControlIndicatorPart, &r);
+      XSETINT (bar->dragging, - (mouse_pos.v - r.top) - 1);
     }
 
   last_scroll_bar_part = part;
-  bar->dragging = Qnil;
   tracked_scroll_bar = bar;
 }
 
@@ -4433,10 +4886,10 @@ x_scroll_bar_handle_release (bar, bufp)
      struct input_event *bufp;
 {
   if (last_scroll_bar_part != scroll_bar_handle
-      || !GC_NILP (bar->dragging))
+      || (INTEGERP (bar->dragging) && XINT (bar->dragging) >= 0))
     construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
 
-  HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
+  HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
   set_scroll_bar_timer (kEventDurationForever);
 
   last_scroll_bar_part = -1;
@@ -4446,28 +4899,26 @@ x_scroll_bar_handle_release (bar, bufp)
 
 static void
 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
-     WindowPtr win;
+     WindowRef win;
      struct scroll_bar *bar;
      Point mouse_pos;
      struct input_event *bufp;
 {
-  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+  ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
 
   if (last_scroll_bar_part == scroll_bar_handle)
     {
       int top, top_range;
       Rect r;
 
-      get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
+      get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar),
                               kControlIndicatorPart, &r);
 
-      if (GC_NILP (bar->dragging))
-       XSETINT (bar->dragging, mouse_pos.v - r.top);
+      if (INTEGERP (bar->dragging) && XINT (bar->dragging) < 0)
+       XSETINT (bar->dragging, - (XINT (bar->dragging) + 1));
 
       top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
-      top_range = (XINT (bar->track_height) - (r.bottom - r.top)) *
-       (1.0 + (float) GetControlViewSize (ch) / GetControl32BitMaximum (ch))
-       + .5;
+      top_range = XINT (bar->track_height) - XINT (bar->min_handle);
 
       if (top < 0)
        top = 0;
@@ -4508,13 +4959,13 @@ x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
        }
 
       if (unhilite_p)
-       HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
+       HiliteControl (SCROLL_BAR_CONTROL_REF (bar), 0);
       else if (part != last_scroll_bar_part
               || scroll_bar_timer_event_posted_p)
        {
          construct_scroll_bar_click (bar, part, bufp);
          last_scroll_bar_part = part;
-         HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
+         HiliteControl (SCROLL_BAR_CONTROL_REF (bar), part_code);
          set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
        }
     }
@@ -4528,19 +4979,22 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
      struct scroll_bar *bar;
      int portion, position, whole;
 {
-  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+  ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
   int value, viewsize, maximum;
 
   if (XINT (bar->track_height) == 0)
     return;
 
-  if (whole == 0)
+  if (whole <= portion)
     value = 0, viewsize = 1, maximum = 0;
   else
     {
-      value = position;
-      viewsize = portion;
-      maximum = max (0, whole - portion);
+      float scale;
+
+      maximum = XINT (bar->track_height) - XINT (bar->min_handle);
+      scale = (float) maximum / (whole - portion);
+      value = position * scale + 0.5f;
+      viewsize = (int) (portion * scale + 0.5f) + XINT (bar->min_handle);
     }
 
   BLOCK_INPUT;
@@ -4584,7 +5038,7 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
   struct scroll_bar *bar
     = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
   Rect r;
-  ControlHandle ch;
+  ControlRef ch;
 
   BLOCK_INPUT;
 
@@ -4593,9 +5047,12 @@ 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",
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
                   false,
 #else
                   width < disp_height,
@@ -4605,7 +5062,7 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
   ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
                   0, 0, 0, scrollBarProc, (long) bar);
 #endif
-  SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
+  SET_SCROLL_BAR_CONTROL_REF (bar, ch);
 
   XSETWINDOW (bar->window, w);
   XSETINT (bar->top, top);
@@ -4615,9 +5072,13 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
   XSETINT (bar->start, 0);
   XSETINT (bar->end, 0);
   bar->dragging = Qnil;
+#ifdef MAC_OSX
+  bar->fringe_extended_p = Qnil;
+#endif
 #ifdef USE_TOOLKIT_SCROLL_BARS
   bar->track_top = Qnil;
   bar->track_height = Qnil;
+  bar->min_handle = Qnil;
 #endif
 
   /* Add bar to its frame's list of scroll bars.  */
@@ -4654,7 +5115,7 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
      int rebuild;
 {
   int dragging = ! NILP (bar->dragging);
-  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+  ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
   int length = end - start;
@@ -4719,8 +5180,11 @@ 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));
+  DisposeControl (SCROLL_BAR_CONTROL_REF (bar));
 
   /* Disassociate this scroll bar from its window.  */
   XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
@@ -4743,6 +5207,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
   int window_y, window_height;
+#ifdef MAC_OSX
+  int fringe_extended_p;
+#endif
 
   /* Get window dimensions.  */
   window_box (w, -1, 0, &window_y, 0, &window_height);
@@ -4762,9 +5229,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
   /* Compute the left edge of the scroll bar.  */
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left;
+    sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
   else
-    sb_left = left + width - sb_width;
+    sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
 
   /* Adjustments according to Inside Macintosh to make it look nice */
   disp_top = top;
@@ -4785,11 +5252,29 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
     sb_left++;
 #endif
 
+#ifdef MAC_OSX
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+    fringe_extended_p = (WINDOW_LEFTMOST_P (w)
+                        && WINDOW_LEFT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_LEFT_MARGIN_COLS (w) == 0));
+  else
+    fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
+                        && WINDOW_RIGHT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
+#endif
+
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
     {
       BLOCK_INPUT;
-      mac_clear_area (f, left, top, width, height);
+#ifdef MAC_OSX
+      if (fringe_extended_p)
+       mac_clear_area (f, sb_left, top, sb_width, height);
+      else
+#endif
+       mac_clear_area (f, left, top, width, height);
       UNBLOCK_INPUT;
       bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
                                 disp_height);
@@ -4798,10 +5283,10 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   else
     {
       /* It may just need to be moved and resized.  */
-      ControlHandle ch;
+      ControlRef ch;
 
       bar = XSCROLL_BAR (w->vertical_scroll_bar);
-      ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+      ch = SCROLL_BAR_CONTROL_REF (bar);
 
       BLOCK_INPUT;
 
@@ -4809,12 +5294,24 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
       if (!(XINT (bar->left) == sb_left
            && XINT (bar->top) == top
            && XINT (bar->width) == sb_width
-           && XINT (bar->height) == height))
+           && XINT (bar->height) == height
+#ifdef MAC_OSX
+           && !NILP (bar->fringe_extended_p) == fringe_extended_p
+#endif
+           ))
        {
          /* Since toolkit scroll bars are smaller than the space reserved
             for them on the frame, we have to clear "under" them.  */
-         mac_clear_area (f, left, top, width, height);
+#ifdef MAC_OSX
+         if (fringe_extended_p)
+           mac_clear_area (f, sb_left, top, sb_width, height);
+         else
+#endif
+           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,
@@ -4832,49 +5329,62 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 #ifdef USE_TOOLKIT_SCROLL_BARS
          bar->track_top = Qnil;
          bar->track_height = Qnil;
+         bar->min_handle = Qnil;
 #endif
         }
 
       UNBLOCK_INPUT;
     }
 
+#ifdef MAC_OSX
+  bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
+#endif
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
   if (NILP (bar->track_top))
-    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;
+    {
+      if (sb_width >= disp_height
+#ifdef MAC_OSX
+         || sb_width < MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
+#endif
+         )
+       {
+         XSETINT (bar->track_top, 0);
+         XSETINT (bar->track_height, 0);
+         XSETINT (bar->min_handle, 0);
+       }
+      else
+       {
+         ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
+         Rect r0, r1;
 
-       BLOCK_INPUT;
+         BLOCK_INPUT;
 
-       SetControl32BitMinimum (ch, 0);
-       SetControl32BitMaximum (ch, 1);
-       SetControlViewSize (ch, 1);
+         SetControl32BitMinimum (ch, 0);
+         SetControl32BitMaximum (ch, 1 << 30);
+         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 << 30);
+         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);
+         XSETINT (bar->min_handle, r1.bottom - r1.top);
 
-       /* 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);
+         /* 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;
-      }
+         UNBLOCK_INPUT;
+       }
+    }
 
   x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
 #else /* not USE_TOOLKIT_SCROLL_BARS */
@@ -5014,7 +5524,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;
@@ -5122,19 +5632,24 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
      unsigned long *time;
 {
   struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
-  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+  ControlRef ch = SCROLL_BAR_CONTROL_REF (bar);
 #if TARGET_API_MAC_CARBON
-  WindowPtr wp = GetControlOwner (ch);
+  WindowRef wp = GetControlOwner (ch);
 #else
-  WindowPtr wp = (*ch)->contrlOwner;
+  WindowRef wp = (*ch)->contrlOwner;
 #endif
   Point mouse_pos;
   struct frame *f = mac_window_to_frame (wp);
   int win_y, top_range;
 
+#if TARGET_API_MAC_CARBON
+  GetGlobalMouse (&mouse_pos);
+  mouse_pos.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
+  mouse_pos.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
+#else
   SetPortWindowPort (wp);
-
   GetMouse (&mouse_pos);
+#endif
 
   win_y = mouse_pos.v - XINT (bar->top);
   top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
@@ -5188,103 +5703,635 @@ x_scroll_bar_clear (f)
 
 \f
 /***********************************************************************
-                            Text Cursor
+                              Tool-bars
  ***********************************************************************/
+#if USE_MAC_TOOLBAR
 
-/* Set clipping for output in glyph row ROW.  W is the window in which
-   we operate.  GC is the graphics context to set clipping in.
+/* In identifiers such as function/variable names, Emacs tool bar is
+   referred to as `tool_bar', and Carbon HIToolbar as `toolbar'.  */
 
-   ROW may be a text row or, e.g., a mode line.  Text rows must be
-   clipped to the interior of the window dedicated to text display,
-   mode lines must be clipped to the whole window.  */
+#define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
+#define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
+
+#define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
+#define TOOLBAR_ITEM_COMMAND_ID_P(id)                  \
+  (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
+#define TOOLBAR_ITEM_COMMAND_ID_VALUE(id)      \
+  ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
+#define TOOLBAR_ITEM_MAKE_COMMAND_ID(value)    \
+  ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
+
+static int mac_event_to_emacs_modifiers P_ ((EventRef));
+static void mac_handle_origin_change P_ ((struct frame *));
+static OSStatus mac_handle_toolbar_command_event P_ ((EventHandlerCallRef,
+                                                     EventRef, void *));
 
 static void
-x_clip_to_row (w, row, area, gc)
-     struct window *w;
-     struct glyph_row *row;
-     int area;
-     GC gc;
+mac_move_window_with_gravity (f, win_gravity, left, top)
+     struct frame *f;
+     int win_gravity;
+     short left, top;
 {
-  struct frame *f = XFRAME (WINDOW_FRAME (w));
-  Rect clip_rect;
-  int window_x, window_y, window_width;
+  Rect inner, outer;
 
-  window_box (w, area, &window_x, &window_y, &window_width, 0);
+  mac_get_window_bounds (f, &inner, &outer);
 
-  clip_rect.left = window_x;
-  clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
-  clip_rect.top = max (clip_rect.top, window_y);
-  clip_rect.right = clip_rect.left + window_width;
-  clip_rect.bottom = clip_rect.top + row->visible_height;
+  switch (win_gravity)
+    {
+    case NorthWestGravity:
+    case WestGravity:
+    case SouthWestGravity:
+      left += inner.left - outer.left;
+      break;
 
-  mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
-}
+    case NorthGravity:
+    case CenterGravity:
+    case SouthGravity:
+      left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
+      break;
 
+    case NorthEastGravity:
+    case EastGravity:
+    case SouthEastGravity:
+      left += inner.right - outer.right;
+      break;
+    }
 
-/* Draw a hollow box cursor on window W in glyph row ROW.  */
+  switch (win_gravity)
+    {
+    case NorthWestGravity:
+    case NorthGravity:
+    case NorthEastGravity:
+      top += inner.top - outer.top;
+      break;
+
+    case WestGravity:
+    case CenterGravity:
+    case EastGravity:
+      top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
+      break;
+
+    case SouthWestGravity:
+    case SouthGravity:
+    case SouthEastGravity:
+      top += inner.bottom - outer.bottom;
+      break;
+    }
+
+  MoveWindow (FRAME_MAC_WINDOW (f), left, top, false);
+}
 
 static void
-x_draw_hollow_cursor (w, row)
-     struct window *w;
-     struct glyph_row *row;
+mac_get_window_origin_with_gravity (f, win_gravity, left, top)
+     struct frame *f;
+     int win_gravity;
+     short *left, *top;
 {
-  struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-  Display *dpy = FRAME_MAC_DISPLAY (f);
-  int x, y, wd, h;
-  XGCValues xgcv;
-  struct glyph *cursor_glyph;
-  GC gc;
+  Rect inner, outer;
 
-  /* Get the glyph the cursor is on.  If we can't tell because
-     the current matrix is invalid or such, give up.  */
-  cursor_glyph = get_phys_cursor_glyph (w);
-  if (cursor_glyph == NULL)
-    return;
+  mac_get_window_bounds (f, &inner, &outer);
 
-  /* Compute frame-relative coordinates for phys cursor.  */
-  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
-  wd = w->phys_cursor_width;
+  switch (win_gravity)
+    {
+    case NorthWestGravity:
+    case WestGravity:
+    case SouthWestGravity:
+      *left = outer.left;
+      break;
 
-  /* The foreground of cursor_gc is typically the same as the normal
-     background color, which can cause the cursor box to be invisible.  */
-  xgcv.foreground = f->output_data.mac->cursor_pixel;
-  if (dpyinfo->scratch_cursor_gc)
-    XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
-  else
-    dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
-                                           GCForeground, &xgcv);
-  gc = dpyinfo->scratch_cursor_gc;
+    case NorthGravity:
+    case CenterGravity:
+    case SouthGravity:
+      *left = outer.left + ((outer.right - outer.left)
+                           - (inner.right - inner.left)) / 2;
+      break;
 
-  /* 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_reset_clip_rectangles (dpy, gc);
-}
+    case NorthEastGravity:
+    case EastGravity:
+    case SouthEastGravity:
+      *left = outer.right - (inner.right - inner.left);
+      break;
+    }
 
+  switch (win_gravity)
+    {
+    case NorthWestGravity:
+    case NorthGravity:
+    case NorthEastGravity:
+      *top = outer.top;
+      break;
 
-/* Draw a bar cursor on window W in glyph row ROW.
+    case WestGravity:
+    case CenterGravity:
+    case EastGravity:
+      *top = outer.top + ((outer.bottom - outer.top)
+                         - (inner.bottom - inner.top)) / 2;
+      break;
 
-   Implementation note: One would like to draw a bar cursor with an
-   angle equal to the one given by the font property XA_ITALIC_ANGLE.
-   Unfortunately, I didn't find a font yet that has this property set.
-   --gerd.  */
+    case SouthWestGravity:
+    case SouthGravity:
+    case SouthEastGravity:
+      *top = outer.bottom - (inner.bottom - inner.top);
+      break;
+    }
+}
 
-static void
-x_draw_bar_cursor (w, row, width, kind)
-     struct window *w;
-     struct glyph_row *row;
-     int width;
-     enum text_cursor_kinds kind;
+static OSStatus
+mac_handle_toolbar_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
 {
-  struct frame *f = XFRAME (w->frame);
-  struct glyph *cursor_glyph;
+  OSStatus err, result = eventNotHandledErr;
 
-  /* If cursor is out of bounds, don't draw garbage.  This can happen
-     in mini-buffer windows when switching between echo area glyphs
-     and mini-buffer.  */
-  cursor_glyph = get_phys_cursor_glyph (w);
+  switch (GetEventKind (event))
+    {
+    case kEventToolbarGetDefaultIdentifiers:
+      result = noErr;
+      break;
+
+    case kEventToolbarGetAllowedIdentifiers:
+      {
+       CFMutableArrayRef array;
+
+       GetEventParameter (event, kEventParamMutableArray,
+                          typeCFMutableArrayRef, NULL,
+                          sizeof (CFMutableArrayRef), NULL, &array);
+       CFArrayAppendValue (array, TOOLBAR_ICON_ITEM_IDENTIFIER);
+       result = noErr;
+      }
+      break;
+
+    case kEventToolbarCreateItemWithIdentifier:
+      {
+       CFStringRef identifier;
+       HIToolbarItemRef item = NULL;
+
+       GetEventParameter (event, kEventParamToolbarItemIdentifier,
+                          typeCFStringRef, NULL,
+                          sizeof (CFStringRef), NULL, &identifier);
+
+       if (CFStringCompare (identifier, TOOLBAR_ICON_ITEM_IDENTIFIER, 0)
+           == kCFCompareEqualTo)
+         HIToolbarItemCreate (identifier,
+                              kHIToolbarItemAllowDuplicates
+                              | kHIToolbarItemCantBeRemoved, &item);
+
+       if (item)
+         {
+           SetEventParameter (event, kEventParamToolbarItem,
+                              typeHIToolbarItemRef,
+                              sizeof (HIToolbarItemRef), &item);
+           result = noErr;
+         }
+      }
+      break;
+
+    default:
+      abort ();
+    }
+
+  return result;
+}
+
+static CGImageRef
+mac_image_spec_to_cg_image (f, image)
+     struct frame *f;
+     Lisp_Object image;
+{
+  if (!valid_image_p (image))
+    return NULL;
+  else
+    {
+      int img_id = lookup_image (f, image);
+      struct image *img = IMAGE_FROM_ID (f, img_id);
+
+      prepare_image_for_display (f, img);
+
+      return img->data.ptr_val;
+    }
+}
+
+/* Create a tool bar for frame F.  */
+
+static OSStatus
+mac_create_frame_tool_bar (f)
+     FRAME_PTR f;
+{
+  OSStatus err;
+  HIToolbarRef toolbar;
+
+  err = HIToolbarCreate (TOOLBAR_IDENTIFIER, kHIToolbarNoAttributes,
+                        &toolbar);
+  if (err == noErr)
+    {
+      static const EventTypeSpec specs[] =
+       {{kEventClassToolbar, kEventToolbarGetDefaultIdentifiers},
+        {kEventClassToolbar, kEventToolbarGetAllowedIdentifiers},
+        {kEventClassToolbar, kEventToolbarCreateItemWithIdentifier}};
+
+      err = InstallEventHandler (HIObjectGetEventTarget (toolbar),
+                                mac_handle_toolbar_event,
+                                GetEventTypeCount (specs), specs,
+                                f, NULL);
+    }
+
+  if (err == noErr)
+    err = HIToolbarSetDisplayMode (toolbar, kHIToolbarDisplayModeIconOnly);
+  if (err == noErr)
+    {
+      static const EventTypeSpec specs[] =
+       {{kEventClassCommand, kEventCommandProcess}};
+
+      err = InstallWindowEventHandler (FRAME_MAC_WINDOW (f),
+                                      mac_handle_toolbar_command_event,
+                                      GetEventTypeCount (specs),
+                                      specs, f, NULL);
+    }
+  if (err == noErr)
+    err = SetWindowToolbar (FRAME_MAC_WINDOW (f), toolbar);
+
+  if (toolbar)
+    CFRelease (toolbar);
+
+  return err;
+}
+
+/* Update the tool bar for frame F.  Add new buttons and remove old.  */
+
+void
+update_frame_tool_bar (f)
+     FRAME_PTR f;
+{
+  HIToolbarRef toolbar = NULL;
+  short left, top;
+  CFArrayRef old_items = NULL;
+  CFIndex old_count;
+  int i, pos, win_gravity = f->output_data.mac->toolbar_win_gravity;
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  BLOCK_INPUT;
+
+  GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
+  if (toolbar == NULL)
+    {
+      mac_create_frame_tool_bar (f);
+      GetWindowToolbar (FRAME_MAC_WINDOW (f), &toolbar);
+      if (toolbar == NULL)
+       goto out;
+      if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
+       mac_get_window_origin_with_gravity (f, win_gravity, &left, &top);
+    }
+
+  HIToolbarCopyItems (toolbar, &old_items);
+  if (old_items == NULL)
+    goto out;
+
+  old_count = CFArrayGetCount (old_items);
+  pos = 0;
+  for (i = 0; i < f->n_tool_bar_items; ++i)
+    {
+#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
+
+      int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
+      int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
+      int idx;
+      Lisp_Object image;
+      CGImageRef cg_image;
+      CFStringRef label;
+      HIToolbarItemRef item;
+
+      /* If image is a vector, choose the image according to the
+        button state.  */
+      image = PROP (TOOL_BAR_ITEM_IMAGES);
+      if (VECTORP (image))
+       {
+         if (enabled_p)
+           idx = (selected_p
+                  ? TOOL_BAR_IMAGE_ENABLED_SELECTED
+                  : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
+         else
+           idx = (selected_p
+                  ? TOOL_BAR_IMAGE_DISABLED_SELECTED
+                  : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
+
+         xassert (ASIZE (image) >= idx);
+         image = AREF (image, idx);
+       }
+      else
+       idx = -1;
+
+      cg_image = mac_image_spec_to_cg_image (f, image);
+      /* Ignore invalid image specifications.  */
+      if (cg_image == NULL)
+       continue;
+
+      label = cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION));
+      if (label == NULL)
+       label = CFSTR ("");
+
+      if (pos < old_count)
+       {
+         CGImageRef old_cg_image = NULL;
+         CFStringRef old_label = NULL;
+         Boolean old_enabled_p;
+
+         item = (HIToolbarItemRef) CFArrayGetValueAtIndex (old_items, pos);
+
+         HIToolbarItemCopyImage (item, &old_cg_image);
+         if (cg_image != old_cg_image)
+           HIToolbarItemSetImage (item, cg_image);
+         CGImageRelease (old_cg_image);
+
+         HIToolbarItemCopyLabel (item, &old_label);
+         if (CFStringCompare (label, old_label, 0) != kCFCompareEqualTo)
+           HIToolbarItemSetLabel (item, label);
+         CFRelease (old_label);
+
+         old_enabled_p = HIToolbarItemIsEnabled (item);
+         if ((enabled_p || idx >= 0) != old_enabled_p)
+           HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
+       }
+      else
+       {
+         item = NULL;
+         HIToolbarCreateItemWithIdentifier (toolbar,
+                                            TOOLBAR_ICON_ITEM_IDENTIFIER,
+                                            NULL, &item);
+         if (item)
+           {
+             HIToolbarItemSetImage (item, cg_image);
+             HIToolbarItemSetLabel (item, label);
+             HIToolbarItemSetEnabled (item, (enabled_p || idx >= 0));
+             HIToolbarAppendItem (toolbar, item);
+             CFRelease (item);
+           }
+       }
+
+      CFRelease (label);
+      if (item)
+       {
+         HIToolbarItemSetCommandID (item, TOOLBAR_ITEM_MAKE_COMMAND_ID (i));
+         pos++;
+       }
+    }
+
+  CFRelease (old_items);
+
+  while (pos < old_count)
+    HIToolbarRemoveItemAtIndex (toolbar, --old_count);
+
+  ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), true,
+                        !win_gravity && f == mac_focus_frame (dpyinfo));
+  /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
+     toolbar visibility change.  */
+  mac_handle_origin_change (f);
+  if (win_gravity >= NorthWestGravity && win_gravity <= SouthEastGravity)
+    {
+      mac_move_window_with_gravity (f, win_gravity, left, top);
+      /* If the title bar is completely outside the screen, adjust the
+        position. */
+      ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
+                              kWindowConstrainMoveRegardlessOfFit
+                              | kWindowConstrainAllowPartial, NULL, NULL);
+      f->output_data.mac->toolbar_win_gravity = 0;
+    }
+
+ out:
+  UNBLOCK_INPUT;
+}
+
+/* Hide the tool bar on frame F.  Unlike the counterpart on GTK+, it
+   doesn't deallocate the resources.  */
+
+void
+free_frame_tool_bar (f)
+     FRAME_PTR f;
+{
+  if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f)))
+    {
+      struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+      BLOCK_INPUT;
+      ShowHideWindowToolbar (FRAME_MAC_WINDOW (f), false,
+                            f == mac_focus_frame (dpyinfo));
+      /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
+        on toolbar visibility change.  */
+      mac_handle_origin_change (f);
+      UNBLOCK_INPUT;
+    }
+}
+
+static void
+mac_tool_bar_note_mouse_movement (f, event)
+     struct frame *f;
+     EventRef event;
+{
+  OSStatus err;
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+  int mouse_down_p;
+  HIViewRef item_view;
+  UInt32 command_id;
+
+  mouse_down_p = (dpyinfo->grabbed
+                 && f == last_mouse_frame
+                 && FRAME_LIVE_P (f));
+  if (mouse_down_p)
+    return;
+
+  err = HIViewGetViewForMouseEvent (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
+                                   event, &item_view);
+  /* This doesn't work on Mac OS X 10.2.  On Mac OS X 10.3 and 10.4, a
+     toolbar item view seems to have the same command ID with that of
+     the toolbar item.  */
+  if (err == noErr)
+    err = GetControlCommandID (item_view, &command_id);
+  if (err == noErr && TOOLBAR_ITEM_COMMAND_ID_P (command_id))
+    {
+      int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id);
+
+      if (i < f->n_tool_bar_items)
+       {
+         HIRect bounds;
+         HIViewRef content_view;
+
+         err = HIViewGetBounds (item_view, &bounds);
+         if (err == noErr)
+           err = HIViewFindByID (HIViewGetRoot (FRAME_MAC_WINDOW (f)),
+                                 kHIViewWindowContentID, &content_view);
+         if (err == noErr)
+           err = HIViewConvertRect (&bounds, item_view, content_view);
+         if (err == noErr)
+           SetRect (&last_mouse_glyph,
+                    CGRectGetMinX (bounds), CGRectGetMinY (bounds),
+                    CGRectGetMaxX (bounds), CGRectGetMaxY (bounds));
+
+         help_echo_object = help_echo_window = Qnil;
+         help_echo_pos = -1;
+         help_echo_string = PROP (TOOL_BAR_ITEM_HELP);
+         if (NILP (help_echo_string))
+           help_echo_string = PROP (TOOL_BAR_ITEM_CAPTION);
+       }
+    }
+}
+
+static OSStatus
+mac_handle_toolbar_command_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus err, result = eventNotHandledErr;
+  struct frame *f = (struct frame *) data;
+  HICommand command;
+
+  err = GetEventParameter (event, kEventParamDirectObject,
+                          typeHICommand, NULL,
+                          sizeof (HICommand), NULL, &command);
+  if (err != noErr)
+    return result;
+
+  switch (GetEventKind (event))
+    {
+    case kEventCommandProcess:
+      if (!TOOLBAR_ITEM_COMMAND_ID_P (command.commandID))
+       result = CallNextEventHandler (next_handler, event);
+      else
+       {
+         int i = TOOLBAR_ITEM_COMMAND_ID_VALUE (command.commandID);
+
+         if (i < f->n_tool_bar_items
+             && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)))
+           {
+             Lisp_Object frame;
+             struct input_event buf;
+
+             EVENT_INIT (buf);
+
+             XSETFRAME (frame, f);
+             buf.kind = TOOL_BAR_EVENT;
+             buf.frame_or_window = frame;
+             buf.arg = frame;
+             kbd_buffer_store_event (&buf);
+
+             buf.kind = TOOL_BAR_EVENT;
+             buf.frame_or_window = frame;
+             buf.arg = PROP (TOOL_BAR_ITEM_KEY);
+             buf.modifiers = mac_event_to_emacs_modifiers (event);
+             kbd_buffer_store_event (&buf);
+
+             result = noErr;
+           }
+       }
+      break;
+
+    default:
+      abort ();
+    }
+#undef PROP
+
+  return result;
+}
+#endif /* USE_MAC_TOOLBAR */
+
+\f
+/***********************************************************************
+                            Text Cursor
+ ***********************************************************************/
+
+/* Set clipping for output in glyph row ROW.  W is the window in which
+   we operate.  GC is the graphics context to set clipping in.
+
+   ROW may be a text row or, e.g., a mode line.  Text rows must be
+   clipped to the interior of the window dedicated to text display,
+   mode lines must be clipped to the whole window.  */
+
+static void
+x_clip_to_row (w, row, area, gc)
+     struct window *w;
+     struct glyph_row *row;
+     int area;
+     GC gc;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  Rect clip_rect;
+  int window_x, window_y, window_width;
+
+  window_box (w, area, &window_x, &window_y, &window_width, 0);
+
+  clip_rect.left = window_x;
+  clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  clip_rect.top = max (clip_rect.top, window_y);
+  clip_rect.right = clip_rect.left + window_width;
+  clip_rect.bottom = clip_rect.top + row->visible_height;
+
+  mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
+}
+
+
+/* Draw a hollow box cursor on window W in glyph row ROW.  */
+
+static void
+x_draw_hollow_cursor (w, row)
+     struct window *w;
+     struct glyph_row *row;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+  Display *dpy = FRAME_MAC_DISPLAY (f);
+  int x, y, wd, h;
+  XGCValues xgcv;
+  struct glyph *cursor_glyph;
+  GC gc;
+
+  /* Get the glyph the cursor is on.  If we can't tell because
+     the current matrix is invalid or such, give up.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph == NULL)
+    return;
+
+  /* Compute frame-relative coordinates for phys cursor.  */
+  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
+     background color, which can cause the cursor box to be invisible.  */
+  xgcv.foreground = f->output_data.mac->cursor_pixel;
+  if (dpyinfo->scratch_cursor_gc)
+    XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
+  else
+    dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
+                                           GCForeground, &xgcv);
+  gc = dpyinfo->scratch_cursor_gc;
+
+  /* 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 - 1);
+  mac_reset_clip_rectangles (dpy, gc);
+}
+
+
+/* Draw a bar cursor on window W in glyph row ROW.
+
+   Implementation note: One would like to draw a bar cursor with an
+   angle equal to the one given by the font property XA_ITALIC_ANGLE.
+   Unfortunately, I didn't find a font yet that has this property set.
+   --gerd.  */
+
+static void
+x_draw_bar_cursor (w, row, width, kind)
+     struct window *w;
+     struct glyph_row *row;
+     int width;
+     enum text_cursor_kinds kind;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct glyph *cursor_glyph;
+
+  /* If cursor is out of bounds, don't draw garbage.  This can happen
+     in mini-buffer windows when switching between echo area glyphs
+     and mini-buffer.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
   if (cursor_glyph == NULL)
     return;
 
@@ -5630,6 +6677,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
@@ -5650,7 +6748,9 @@ x_calc_absolute_position (f)
 
   /* Find the offsets of the outside upper-left corner of
      the inner window, with respect to the outer window.  */
+  BLOCK_INPUT;
   mac_get_window_bounds (f, &inner, &outer);
+  UNBLOCK_INPUT;
 
   width_diff = (outer.right - outer.left) - (inner.right - inner.left);
   height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
@@ -5710,7 +6810,8 @@ 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 (!NILP (tip_frame) && XFRAME (tip_frame) == f)
+    mac_handle_origin_change (f);
 #else
   {
     Rect inner, outer, screen_rect, dummy;
@@ -5784,45 +6885,21 @@ 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 TARGET_API_MAC_CARBON
+  if (!NILP (tip_frame) && f == XFRAME (tip_frame))
+#endif
+    mac_handle_size_change (f, pixelwidth, pixelheight);
 
-  /* If cursor was outside the new size, mark it as off.  */
-  mark_window_cursors_off (XWINDOW (f->root_window));
+  if (f->output_data.mac->internal_border_width
+      != FRAME_INTERNAL_BORDER_WIDTH (f))
+    {
+      mac_clear_window (f);
+      f->output_data.mac->internal_border_width
+       = FRAME_INTERNAL_BORDER_WIDTH (f);
+    }
 
-  /* 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);
+  SET_FRAME_GARBAGED (f);
 
   UNBLOCK_INPUT;
 }
@@ -5855,13 +6932,22 @@ 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
+  pix_x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
+  pix_y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
+
+  BLOCK_INPUT;
+  CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
+  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.  */
@@ -5933,15 +7019,17 @@ static void
 mac_handle_visibility_change (f)
      struct frame *f;
 {
-  WindowPtr wp = FRAME_MAC_WINDOW (f);
+  WindowRef wp = FRAME_MAC_WINDOW (f);
   int visible = 0, iconified = 0;
   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)
     {
@@ -5956,6 +7044,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)))
@@ -5969,6 +7058,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);
       }
 
@@ -5987,9 +7077,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))
@@ -6000,27 +7087,7 @@ 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 MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-                               kWindowCascadeStartAtParentWindowScreen
-#else
-                               kWindowCascadeOnParentWindowScreen
-#endif
-                               );
-           x_real_positions (f, &f->left_pos, &f->top_pos);
-         }
-       else
-#endif
-         x_set_offset (f, f->left_pos, f->top_pos, 0);
+       x_set_offset (f, f->left_pos, f->top_pos, 0);
 
       f->output_data.mac->asked_for_visible = 1;
 
@@ -6094,18 +7161,20 @@ x_make_frame_invisible (f)
 
   BLOCK_INPUT;
 
+#if !TARGET_API_MAC_CARBON
   /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
      that the current position of the window is user-specified, rather than
      program-specified, so that when the window is mapped again, it will be
      placed at the same location, without forcing the user to position it
      by hand again (they have already done that once for this window.)  */
   x_wm_set_size_hint (f, (long) 0, 1);
+#endif
 
   HideWindow (FRAME_MAC_WINDOW (f));
 
   UNBLOCK_INPUT;
 
-#if !USE_CARBON_EVENTS
+#if !TARGET_API_MAC_CARBON
   mac_handle_visibility_change (f);
 #endif
 }
@@ -6116,7 +7185,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
@@ -6144,7 +7213,7 @@ x_iconify_frame (f)
   if (err != noErr)
     error ("Can't notify window manager of iconification");
 
-#if !USE_CARBON_EVENTS
+#if !TARGET_API_MAC_CARBON
   mac_handle_visibility_change (f);
 #endif
 }
@@ -6157,13 +7226,16 @@ x_free_frame_resources (f)
      struct frame *f;
 {
   struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-  WindowPtr wp = FRAME_MAC_WINDOW (f);
+  WindowRef wp = FRAME_MAC_WINDOW (f);
 
   BLOCK_INPUT;
 
   if (wp != tip_window)
     remove_window_handler (wp);
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   DisposeWindow (wp);
   if (wp == tip_window)
     /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
@@ -6184,7 +7256,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)
@@ -6432,29 +7509,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 == '*')
@@ -6463,15 +7536,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 == '?')
@@ -6507,8 +7582,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;
@@ -6545,10 +7618,6 @@ xlfdpat_create (pattern)
       }
 
   return pat;
-
- error:
-  xlfdpat_destroy (pat);
-  return NULL;
 }
 
 static INLINE int
@@ -6562,14 +7631,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));
@@ -6626,17 +7696,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);
 
@@ -6717,6 +7787,9 @@ 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;
+extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
 #endif
 
 /* Alist linking character set strings to Mac text encoding and Emacs
@@ -6735,11 +7808,14 @@ create_text_encoding_info_alist ()
       Lisp_Object existing_info;
 
       if (!(CONSP (charset_info)
-           && STRINGP (charset = XCAR (charset_info))
+           && (charset = XCAR (charset_info),
+               STRINGP (charset))
            && CONSP (XCDR (charset_info))
-           && INTEGERP (text_encoding = XCAR (XCDR (charset_info)))
+           && (text_encoding = XCAR (XCDR (charset_info)),
+               INTEGERP (text_encoding))
            && CONSP (XCDR (XCDR (charset_info)))
-           && SYMBOLP (coding_system = XCAR (XCDR (XCDR (charset_info))))))
+           && (coding_system = XCAR (XCDR (XCDR (charset_info))),
+               SYMBOLP (coding_system))))
        continue;
 
       existing_info = assq_no_quit (text_encoding, result);
@@ -6803,7 +7879,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;
@@ -6850,7 +7926,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;
@@ -6907,29 +7984,176 @@ parse_x_font_name (xf, family, size, style, charset)
     if (isascii (*p))
       *p = tolower (*p);
 
-  return 1;
+  return 1;
+}
+
+
+static void
+add_font_name_table_entry (char *font_name)
+{
+  if (font_name_table_size == 0)
+    {
+      font_name_table_size = 256;
+      font_name_table = (char **)
+       xmalloc (font_name_table_size * sizeof (char *));
+    }
+  else if (font_name_count + 1 >= font_name_table_size)
+    {
+      font_name_table_size *= 2;
+      font_name_table = (char **)
+       xrealloc (font_name_table,
+                 font_name_table_size * sizeof (char *));
+    }
+
+  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 FMFontStyle
+fm_get_style_from_font (font)
+     FMFont font;
+{
+  OSStatus err;
+  FMFontStyle style = normal;
+  ByteCount len;
+  UInt16 mac_style;
+  FMFontFamily font_family;
+#define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
+
+  /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
+     some font (e.g., Optima) even if it is `bold'.  */
+  err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
+                       sizeof (mac_style), &mac_style, &len);
+  if (err == noErr
+      && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
+    style = EndianU16_BtoN (mac_style);
+  else
+    FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
+
+  return style;
+}
+
+static ATSUFontID
+atsu_find_font_from_family_name (family)
+     const char *family;
+{
+  struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
+  unsigned hash_code;
+  int i;
+  Lisp_Object rest, best;
+  FMFontStyle min_style, style;
+
+  i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
+                  &hash_code);
+  if (i < 0)
+    return kATSUInvalidFontID;
+
+  rest = HASH_VALUE (h, i);
+  if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
+    return cons_to_long (rest);
+
+  rest = Fnreverse (rest);
+  best = XCAR (rest);
+  rest = XCDR (rest);
+  if (!NILP (rest)
+      && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
+    do
+      {
+       style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
+       if (style < min_style)
+         {
+           best = XCAR (rest);
+           if (style == normal)
+             break;
+           else
+             min_style = style;
+         }
+       rest = XCDR (rest);
+      }
+    while (!NILP (rest));
+
+  HASH_VALUE (h, i) = best;
+  return cons_to_long (best);
 }
 
+static Lisp_Object
+fm_style_to_face_attributes (fm_style)
+     FMFontStyle fm_style;
+{
+  Lisp_Object tem;
 
-static void
-add_font_name_table_entry (char *font_name)
+  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;
+}
+
+static Lisp_Object
+atsu_find_font_family_name (font_id)
+     ATSUFontID font_id;
 {
-  if (font_name_table_size == 0)
-    {
-      font_name_table_size = 256;
-      font_name_table = (char **)
-       xmalloc (font_name_table_size * sizeof (char *));
-    }
-  else if (font_name_count + 1 >= font_name_table_size)
+  OSStatus err;
+  ByteCount len;
+  Lisp_Object family = Qnil;
+
+  err = ATSUFindFontName (font_id, kFontFamilyName,
+                         kFontMacintoshPlatform, kFontNoScript,
+                         kFontNoLanguage, 0, NULL, &len, NULL);
+  if (err == noErr)
     {
-      font_name_table_size *= 2;
-      font_name_table = (char **)
-       xrealloc (font_name_table,
-                 font_name_table_size * sizeof (char *));
+      family = make_uninit_string (len);
+      err = ATSUFindFontName (font_id, kFontFamilyName,
+                             kFontMacintoshPlatform, kFontNoScript,
+                             kFontNoLanguage, len, SDATA (family),
+                             NULL, NULL);
     }
+  if (err == noErr)
+    decode_mac_font_name (SDATA (family), len + 1, Qnil);
 
-  font_name_table[font_name_count++] = font_name;
+  return family;
+}
+
+Lisp_Object
+mac_atsu_font_face_attributes (font_id)
+     ATSUFontID font_id;
+{
+  Lisp_Object family, style_attrs;
+
+  family = atsu_find_font_family_name (font_id);
+  if (NILP (family))
+    return Qnil;
+  style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
+  return Fcons (QCfamily, Fcons (family, style_attrs));
 }
+#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
@@ -6955,65 +8179,50 @@ 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;
-      ByteCount name_len;
+      Lisp_Object prev_family = Qnil;
+      int j;
 
       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);;
+                        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++)
          {
-           err = ATSUFindFontName (font_ids[i], kFontFamilyName,
-                                   kFontMacintoshPlatform, kFontNoScript,
-                                   kFontNoLanguage, 0, NULL, &name_len, NULL);
-           if (err != noErr)
-             continue;
-           name = xmalloc (name_len + 1);
-           if (name == NULL)
+           Lisp_Object family;
+
+           family = atsu_find_font_family_name (font_ids[i]);
+           if (NILP (family) || SREF (family, 0) == '.')
              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))
+           if (!NILP (Fequal (prev_family, family)))
+             family = prev_family;
+           else
+             j = hash_lookup (h, family, &hash_code);
+           if (j < 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;
+               add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
+               j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
+                                               Qnil), hash_code);
              }
-           else
-             xfree (name);
+           else if (EQ (prev_family, family))
+             HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
+                                        HASH_VALUE (h, j));
+           prev_family = family;
          }
-      if (prev_name)
-       xfree (prev_name);
       if (font_ids)
        xfree (font_ids);
     }
@@ -7041,16 +8250,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);
@@ -7059,13 +8268,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)
@@ -7074,27 +8285,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)));
        }
     }
 
@@ -7114,7 +8305,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 */
@@ -7133,7 +8324,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);
@@ -7145,8 +8336,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
        {
@@ -7167,14 +8360,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)));
                }
            }
 
@@ -7215,7 +8403,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 */
@@ -7225,14 +8413,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.  */
@@ -7302,7 +8492,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
@@ -7311,8 +8501,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",
@@ -7325,7 +8513,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
@@ -7484,7 +8672,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;
@@ -7512,14 +8701,16 @@ 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 size;
   char *name;
@@ -7558,26 +8749,27 @@ 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,
-                                    kDiacriticsType};
-      ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector,
-                                            kDecomposeDiacriticsSelector};
-      Lisp_Object font_id_cons;
-
-      font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
-                              atsu_font_id_hash, Qnil);
-      if (NILP (font_id_cons))
-       return NULL;
-      font_id = cons_to_long (font_id_cons);
+      static const ATSUAttributeValuePtr values[] =
+       {&font_id, &size_fixed,
+        &bold_p, &italic_p};
+      static const ATSUFontFeatureType types[] =
+       {kAllTypographicFeaturesType, kDiacriticsType};
+      static const ATSUFontFeatureSelector selectors[] =
+       {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
+      FMFontStyle style;
+
+      font_id = atsu_find_font_from_family_name (family);
+      if (font_id == kATSUInvalidFontID)
+       return;
       size_fixed = Long2Fix (size);
       bold_p = (fontface & bold) != 0;
       italic_p = (fontface & italic) != 0;
@@ -7590,7 +8782,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
@@ -7636,7 +8832,7 @@ XLoadQueryFont (Display *dpy, char *fontname)
 #if USE_ATSUI
   if (font->mac_style)
     {
-      OSErr err;
+      OSStatus err;
       UniChar c;
 
       font->min_byte1 = 0;
@@ -7644,45 +8840,34 @@ XLoadQueryFont (Display *dpy, char *fontname)
       font->min_char_or_byte2 = 0;
       font->max_char_or_byte2 = 0xff;
 
-      font->bounds.rows = xmalloc (sizeof (XCharStructRow *) * 0x100);
-      if (font->bounds.rows == NULL)
-       {
-         mac_unload_font (&one_mac_display_info, font);
-         return NULL;
-       }
-      bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100);
-      font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow));
-      if (font->bounds.rows[0] == NULL)
-       {
-         mac_unload_font (&one_mac_display_info, font);
-         return NULL;
-       }
-      bzero (font->bounds.rows[0], sizeof (XCharStructRow));
+      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
-      space_bounds = font->bounds.rows[0]->per_char + 0x20;
+      space_bounds = font->bounds.rows[0] + 0x20;
       err = mac_query_char_extents (font->mac_style, 0x20,
                                    &font->ascent, &font->descent,
                                    space_bounds,
@@ -7693,14 +8878,14 @@ XLoadQueryFont (Display *dpy, char *fontname)
                                    NULL
 #endif
                                    );
-      if (err != noErr)
+      if (err != noErr
+         || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
        {
          mac_unload_font (&one_mac_display_info, font);
          return NULL;
        }
-      XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], 0x20);
 
-      pcm = font->bounds.rows[0]->per_char;
+      pcm = font->bounds.rows[0];
       for (c = 0x21; c <= 0xff; c++)
        {
          if (c == 0xad)
@@ -7708,11 +8893,19 @@ XLoadQueryFont (Display *dpy, char *fontname)
            continue;
          else if (c == 0x7f)
            {
-             c = 0x9f;
-             continue;
+#if USE_CG_TEXT_DRAWING
+             if (font->cg_glyphs)
+               {
+                 c = 0x9f;
+                 pcm = NULL;
+                 continue;
+               }
+#endif
+             break;
            }
 
-         mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
+         mac_query_char_extents (font->mac_style, c, NULL, NULL,
+                                 pcm ? pcm + c : NULL,
 #if USE_CG_TEXT_DRAWING
                                  (font->cg_glyphs ? font->cg_glyphs + c
                                   : NULL)
@@ -7720,7 +8913,6 @@ XLoadQueryFont (Display *dpy, char *fontname)
                                    NULL
 #endif
                                  );
-         XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], c);
 
 #if USE_CG_TEXT_DRAWING
          if (font->cg_glyphs && font->cg_glyphs[c] == 0)
@@ -7731,6 +8923,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
              font->cg_font = NULL;
              xfree (font->cg_glyphs);
              font->cg_glyphs = NULL;
+             if (pcm == NULL)
+               break;
            }
 #endif
        }
@@ -7738,23 +8932,14 @@ XLoadQueryFont (Display *dpy, char *fontname)
   else
 #endif
     {
-      GrafPtr port;
-      SInt16 old_fontnum, old_fontsize;
-      Style old_fontface;
+      OSStatus err;
       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);
@@ -7826,26 +9011,21 @@ XLoadQueryFont (Display *dpy, char *fontname)
 
          font->bounds.per_char =
            xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
-         if (font->bounds.per_char == NULL)
-           {
-             mac_unload_font (&one_mac_display_info, font);
-             return NULL;
-           }
          bzero (font->bounds.per_char,
                 sizeof (XCharStruct) * (0xff - 0x20 + 1));
 
          space_bounds = font->bounds.per_char;
-         mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
-                                 space_bounds, NULL);
+         err = mac_query_char_extents (NULL, 0x20, &font->ascent,
+                                       &font->descent, space_bounds, NULL);
+         if (err != noErr || space_bounds->width <= 0)
+           {
+             mac_unload_font (&one_mac_display_info, font);
+             return NULL;
+           }
 
          for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
            mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
        }
-
-      /* Restore previous font number, size and face.  */
-      TextFont (old_fontnum);
-      TextSize (old_fontsize);
-      TextFace (old_fontface);
     }
 
   if (space_bounds)
@@ -7864,6 +9044,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
                                             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);
@@ -7873,6 +9055,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
                                             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
@@ -7974,16 +9158,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;
@@ -8135,8 +9317,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;
 }
@@ -8172,6 +9354,155 @@ 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;
+
+extern Lisp_Object Qfont;
+static Lisp_Object Qpanel_closed, Qselection;
+
+static OSStatus mac_store_event_ref_as_apple_event P_ ((AEEventClass, AEEventID,
+                                                       Lisp_Object,
+                                                       Lisp_Object,
+                                                       EventRef, UInt32,
+                                                       const EventParamName *,
+                                                       const EventParamType *));
+
+int
+mac_font_panel_visible_p ()
+{
+  return font_panel_shown_p && FPIsFontPanelVisible ();
+}
+
+static pascal OSStatus
+mac_handle_font_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  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 kEventFontPanelClosed:
+      id_key = Qpanel_closed;
+      num_params = 0;
+      names = NULL;
+      types = NULL;
+      break;
+
+    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);
+  if (err == noErr)
+    result = noErr;
+
+  return result;
+}
+
+OSStatus
+mac_show_hide_font_panel ()
+{
+  if (!font_panel_shown_p)
+    {
+      OSStatus err;
+
+      static const EventTypeSpec specs[] =
+       {{kEventClassFont, kEventFontPanelClosed},
+        {kEventClassFont, kEventFontSelection}};
+
+      err = InstallApplicationEventHandler (mac_handle_font_event,
+                                           GetEventTypeCount (specs),
+                                           specs, NULL, NULL);
+      if (err != noErr)
+       return err;
+
+      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 */
@@ -8198,12 +9529,9 @@ 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
-#define TERM_WINDOW_RESOURCE 129
-
 #define DEFAULT_NUM_COLS 80
 
 #define MIN_DOC_SIZE 64
@@ -8235,7 +9563,7 @@ Lisp_Object Vmac_function_modifier;
    a three button mouse */
 Lisp_Object Vmac_emulate_three_button_mouse;
 
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
    mouse-2, instead of mouse-3.  */
 int mac_wheel_button_is_mouse_2;
@@ -8254,12 +9582,30 @@ int mac_pass_control_to_system;
    Carbon/Apple event handlers.  */
 static struct input_event *read_socket_inev = NULL;
 
+/* Whether or not the screen configuration has changed.  */
+static int mac_screen_config_changed = 0;
+
 Point saved_menu_event_location;
 
 /* Apple Events */
-#if USE_CARBON_EVENTS
-static Lisp_Object Qhicommand;
-#endif
+#if TARGET_API_MAC_CARBON
+static Lisp_Object Qhi_command;
+#ifdef MAC_OSX
+extern Lisp_Object Qwindow;
+static Lisp_Object Qtoolbar_switch_mode;
+#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 /* TARGET_API_MAC_CARBON */
 extern int mac_ready_for_apple_events;
 extern Lisp_Object Qundefined;
 extern void init_apple_event_handler P_ ((void));
@@ -8268,24 +9614,19 @@ extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
                                           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
+extern OSErr install_drag_handler P_ ((WindowRef));
+extern void remove_drag_handler P_ ((WindowRef));
+
+#if TARGET_API_MAC_CARBON
+/* Showing help echo string during menu tracking  */
+extern OSStatus install_menu_target_item_handler P_ ((void));
 
-#if USE_CARBON_EVENTS
 #ifdef MAC_OSX
-extern void init_service_handler ();
-static Lisp_Object Qservices, Qpaste, Qperform;
+extern OSStatus install_service_handler ();
+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);
 
 extern void init_emacs_passwd_dir ();
 extern int emacs_main (int, char **, char **);
@@ -8293,8 +9634,83 @@ extern int emacs_main (int, char **, char **);
 extern void initialize_applescript();
 extern void terminate_applescript();
 
-static unsigned int
-#if USE_CARBON_EVENTS
+/* 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 int
+#if TARGET_API_MAC_CARBON
 mac_to_emacs_modifiers (UInt32 mods)
 #else
 mac_to_emacs_modifiers (EventModifiers mods)
@@ -8330,14 +9746,31 @@ mac_to_emacs_modifiers (EventModifiers mods)
   }
 
 #ifdef MAC_OSX
-  if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
-    Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
-    if (INTEGERP(val))
-      result |= XUINT(val);
-  }
+  if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
+    Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+#endif
+
+  return result;
+}
+
+static UInt32
+mac_mapped_modifiers (modifiers)
+     UInt32 modifiers;
+{
+  UInt32 mapped_modifiers_all =
+    (NILP (Vmac_control_modifier) ? 0 : controlKey)
+    | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+    | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+
+#ifdef MAC_OSX
+  mapped_modifiers_all |=
+    (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
 #endif
 
-  return result;
+  return mapped_modifiers_all & modifiers;
 }
 
 static int
@@ -8354,17 +9787,51 @@ mac_get_emulated_btn ( UInt32 modifiers )
   return result;
 }
 
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
+/***** Code to handle C-g testing  *****/
+extern int quit_char;
+extern int make_ctrl_char P_ ((int));
+
+int
+mac_quit_char_key_p (modifiers, key_code)
+     UInt32 modifiers, key_code;
+{
+  UInt32 char_code;
+  unsigned long some_state = 0;
+  Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+  int c, emacs_modifiers;
+
+  /* Mask off modifier keys that are mapped to some Emacs modifiers.  */
+  key_code |= (modifiers & ~(mac_mapped_modifiers (modifiers)));
+  char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
+  if (char_code & ~0xff)
+    return 0;
+
+  emacs_modifiers = mac_to_emacs_modifiers (modifiers);
+  if (emacs_modifiers & ctrl_modifier)
+    c = make_ctrl_char (char_code);
+
+  c |= (emacs_modifiers
+       & (meta_modifier | alt_modifier
+          | hyper_modifier | super_modifier));
+
+  return c == quit_char;
+}
+#endif
+
+#if TARGET_API_MAC_CARBON
 /* Obtains the event modifiers from the event ref and then calls
    mac_to_emacs_modifiers.  */
-static UInt32
+static int
 mac_event_to_emacs_modifiers (EventRef eventRef)
 {
-  UInt32 mods = 0;
+  UInt32 mods = 0, class;
+
   GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
                    sizeof (UInt32), NULL, &mods);
+  class = GetEventClass (eventRef);
   if (!NILP (Vmac_emulate_three_button_mouse) &&
-      GetEventClass(eventRef) == kEventClassMouse)
+      (class == kEventClassMouse || class == kEventClassCommand))
     {
       mods &= ~(optionKey | cmdKey);
     }
@@ -8402,15 +9869,16 @@ mac_get_mouse_btn (EventRef ref)
 
 /* Normally, ConvertEventRefToEventRecord will correctly handle all
    events.  However the click of the mouse wheel is not converted to a
-   mouseDown or mouseUp event.  Likewise for dead key down events.
-   This calls ConvertEventRef, but then checks to see if it is a mouse
-   up/down, or a dead key down carbon event that has not been
+   mouseDown or mouseUp event.  Likewise for dead key events.  This
+   calls ConvertEventRefToEventRecord, but then checks to see if it is
+   a mouse up/down, or a dead key Carbon event that has not been
    converted, and if so, converts it by hand (to be picked up in the
    XTread_socket loop).  */
 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
 {
   OSStatus err;
   Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
+  EventKind action;
 
   if (result)
     return result;
@@ -8439,6 +9907,14 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
       switch (GetEventKind (eventRef))
        {
        case kEventRawKeyDown:
+         action = keyDown;
+         goto keystroke_common;
+       case kEventRawKeyRepeat:
+         action = autoKey;
+         goto keystroke_common;
+       case kEventRawKeyUp:
+         action = keyUp;
+       keystroke_common:
          {
            unsigned char char_codes;
            UInt32 key_code;
@@ -8452,7 +9928,7 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
                                       NULL, &key_code);
            if (err == noErr)
              {
-               eventRec->what = keyDown;
+               eventRec->what = action;
                eventRec->message = char_codes | ((key_code & 0xff) << 8);
                result = 1;
              }
@@ -8489,11 +9965,12 @@ static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
 
 #endif
 
+#ifdef MAC_OS8
 static void
 do_get_menus (void)
 {
   Handle menubar_handle;
-  MenuHandle menu_handle;
+  MenuRef menu;
 
   menubar_handle = GetNewMBar (128);
   if(menubar_handle == NULL)
@@ -8502,9 +9979,9 @@ do_get_menus (void)
   DrawMenuBar ();
 
 #if !TARGET_API_MAC_CARBON
-  menu_handle = GetMenuHandle (M_APPLE);
-  if(menu_handle != NULL)
-    AppendResMenu (menu_handle,'DRVR');
+  menu = GetMenuRef (M_APPLE);
+  if (menu != NULL)
+    AppendResMenu (menu'DRVR');
   else
     abort ();
 #endif
@@ -8550,9 +10027,10 @@ do_check_ram_size (void)
       exit (1);
     }
 }
+#endif /* MAC_OS8 */
 
 static void
-do_window_update (WindowPtr win)
+do_window_update (WindowRef win)
 {
   struct frame *f = mac_window_to_frame (win);
 
@@ -8580,6 +10058,9 @@ do_window_update (WindowPtr win)
          GetPortVisibleRegion (GetWindowPort (win), region);
          GetRegionBounds (region, &r);
          expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
+#endif
          UpdateControls (win, region);
          DisposeRgn (region);
 #else
@@ -8594,7 +10075,7 @@ do_window_update (WindowPtr win)
 }
 
 static int
-is_emacs_window (WindowPtr win)
+is_emacs_window (WindowRef win)
 {
   Lisp_Object tail, frame;
 
@@ -8609,23 +10090,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;
 
@@ -8633,52 +10188,19 @@ do_apple_menu (SInt16 menu_item)
     NoteAlert (ABOUT_ALERT_ID, NULL);
   else
     {
-      GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
+      GetMenuItemText (GetMenuRef (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)
+     WindowRef w;
+     const EventRecord *e;
 {
   Rect limit_rect;
   int rows, columns, width, height;
@@ -8723,50 +10245,64 @@ 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);
+  WindowRef 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
    wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen.  */
 
 static void
-do_zoom_window (WindowPtr w, int zoom_in_or_out)
+do_zoom_window (WindowRef 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);
@@ -8804,140 +10340,342 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   SetPort (save_port);
 #endif /* not TARGET_API_MAC_CARBON */
 
+#if !TARGET_API_MAC_CARBON
   /* retrieve window size and update application values */
-#if TARGET_API_MAC_CARBON
-  GetWindowPortBounds (w, &port_rect);
-#else
   port_rect = w->portRect;
-#endif
   height = port_rect.bottom - port_rect.top;
   width = port_rect.right - port_rect.left;
 
-  if (width != FRAME_PIXEL_WIDTH (f)
-      || height != FRAME_PIXEL_HEIGHT (f))
+  mac_handle_size_change (f, width, height);
+  mac_handle_origin_change (f);
+#endif
+}
+
+static void
+mac_set_unicode_keystroke_event (code, buf)
+     UniChar code;
+     struct input_event *buf;
+{
+  int charset_id, c1, c2;
+
+  if (code < 0x80)
     {
-      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
-      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
+      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);
+    }
+}
 
-      change_frame_size (f, rows, columns, 0, 1, 0);
-      SET_FRAME_GARBAGED (f);
-      cancel_mouse_face (f);
+static void
+do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
+     EventKind action;
+     unsigned char char_code;
+     UInt32 key_code, modifiers;
+     unsigned long timestamp;
+     struct input_event *buf;
+{
+  static SInt16 last_key_script = -1;
+  SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
+  UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers);
+
+#ifdef MAC_OSX
+  if (mapped_modifiers & kEventKeyModifierFnMask
+      && key_code <= 0x7f
+      && fn_keycode_to_keycode_table[key_code])
+    key_code = fn_keycode_to_keycode_table[key_code];
+#endif
 
-      FRAME_PIXEL_WIDTH (f) = width;
-      FRAME_PIXEL_HEIGHT (f) = height;
+  if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
+    {
+      buf->kind = NON_ASCII_KEYSTROKE_EVENT;
+      buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
+#ifdef MAC_OSX
+      if (modifiers & kEventKeyModifierFnMask
+         && key_code <= 0x7f
+         && fn_keycode_to_keycode_table[key_code] == key_code)
+       modifiers &= ~kEventKeyModifierFnMask;
+#endif
+    }
+  else if (mapped_modifiers)
+    {
+      /* translate the keycode back to determine the original key */
+#ifdef MAC_OSX
+      UCKeyboardLayout *uchr_ptr = NULL;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+      OSStatus err;
+      KeyboardLayoutRef layout;
+
+      err = KLGetCurrentKeyboardLayout (&layout);
+      if (err == noErr)
+       err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
+                                          (const void **) &uchr_ptr);
+#else
+      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)
+       uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
+#endif
+
+      if (uchr_ptr)
+       {
+         OSStatus status;
+         UInt16 key_action = action - 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 (uchr_ptr, key_code, 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, buf);
+       }
+#endif /* MAC_OSX */
+
+      if (buf->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 = modifiers & ~mapped_modifiers;
+         /* set high byte of keycode to modifier high byte*/
+         int new_key_code = key_code | new_modifiers;
+         Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+         unsigned long some_state = 0;
+         UInt32 new_char_code;
+
+         new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
+         if (new_char_code == 0)
+           /* Seems like a dead key.  Append up-stroke.  */
+           new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
+                                         &some_state);
+         if (new_char_code)
+           {
+             buf->kind = ASCII_KEYSTROKE_EVENT;
+             buf->code = new_char_code & 0xff;
+           }
+       }
+    }
+
+  if (buf->kind == NO_EVENT)
+    {
+      buf->kind = ASCII_KEYSTROKE_EVENT;
+      buf->code = char_code;
+    }
+
+  buf->modifiers = mac_to_emacs_modifiers (modifiers);
+  buf->modifiers |= (extra_keyboard_modifiers
+                    & (meta_modifier | alt_modifier
+                       | hyper_modifier | super_modifier));
+
+#if TARGET_API_MAC_CARBON
+  if (buf->kind == ASCII_KEYSTROKE_EVENT
+      && buf->code >= 0x80 && buf->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] = buf->code;
+         err = ConvertFromPStringToUnicode (ttu_info, pstr,
+                                            sizeof (UniChar),
+                                            &unicode_len, &code);
+         if (err == noErr && unicode_len == sizeof (UniChar))
+           mac_set_unicode_keystroke_event (code, buf);
+         DisposeTextToUnicodeInfo (&ttu_info);
+       }
+    }
+#endif
+
+  if (buf->kind == ASCII_KEYSTROKE_EVENT
+      && buf->code >= 0x80
+      && 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);
+      last_key_script = current_key_script;
     }
-  x_real_positions (f, &f->left_pos, &f->top_pos);
 }
 
-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);
+             mac_wakeup_from_rne ();
+           }
+       }
     }
 
   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);
 }
 
-#if USE_CARBON_EVENTS
-static pascal OSStatus
-mac_handle_command_event (next_handler, event, data)
-     EventHandlerCallRef next_handler;
+#ifdef MAC_OSX
+OSStatus
+mac_store_service_event (event)
      EventRef event;
-     void *data;
 {
-  OSStatus result, err;
-  HICommand command;
-  Lisp_Object class_key, id_key, binding;
-
-  result = CallNextEventHandler (next_handler, event);
-  if (result != eventNotHandledErr)
-    return result;
-
-  err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
-                          NULL, sizeof (HICommand), NULL, &command);
+  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};
 
-  if (err != noErr || command.commandID == 0)
-    return eventNotHandledErr;
+  switch (GetEventKind (event))
+    {
+    case kEventServicePaste:
+      id_key = Qpaste;
+      num_params = 0;
+      names = NULL;
+      types = NULL;
+      break;
 
-  /* A HICommand event is mapped to an Apple event whose event class
-     symbol is `hicommand' and event ID is its command ID.  */
-  class_key = Qhicommand;
-  mac_find_apple_event_spec (0, command.commandID,
-                            &class_key, &id_key, &binding);
-  if (!NILP (binding) && !EQ (binding, Qundefined))
-    if (INTEGERP (binding))
-      return XINT (binding);
-    else
-      {
-       AppleEvent apple_event;
-       UInt32 modifiers;
-       static EventParamName names[] = {kEventParamDirectObject,
-                                        kEventParamKeyModifiers};
-       static EventParamType types[] = {typeHICommand,
-                                        typeUInt32};
-       err = create_apple_event_from_event_ref (event, 2, names, types,
-                                                &apple_event);
-       if (err == noErr)
-         {
-           err = mac_store_apple_event (class_key, id_key, &apple_event);
-           AEDisposeDesc (&apple_event);
-         }
-       if (err == noErr)
-         return noErr;
-      }
+    case kEventServicePerform:
+      id_key = Qperform;
+      num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
+      names = names_pfm;
+      types = types_pfm;
+      break;
 
-  return eventNotHandledErr;
-}
+    default:
+      abort ();
+    }
 
-static OSErr
-init_command_handler ()
-{
-  OSErr err = noErr;
-  EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
-  static EventHandlerUPP handle_command_eventUPP = NULL;
+  err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
+                                           event, num_params,
+                                           names, types);
 
-  if (handle_command_eventUPP == NULL)
-    handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
-  return InstallApplicationEventHandler (handle_command_eventUPP,
-                                        GetEventTypeCount (specs), specs,
-                                        NULL, NULL);
+  return err;
 }
+#endif /* MAC_OSX */
 
 static pascal OSStatus
 mac_handle_window_event (next_handler, event, data)
@@ -8945,37 +10683,92 @@ mac_handle_window_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  WindowPtr wp;
-  OSStatus result, err;
+  WindowRef wp;
+  OSStatus err, result = eventNotHandledErr;
+  struct frame *f;
   UInt32 attributes;
   XSizeHints *size_hints;
 
   err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
-                          NULL, sizeof (WindowPtr), NULL, &wp);
+                          NULL, sizeof (WindowRef), NULL, &wp);
   if (err != noErr)
     return eventNotHandledErr;
 
+  f = mac_window_to_frame (wp);
   switch (GetEventKind (event))
     {
+      /* -- window refresh events -- */
+
     case kEventWindowUpdate:
       result = CallNextEventHandler (next_handler, event);
       if (result != eventNotHandledErr)
-       return result;
+       break;
 
       do_window_update (wp);
-      return noErr;
+      result = noErr;
+      break;
+
+      /* -- window state change events -- */
+
+    case kEventWindowShowing:
+      size_hints = FRAME_SIZE_HINTS (f);
+      if (!(size_hints->flags & (USPosition | PPosition)))
+       {
+         struct frame *sf = SELECTED_FRAME ();
+
+         if (!(FRAME_MAC_P (sf)))
+           RepositionWindow (wp, NULL, kWindowCenterOnMainScreen);
+         else
+           {
+             RepositionWindow (wp, FRAME_MAC_WINDOW (sf),
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+                               kWindowCascadeStartAtParentWindowScreen
+#else
+                               kWindowCascadeOnParentWindowScreen
+#endif
+                               );
+#if USE_MAC_TOOLBAR
+             /* This is a workaround.  RepositionWindow fails to put
+                a window at the cascading position when its parent
+                window has a Carbon HIToolbar.  */
+             if (f->top_pos == sf->top_pos && f->left_pos == sf->left_pos)
+               MoveWindowStructure (wp,  f->left_pos + 10, f->top_pos + 32);
+#endif
+           }
+         result = noErr;
+       }
+      break;
+
+    case kEventWindowHiding:
+      /* Before unmapping the window, update the WM_SIZE_HINTS
+        property to claim that the current position of the window is
+        user-specified, rather than program-specified, so that when
+        the window is mapped again, it will be placed at the same
+        location, without forcing the user to position it by hand
+        again (they have already done that once for this window.)  */
+      x_wm_set_size_hint (f, (long) 0, 1);
+      result = noErr;
+      break;
+
+    case kEventWindowShown:
+    case kEventWindowHidden:
+    case kEventWindowCollapsed:
+    case kEventWindowExpanded:
+      mac_handle_visibility_change (f);
+      result = noErr;
+      break;
 
     case kEventWindowBoundsChanging:
       result = CallNextEventHandler (next_handler, event);
       if (result != eventNotHandledErr)
-       return result;
+       break;
 
       err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
                               NULL, sizeof (UInt32), NULL, &attributes);
       if (err != noErr)
        break;
 
-      size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
+      size_hints = FRAME_SIZE_HINTS (f);
       if ((attributes & kWindowBoundsChangeUserResize)
          && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
              == (PResizeInc | PBaseSize | PMinSize)))
@@ -9012,23 +10805,281 @@ mac_handle_window_event (next_handler, event, data)
          bounds.bottom = bounds.top + height;
          SetEventParameter (event, kEventParamCurrentBounds,
                             typeQDRectangle, sizeof (Rect), &bounds);
-         return noErr;
+         result = noErr;
        }
       break;
 
-    case kEventWindowShown:
-    case kEventWindowHidden:
-    case kEventWindowExpanded:
-    case kEventWindowCollapsed:
+    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);
+             mac_wakeup_from_rne ();
+           }
+       }
+
+      if (attributes & kWindowBoundsChangeOriginChanged)
+       mac_handle_origin_change (f);
+
+      result = noErr;
+      break;
+
+      /* -- window action events -- */
+
+    case kEventWindowClose:
+      {
+       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);
+      }
+      result = noErr;
+      break;
+
+    case kEventWindowGetIdealSize:
+      result = CallNextEventHandler (next_handler, event);
+      if (result != eventNotHandledErr)
+       break;
+
+      {
+       Point ideal_size = mac_get_ideal_size (f);
+
+       err = SetEventParameter (event, kEventParamDimensions,
+                                typeQDPoint, sizeof (Point), &ideal_size);
+       if (err == noErr)
+         result = noErr;
+      }
+      break;
+
+#ifdef MAC_OSX
+    case kEventWindowToolbarSwitchMode:
+      {
+       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);
+      }
+      if (err == noErr)
+       result = noErr;
+      break;
+#endif
+
+#if USE_MAC_TSM
+      /* -- window focus events -- */
+
+    case kEventWindowFocusAcquired:
+      err = mac_tsm_resume ();
+      if (err == noErr)
+       result = noErr;
+      break;
+
+    case kEventWindowFocusRelinquish:
+      err = mac_tsm_suspend ();
+      if (err == noErr)
+       result = noErr;
+      break;
+#endif
+
+    default:
+      abort ();
+    }
+
+  return result;
+}
+
+static pascal OSStatus
+mac_handle_application_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus err, result = eventNotHandledErr;
+
+  switch (GetEventKind (event))
+    {
+#if USE_MAC_TSM
+    case kEventAppActivated:
+      err = mac_tsm_resume ();
+      break;
+
+    case kEventAppDeactivated:
+      err = mac_tsm_suspend ();
+      break;
+#endif
+
+    default:
+      abort ();
+    }
+
+  if (err == noErr)
+    result = noErr;
+
+  return result;
+}
+
+static pascal OSStatus
+mac_handle_keyboard_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus err, result = eventNotHandledErr;
+  UInt32 event_kind, key_code, modifiers, mapped_modifiers;
+  unsigned char char_code;
+
+  event_kind = GetEventKind (event);
+  switch (event_kind)
+    {
+    case kEventRawKeyDown:
+    case kEventRawKeyRepeat:
+    case kEventRawKeyUp:
+      if (read_socket_inev == NULL)
+       {
+         result = CallNextEventHandler (next_handler, event);
+         break;
+       }
+
+      err = GetEventParameter (event, kEventParamKeyModifiers,
+                              typeUInt32, NULL,
+                              sizeof (UInt32), NULL, &modifiers);
+      if (err != noErr)
+       break;
+
+      mapped_modifiers = mac_mapped_modifiers (modifiers);
+
+      /* 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 (!(mapped_modifiers
+           & ~(mac_pass_command_to_system ? cmdKey : 0)
+           & ~(mac_pass_control_to_system ? controlKey : 0)))
+       {
+         result = CallNextEventHandler (next_handler, event);
+         if (result != eventNotHandledErr)
+           break;
+       }
+
+#if USE_MAC_TSM
+      if (read_socket_inev->kind != NO_EVENT)
+       {
+         result = noErr;
+         break;
+       }
+#endif
+
+      if (event_kind == kEventRawKeyUp)
+       break;
+
+      err = GetEventParameter (event, kEventParamKeyMacCharCodes,
+                              typeChar, NULL,
+                              sizeof (char), NULL, &char_code);
+      if (err != noErr)
+       break;
+
+      err = GetEventParameter (event, kEventParamKeyCode,
+                              typeUInt32, NULL,
+                              sizeof (UInt32), NULL, &key_code);
+      if (err != noErr)
+       break;
+
+      do_keystroke ((event_kind == kEventRawKeyDown ? keyDown : autoKey),
+                   char_code, key_code, modifiers,
+                   ((unsigned long)
+                    (GetEventTime (event) / kEventDurationMillisecond)),
+                   read_socket_inev);
+      result = noErr;
+      break;
+
+    default:
+      abort ();
+    }
+
+  return result;
+}
+
+static pascal OSStatus
+mac_handle_command_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus err, result = eventNotHandledErr;
+  HICommand command;
+  static const EventParamName names[] =
+    {kEventParamDirectObject, kEventParamKeyModifiers};
+  static const EventParamType types[] =
+    {typeHICommand, typeUInt32};
+  int num_params = sizeof (names) / sizeof (names[0]);
+
+  err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
+                          NULL, sizeof (HICommand), NULL, &command);
+  if (err != noErr)
+    return eventNotHandledErr;
+
+  switch (GetEventKind (event))
+    {
+    case kEventCommandProcess:
       result = CallNextEventHandler (next_handler, event);
+      if (result != eventNotHandledErr)
+       break;
 
-      mac_handle_visibility_change (mac_window_to_frame (wp));
-      return noErr;
+      err = GetEventParameter (event, kEventParamDirectObject,
+                              typeHICommand, NULL,
+                              sizeof (HICommand), NULL, &command);
+
+      if (err != noErr || command.commandID == 0)
+       break;
 
+      /* 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);
+      if (err == noErr)
+       result = noErr;
       break;
+
+    default:
+      abort ();
     }
 
-  return eventNotHandledErr;
+  return result;
 }
 
 static pascal OSStatus
@@ -9037,13 +11088,13 @@ mac_handle_mouse_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  OSStatus result, err;
+  OSStatus err, result = eventNotHandledErr;
 
   switch (GetEventKind (event))
     {
     case kEventMouseWheelMoved:
       {
-       WindowPtr wp;
+       WindowRef wp;
        struct frame *f;
        EventMouseWheelAxis axis;
        SInt32 delta;
@@ -9051,15 +11102,14 @@ mac_handle_mouse_event (next_handler, event, data)
 
        result = CallNextEventHandler (next_handler, event);
        if (result != eventNotHandledErr || read_socket_inev == NULL)
-         return result;
+         break;
+
+       f = mac_focus_frame (&one_mac_display_info);
 
        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))
+       if (err != noErr
+           || wp != FRAME_MAC_WINDOW (f))
          break;
 
        err = GetEventParameter (event, kEventParamMouseWheelAxis,
@@ -9068,291 +11118,487 @@ mac_handle_mouse_event (next_handler, event, data)
        if (err != noErr || axis != kEventMouseWheelAxisY)
          break;
 
-       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;
+
+       point.h -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
+       point.v -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
+       if (point.h < 0 || point.v < 0
+           || EQ (window_from_coordinates (f, point.h, point.v, 0, 0, 0, 1),
+                  f->tool_bar_window))
+         break;
+
+       err = GetEventParameter (event, kEventParamMouseWheelDelta,
+                                typeSInt32, NULL, sizeof (SInt32),
+                                NULL, &delta);
+       if (err != noErr)
+         break;
+
        read_socket_inev->kind = WHEEL_EVENT;
        read_socket_inev->code = 0;
        read_socket_inev->modifiers =
          (mac_event_to_emacs_modifiers (event)
           | ((delta < 0) ? down_modifier : up_modifier));
-       SetPortWindowPort (wp);
-       GlobalToLocal (&point);
        XSETINT (read_socket_inev->x, point.h);
        XSETINT (read_socket_inev->y, point.v);
        XSETFRAME (read_socket_inev->frame_or_window, f);
 
-       return noErr;
+       result = noErr;
+      }
+      break;
+
+    default:
+      abort ();
+    }
+
+  return result;
+}
+
+#if USE_MAC_TSM
+static pascal OSStatus
+mac_handle_text_input_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus err, result;
+  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);
+  if (result != eventNotHandledErr)
+    return result;
+
+  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++;
+      result = noErr;
+      break;
+
+    case kEventTextInputUnicodeForKeyEvent:
+      {
+       EventRef kbd_event;
+       UInt32 actual_size, 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 && mac_mapped_modifiers (modifiers))
+         /* There're mapped modifier keys.  Process it in
+            do_keystroke.  */
+         break;
+       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 do_keystroke.  */
+               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);
+                     }
+                 }
+               break;
+             }
+         }
+       if (err == noErr)
+         {
+           /* 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;
+           result = noErr;
+         }
+      }
+      break;
+
+    case kEventTextInputOffsetToPos:
+      {
+       struct frame *f;
+       struct window *w;
+       Point p;
+
+       if (!OVERLAYP (Vmac_ts_active_input_overlay))
+         break;
+
+       /* 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 around the current point.  */
+           f = SELECTED_FRAME ();
+           w = XWINDOW (f->selected_window);
+         }
+       else if (WINDOWP (echo_area_window))
+         {
+           /* Active input area is displayed in the echo area.  */
+           w = XWINDOW (echo_area_window);
+           f = WINDOW_XFRAME (w);
+         }
+       else
+         break;
+
+       p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
+              + WINDOW_LEFT_FRINGE_WIDTH (w)
+              + f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f));
+       p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
+              + FONT_BASE (FRAME_FONT (f))
+              + f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f));
+       err = SetEventParameter (event, kEventParamTextInputReplyPoint,
+                                typeQDPoint, sizeof (typeQDPoint), &p);
+       if (err == noErr)
+         result = noErr;
       }
       break;
 
     default:
-      break;
+      abort ();
     }
 
-  return eventNotHandledErr;
+  if (!NILP (id_key))
+    err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
+                                             event, num_params,
+                                             names, types);
+  return result;
 }
+#endif
+#endif /* TARGET_API_MAC_CARBON */
 
-#ifdef MAC_OSX
-OSErr
-mac_store_services_event (event)
-     EventRef event;
+
+OSStatus
+install_window_handler (window)
+     WindowRef window;
 {
-  OSErr err;
-  AppleEvent apple_event;
-  Lisp_Object id_key;
+  OSStatus err = noErr;
 
-  switch (GetEventKind (event))
+#if TARGET_API_MAC_CARBON
+  if (err == noErr)
     {
-    case kEventServicePaste:
-      id_key = Qpaste;
-      err = create_apple_event_from_event_ref (event, 0, NULL, NULL,
-                                              &apple_event);
-      break;
+      static const EventTypeSpec specs[] =
+       {
+         /* -- window refresh events -- */
+         {kEventClassWindow, kEventWindowUpdate},
+         /* -- window state change events -- */
+         {kEventClassWindow, kEventWindowShowing},
+         {kEventClassWindow, kEventWindowHiding},
+         {kEventClassWindow, kEventWindowShown},
+         {kEventClassWindow, kEventWindowHidden},
+         {kEventClassWindow, kEventWindowCollapsed},
+         {kEventClassWindow, kEventWindowExpanded},
+         {kEventClassWindow, kEventWindowBoundsChanging},
+         {kEventClassWindow, kEventWindowBoundsChanged},
+         /* -- window action events -- */
+         {kEventClassWindow, kEventWindowClose},
+         {kEventClassWindow, kEventWindowGetIdealSize},
+#ifdef MAC_OSX
+         {kEventClassWindow, kEventWindowToolbarSwitchMode},
+#endif
+#if USE_MAC_TSM
+         /* -- window focus events -- */
+         {kEventClassWindow, kEventWindowFocusAcquired},
+         {kEventClassWindow, kEventWindowFocusRelinquish},
+#endif
+       };
+      static EventHandlerUPP handle_window_eventUPP = NULL;
 
-    case kEventServicePerform:
-      {
-       static EventParamName names[] = {kEventParamServiceMessageName,
-                                        kEventParamServiceUserData};
-       static EventParamType types[] = {typeCFStringRef,
-                                        typeCFStringRef};
-
-       id_key = Qperform;
-       err = create_apple_event_from_event_ref (event, 2, names, types,
-                                                &apple_event);
-      }
-      break;
+      if (handle_window_eventUPP == NULL)
+       handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
 
-    default:
-      abort ();
+      err = InstallWindowEventHandler (window, handle_window_eventUPP,
+                                      GetEventTypeCount (specs),
+                                      specs, NULL, NULL);
     }
+#endif
 
   if (err == noErr)
-    {
-      err = mac_store_apple_event (Qservices, id_key, &apple_event);
-      AEDisposeDesc (&apple_event);
-    }
+    err = install_drag_handler (window);
 
   return err;
 }
-#endif /* MAC_OSX */
-#endif /* USE_CARBON_EVENTS */
 
+void
+remove_window_handler (window)
+     WindowRef window;
+{
+  remove_drag_handler (window);
+}
 
-OSErr
-install_window_handler (window)
-     WindowPtr window;
+#if TARGET_API_MAC_CARBON
+static OSStatus
+install_application_handler ()
 {
-  OSErr err = noErr;
-#if USE_CARBON_EVENTS
-  EventTypeSpec specs_window[] =
-    {{kEventClassWindow, kEventWindowUpdate},
-     {kEventClassWindow, kEventWindowBoundsChanging},
-     {kEventClassWindow, kEventWindowShown},
-     {kEventClassWindow, kEventWindowHidden},
-     {kEventClassWindow, kEventWindowExpanded},
-     {kEventClassWindow, kEventWindowCollapsed}};
-  EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
-  static EventHandlerUPP handle_window_eventUPP = NULL;
-  static EventHandlerUPP handle_mouse_eventUPP = NULL;
-
-  if (handle_window_eventUPP == NULL)
-    handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
-  if (handle_mouse_eventUPP == NULL)
-    handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
-  err = InstallWindowEventHandler (window, handle_window_eventUPP,
-                                  GetEventTypeCount (specs_window),
-                                  specs_window, NULL, NULL);
+  OSStatus err = noErr;
+
   if (err == noErr)
-    err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
-                                    GetEventTypeCount (specs_mouse),
-                                    specs_mouse, NULL, NULL);
+    {
+      static const EventTypeSpec specs[] = {
+#if USE_MAC_TSM
+       {kEventClassApplication, kEventAppActivated},
+       {kEventClassApplication, kEventAppDeactivated},
 #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);
+      };
+
+      err = InstallApplicationEventHandler (NewEventHandlerUPP
+                                           (mac_handle_application_event),
+                                           GetEventTypeCount (specs),
+                                           specs, NULL, NULL);
+    }
+
+  if (err == noErr)
+    {
+      static const EventTypeSpec specs[] =
+       {{kEventClassKeyboard, kEventRawKeyDown},
+        {kEventClassKeyboard, kEventRawKeyRepeat},
+        {kEventClassKeyboard, kEventRawKeyUp}};
+
+      err = InstallApplicationEventHandler (NewEventHandlerUPP
+                                           (mac_handle_keyboard_event),
+                                           GetEventTypeCount (specs),
+                                           specs, NULL, NULL);
+    }
+
+  if (err == noErr)
+    {
+      static const EventTypeSpec specs[] =
+       {{kEventClassCommand, kEventCommandProcess}};
+
+      err = InstallApplicationEventHandler (NewEventHandlerUPP
+                                           (mac_handle_command_event),
+                                           GetEventTypeCount (specs),
+                                           specs, NULL, NULL);
+    }
+
+  if (err == noErr)
+    {
+      static const EventTypeSpec specs[] =
+       {{kEventClassMouse, kEventMouseWheelMoved}};
+
+      err = InstallApplicationEventHandler (NewEventHandlerUPP
+                                           (mac_handle_mouse_event),
+                                           GetEventTypeCount (specs),
+                                           specs, NULL, NULL);
+    }
 
+#if USE_MAC_TSM
   if (err == noErr)
-    err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL);
+    {
+      static const EventTypeSpec spec[] =
+       {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
+        {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
+        {kEventClassTextInput, kEventTextInputOffsetToPos}};
+
+      err = InstallApplicationEventHandler (NewEventHandlerUPP
+                                           (mac_handle_text_input_event),
+                                           GetEventTypeCount (spec),
+                                           spec, NULL, NULL);
+    }
+#endif
+
+  if (err == noErr)
+    err = install_menu_target_item_handler ();
+
+#ifdef MAC_OSX
   if (err == noErr)
-    err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
+    err = install_service_handler ();
 #endif
+
   return err;
 }
+#endif
 
-void
-remove_window_handler (window)
-     WindowPtr window;
+static pascal void
+mac_handle_dm_notification (event)
+     AppleEvent *event;
 {
-#if TARGET_API_MAC_CARBON
-  if (mac_do_track_dragUPP)
-    RemoveTrackingHandler (mac_do_track_dragUPP, window);
-  if (mac_do_receive_dragUPP)
-    RemoveReceiveHandler (mac_do_receive_dragUPP, window);
-#endif
+  mac_screen_config_changed = 1;
 }
 
-#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;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+static void
+mac_handle_cg_display_reconfig (display, flags, user_info)
+     CGDirectDisplayID display;
+     CGDisplayChangeSummaryFlags flags;
+     void *user_info;
+{
+  mac_screen_config_changed = 1;
+}
+#endif
 
-    case kDragTrackingInWindow:
-      break;
+static OSErr
+init_dm_notification_handler ()
+{
+  OSErr err = noErr;
 
-    case kDragTrackingLeaveWindow:
-      if (can_accept)
-       {
-         struct frame *f = mac_window_to_frame (window);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  if (CGDisplayRegisterReconfigurationCallback != NULL)
+#endif
+    {
+      CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
+                                               NULL);
+    }
+#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+  else         /* CGDisplayRegisterReconfigurationCallback == NULL */
+#endif
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
+    {
+      static DMNotificationUPP handle_dm_notificationUPP = NULL;
+      ProcessSerialNumber psn;
 
-         HideDragHilite (theDrag);
-         SetThemeCursor (kThemeArrowCursor);
-       }
-      break;
+      if (handle_dm_notificationUPP == NULL)
+       handle_dm_notificationUPP =
+         NewDMNotificationUPP (mac_handle_dm_notification);
 
-    case kDragTrackingLeaveHandler:
-      break;
+      err = GetCurrentProcess (&psn);
+      if (err == noErr)
+       err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
     }
+#endif
 
-  return noErr;
+  return err;
 }
 
-static pascal OSErr
-mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
-                    DragReference theDrag)
+static void
+mac_get_screen_info (dpyinfo)
+     struct mac_display_info *dpyinfo;
 {
-  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;
+#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.  */
+  dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
+  dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
+  {
+    CGDisplayErr err;
+    CGDisplayCount ndisps;
+    CGDirectDisplayID *displays;
 
-  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)
-       {
-         OSErr err;
-         AEDesc desc;
+    err = CGGetActiveDisplayList (0, NULL, &ndisps);
+    if (err == noErr)
+      {
+       displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
+       err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
+      }
+    if (err == noErr)
+      {
+       CGRect bounds = CGRectZero;
 
-         err = GetFlavorData (theDrag, theItem, flavorTypeHFS,
-                              &data, &size, 0L);
-         if (err == noErr)
-           err = AECoercePtr (typeFSS, &data.fileSpec, sizeof (FSSpec),
-                              TYPE_FILE_NAME, &desc);
-         if (err == noErr)
-           {
-             Lisp_Object file;
-
-             /* x-dnd functions expect undecoded filenames.  */
-             file = make_uninit_string (AEGetDescDataSize (&desc));
-             err = AEGetDescData (&desc, SDATA (file), SBYTES (file));
-             if (err == noErr)
-               file_list = Fcons (file, file_list);
-             AEDisposeDesc (&desc);
-           }
-       }
-    }
-  /* If there are items in the list, construct an event and post it to
-     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 */
+       while (ndisps-- > 0)
+         bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
+       dpyinfo->height = CGRectGetHeight (bounds);
+       dpyinfo->width = CGRectGetWidth (bounds);
+      }
+    else
       {
-       ProcessSerialNumber psn;
-       GetCurrentProcess (&psn);
-       SetFrontProcess (&psn);
+       dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
+       dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
       }
+  }
+#else  /* !MAC_OSX */
+  {
+    GDHandle gdh = GetMainDevice ();
+    Rect rect = (**gdh).gdRect;
 
-      return noErr;
-    }
-  else
-    return dragNotAcceptedErr;
+    dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
+    for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
+      if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
+       break;
+
+    for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
+        gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
+      UnionRect (&rect, &(**gdh).gdRect, &rect);
+
+    dpyinfo->height = rect.bottom - rect.top;
+    dpyinfo->width = rect.right - rect.left;
+  }
+#endif  /* !MAC_OSX */
 }
-#endif
 
 
 #if __profile__
@@ -9390,7 +11636,7 @@ main (void)
 
 #if __MWERKS__
   /* set creator and type for files created by MSL */
-  _fcreator = 'EMAx';
+  _fcreator = MAC_EMACS_CREATOR_CODE;
   _ftype = 'TEXT';
 #endif
 
@@ -9412,6 +11658,8 @@ main (void)
 
   init_apple_event_handler ();
 
+  init_dm_notification_handler ();
+
   {
     char **argv;
     int argc = 0;
@@ -9437,170 +11685,7 @@ 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.
-
-  */
-  OSStatus err;
-  UInt32 mods = 0;
-  if (!NILP(Vmac_function_modifier))
-    {
-      err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
-                              NULL, sizeof (UInt32), NULL, &mods);
-      if (err != noErr && mods & kEventKeyModifierFnMask)
-       {  *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
-
-         return (*newCode != 0);
-       }
-    }
-#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
+#if !TARGET_API_MAC_CARBON
 static RgnHandle mouse_region = NULL;
 
 Boolean
@@ -9632,12 +11717,46 @@ mac_wait_next_event (er, sleep_time, dequeue)
          return false;
       }
 
-  *er = er_buf;
-  if (dequeue)
-    er_buf.what = nullEvent;
-  return true;
+  *er = er_buf;
+  if (dequeue)
+    er_buf.what = nullEvent;
+  return true;
+}
+#endif /* not TARGET_API_MAC_CARBON */
+
+#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;
+
+      GetGlobalMouse (&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;
 }
-#endif /* not USE_CARBON_EVENTS */
+#endif
 
 /* Emacs calls this whenever it wants to read an input event from the
    user. */
@@ -9648,7 +11767,7 @@ XTread_socket (sd, expected, hold_quit)
 {
   struct input_event inev;
   int count = 0;
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
   EventRef eventRef;
   EventTargetRef toolbox_dispatcher;
 #endif
@@ -9669,65 +11788,54 @@ XTread_socket (sd, expected, hold_quit)
 
   ++handling_signal;
 
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
   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 */
+#else /* !TARGET_API_MAC_CARBON */
   while (mac_wait_next_event (&er, 0, true))
-#endif /* !USE_CARBON_EVENTS */
+#endif /* !TARGET_API_MAC_CARBON */
     {
       int do_help = 0;
       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;
 
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
       timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
-#else
-      timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
-#endif
 
-#if USE_CARBON_EVENTS
-      /* Handle new events */
       if (!mac_convert_event_ref (eventRef, &er))
-       {
-         /* There used to be a handler for the kEventMouseWheelMoved
-            event here.  But as of Mac OS X 10.4, this kind of event
-            is not directly posted to the main event queue by
-            two-finger scrolling on the trackpad.  Instead, some
-            private event is posted and it is converted to a wheel
-            event by the default handler for the application target.
-            The converted one can be received by a Carbon event
-            handler installed on a window target.  */
-         read_socket_inev = &inev;
-         SendEventToEventTarget (eventRef, toolbox_dispatcher);
-         read_socket_inev = NULL;
-       }
-      else
-#endif /* USE_CARBON_EVENTS */
+       goto OTHER;
+#else  /* !TARGET_API_MAC_CARBON */
+      timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
+#endif  /* !TARGET_API_MAC_CARBON */
+
       switch (er.what)
        {
        case mouseDown:
        case mouseUp:
          {
-           WindowPtr window_ptr;
+           WindowRef window_ptr;
            ControlPartCode part_code;
            int tool_bar_p = 0;
 
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
+           OSStatus err;
+
            /* This is needed to send mouse events like aqua window
               buttons to the correct handler.  */
-           if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
-               != eventNotHandledErr)
+           read_socket_inev = &inev;
+           err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
+           read_socket_inev = NULL;
+           if (err != eventNotHandledErr)
              break;
 #endif
            last_mouse_glyph_frame = 0;
@@ -9762,22 +11870,33 @@ 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
+                   || (mac_window_to_frame (window_ptr)
+                       != dpyinfo->x_focus_frame))
                  SelectWindow (window_ptr);
                else
                  {
                    ControlPartCode control_part_code;
-                   ControlHandle ch;
-                   Point mouse_loc = er.where;
+                   ControlRef ch;
+                   Point mouse_loc;
 #ifdef MAC_OSX
                    ControlKind control_kind;
 #endif
 
                    f = mac_window_to_frame (window_ptr);
                    /* convert to local coordinates of new window */
-                   SetPortWindowPort (window_ptr);
-
-                   GlobalToLocal (&mouse_loc);
+                   mouse_loc.h = (er.where.h
+                                  - (f->left_pos
+                                     + FRAME_OUTER_TO_INNER_DIFF_X (f)));
+                   mouse_loc.v = (er.where.v
+                                  - (f->top_pos
+                                     + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
 #if TARGET_API_MAC_CARBON
                    ch = FindControlUnderMouse (mouse_loc, window_ptr,
                                                &control_part_code);
@@ -9790,7 +11909,7 @@ XTread_socket (sd, expected, hold_quit)
                                                     &ch);
 #endif
 
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
                    inev.code = mac_get_mouse_btn (eventRef);
                    inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
@@ -9800,18 +11919,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;
 
@@ -9827,12 +11946,12 @@ XTread_socket (sd, expected, hold_quit)
 #ifdef USE_TOOLKIT_SCROLL_BARS
                        /* Make the "Ctrl-Mouse-2 splits window" work
                           for toolkit scroll bars.  */
-                       if (er.modifiers & controlKey)
+                       if (inev.modifiers & ctrl_modifier)
                          x_scroll_bar_handle_click (bar, control_part_code,
                                                     &er, &inev);
                        else if (er.what == mouseDown)
                          x_scroll_bar_handle_press (bar, control_part_code,
-                                                    &inev);
+                                                    mouse_loc, &inev);
                        else
                          x_scroll_bar_handle_release (bar, &inev);
 #else  /* not USE_TOOLKIT_SCROLL_BARS */
@@ -9895,7 +12014,9 @@ XTread_socket (sd, expected, hold_quit)
                      f->mouse_moved = 0;
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
-                   if (inev.kind == MOUSE_CLICK_EVENT)
+                   if (inev.kind == MOUSE_CLICK_EVENT
+                       || (inev.kind == SCROLL_BAR_CLICK_EVENT
+                           && (inev.modifiers & ctrl_modifier)))
 #endif
                      switch (er.what)
                        {
@@ -9911,17 +12032,27 @@ 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.  */
                {
                  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 /* not TARGET_API_MAC_CARBON */
                break;
 
              case inGoAway:
@@ -9945,39 +12076,38 @@ XTread_socket (sd, expected, hold_quit)
                  do_zoom_window (window_ptr, part_code);
                break;
 
+#if USE_MAC_TOOLBAR
+             case inStructure:
+               {
+                 OSStatus err;
+                 HIViewRef ch;
+
+                 err = HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr),
+                                                   eventRef, &ch);
+                 /* This doesn't work on Mac OS X 10.2.  */
+                 if (err == noErr)
+                   HIViewClick (ch, eventRef);
+               }
+               break;
+#endif /* USE_MAC_TOOLBAR */
+
              default:
                break;
              }
          }
          break;
 
+#if !TARGET_API_MAC_CARBON
        case updateEvt:
-#if USE_CARBON_EVENTS
-         if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
-             != eventNotHandledErr)
-           break;
-#else
-         do_window_update ((WindowPtr) er.message);
-#endif
+         do_window_update ((WindowRef) er.message);
          break;
+#endif
 
        case osEvt:
-#if USE_CARBON_EVENTS
-         if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
-             != eventNotHandledErr)
-           break;
-#endif
          switch ((er.message >> 24) & 0x000000FF)
            {
-           case suspendResumeMessage:
-             if ((er.message & resumeFlag) == 1)
-               do_app_resume ();
-             else
-               do_app_suspend ();
-             break;
-
            case mouseMovedMessage:
-#if !USE_CARBON_EVENTS
+#if !TARGET_API_MAC_CARBON
              SetRectRgn (mouse_region, er.where.h, er.where.v,
                          er.where.h + 1, er.where.v + 1);
 #endif
@@ -9998,13 +12128,15 @@ XTread_socket (sd, expected, hold_quit)
 
              if (f)
                {
-                 WindowPtr wp = FRAME_MAC_WINDOW (f);
-                 Point mouse_pos = er.where;
-
-                 SetPortWindowPort (wp);
-
-                 GlobalToLocal (&mouse_pos);
-
+                 WindowRef wp = FRAME_MAC_WINDOW (f);
+                 Point mouse_pos;
+
+                 mouse_pos.h = (er.where.h
+                                - (f->left_pos
+                                   + FRAME_OUTER_TO_INNER_DIFF_X (f)));
+                 mouse_pos.v = (er.where.v
+                                - (f->top_pos
+                                   + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
                  if (dpyinfo->grabbed && tracked_scroll_bar)
 #ifdef USE_TOOLKIT_SCROLL_BARS
                    x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
@@ -10018,7 +12150,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;
 
@@ -10043,6 +12175,10 @@ XTread_socket (sd, expected, hold_quit)
                        }
                      if (!note_mouse_movement (f, &mouse_pos))
                        help_echo_string = previous_help_echo_string;
+#if USE_MAC_TOOLBAR
+                     else
+                       mac_tool_bar_note_mouse_movement (f, eventRef);
+#endif
                    }
                }
 
@@ -10052,18 +12188,16 @@ XTread_socket (sd, expected, hold_quit)
              if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
                do_help = 1;
              break;
+
+           default:
+             goto OTHER;
            }
          break;
 
        case activateEvt:
          {
-           WindowPtr window_ptr = (WindowPtr) er.message;
+           WindowRef window_ptr = (WindowRef) er.message;
 
-#if USE_CARBON_EVENTS
-           if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
-               != eventNotHandledErr)
-             break;
-#endif
            if (window_ptr == tip_window)
              {
                HideWindow (tip_window);
@@ -10071,26 +12205,31 @@ XTread_socket (sd, expected, hold_quit)
              }
 
            if (!is_emacs_window (window_ptr))
-             break;
+             goto OTHER;
+
+           f = mac_window_to_frame (window_ptr);
 
            if ((er.modifiers & activeFlag) != 0)
              {
                /* A window has been activated */
-               Point mouse_loc = er.where;
+               Point mouse_loc;
 
                x_detect_focus_change (dpyinfo, &er, &inev);
 
-               SetPortWindowPort (window_ptr);
-               GlobalToLocal (&mouse_loc);
+               mouse_loc.h = (er.where.h
+                              - (f->left_pos
+                                 + FRAME_OUTER_TO_INNER_DIFF_X (f)));
+               mouse_loc.v = (er.where.v
+                              - (f->top_pos
+                                 + FRAME_OUTER_TO_INNER_DIFF_Y (f)));
                /* Window-activated event counts as mouse movement,
                   so update things that depend on mouse position.  */
-               note_mouse_movement (mac_window_to_frame (window_ptr),
-                                    &mouse_loc);
+               note_mouse_movement (f, &mouse_loc);
              }
            else
              {
                /* A window has been deactivated */
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
                if (dpyinfo->grabbed && tracked_scroll_bar)
                  {
                    struct input_event event;
@@ -10110,7 +12249,6 @@ XTread_socket (sd, expected, hold_quit)
 
                x_detect_focus_change (dpyinfo, &er, &inev);
 
-               f = mac_window_to_frame (window_ptr);
                if (f == dpyinfo->mouse_face_mouse_frame)
                  {
                    /* If we move outside the frame, then we're
@@ -10131,116 +12269,48 @@ XTread_socket (sd, expected, hold_quit)
          break;
 
        case keyDown:
+       case keyUp:
        case autoKey:
-         {
-           int keycode = (er.message & keyCodeMask) >> 8;
-           int xkeysym;
-
-#if USE_CARBON_EVENTS && defined (MAC_OSX)
-           /* 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
+         ObscureCursor ();
 
-#if 0
-           if (dpyinfo->x_focus_frame == NULL)
-             {
-               /* Beep if keyboard input occurs when all the frames
-                  are invisible.  */
-               SysBeep (1);
-               break;
-             }
-#endif
+         f = mac_focus_frame (dpyinfo);
+         XSETFRAME (inev.frame_or_window, f);
 
+         /* If mouse-highlight is an integer, input clears out mouse
+            highlighting.  */
+         if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+             && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
            {
-             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;
+             clear_mouse_face (dpyinfo);
+             dpyinfo->mouse_face_hidden = 1;
            }
-
-           ObscureCursor ();
-
-           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
-             {
-               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))
-             {
-               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;
-             }
-           else
-#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);
+#if TARGET_API_MAC_CARBON
+         goto OTHER;
 #else
-         inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+         do_keystroke (er.what, er.message & charCodeMask,
+                       (er.message & keyCodeMask) >> 8,
+                       er.modifiers, timestamp, &inev);
 #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:
+       OTHER:
+#if TARGET_API_MAC_CARBON
+         {
+           OSStatus err;
+
+           read_socket_inev = &inev;
+           err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
+           read_socket_inev = NULL;
+         }
+#endif
          break;
        }
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
       ReleaseEvent (eventRef);
 #endif
 
@@ -10286,7 +12356,13 @@ XTread_socket (sd, expected, hold_quit)
       pending_autoraise_frame = 0;
     }
 
-#if !USE_CARBON_EVENTS
+  if (mac_screen_config_changed)
+    {
+      mac_get_screen_info (dpyinfo);
+      mac_screen_config_changed = 0;
+    }
+
+#if !TARGET_API_MAC_CARBON
   /* Check which frames are still visible.  We do this here because
      there doesn't seem to be any direct notification from the Window
      Manager that the visibility of a window has changed (at least,
@@ -10391,7 +12467,7 @@ make_mac_terminal_frame (struct frame *f)
 
   if (!(FRAME_MAC_WINDOW (f) =
        NewCWindow (NULL, &r, "\p", true, dBoxProc,
-                   (WindowPtr) -1, 1, (long) f->output_data.mac)))
+                   (WindowRef) -1, 1, (long) f->output_data.mac)))
     abort ();
   /* so that update events can find this mac_output struct */
   f->output_data.mac->mFP = f;  /* point back to emacs frame */
@@ -10420,75 +12496,11 @@ make_mac_terminal_frame (struct frame *f)
                            Initialization
  ***********************************************************************/
 
-int mac_initialized = 0;
-
-void
-mac_initialize_display_info ()
-{
-  struct mac_display_info *dpyinfo = &one_mac_display_info;
-  GDHandle main_device_handle;
-
-  bzero (dpyinfo, sizeof (*dpyinfo));
-
-#ifdef MAC_OSX
-  dpyinfo->mac_id_name
-    = (char *) xmalloc (SCHARS (Vinvocation_name)
-                       + SCHARS (Vsystem_name)
-                       + 2);
-  sprintf (dpyinfo->mac_id_name, "%s@%s",
-          SDATA (Vinvocation_name), SDATA (Vsystem_name));
-#else
-  dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
-  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.  */
-  {
-    CGDirectDisplayID disp_id[1];
-    CGDisplayCount disp_count;
-    CGDisplayErr error_code;
-
-    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]);
-  }
-#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 ();
-
-  dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
-  dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
-  dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
-  dpyinfo->mouse_face_window = Qnil;
-  dpyinfo->mouse_face_overlay = Qnil;
-  dpyinfo->mouse_face_hidden = 0;
-}
-
+static int mac_initialized = 0;
 
 static XrmDatabase
 mac_make_rdb (xrm_option)
-     char *xrm_option;
+     const char *xrm_option;
 {
   XrmDatabase database;
 
@@ -10518,9 +12530,37 @@ mac_term_init (display_name, xrm_option, resource_name)
   if (x_display_list)
     error ("Sorry, this version can only handle one display");
 
-  mac_initialize_display_info ();
-
   dpyinfo = &one_mac_display_info;
+  bzero (dpyinfo, sizeof (*dpyinfo));
+
+#ifdef MAC_OSX
+  dpyinfo->mac_id_name
+    = (char *) xmalloc (SCHARS (Vinvocation_name)
+                       + SCHARS (Vsystem_name)
+                       + 2);
+  sprintf (dpyinfo->mac_id_name, "%s@%s",
+          SDATA (Vinvocation_name), SDATA (Vsystem_name));
+#else
+  dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
+  strcpy (dpyinfo->mac_id_name, "Mac Display");
+#endif
+
+  dpyinfo->reference_count = 0;
+  dpyinfo->resx = 72.0;
+  dpyinfo->resy = 72.0;
+
+  mac_get_screen_info (dpyinfo);
+
+  dpyinfo->grabbed = 0;
+  dpyinfo->root_window = NULL;
+  dpyinfo->image_cache = make_image_cache ();
+
+  dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+  dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+  dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
+  dpyinfo->mouse_face_window = Qnil;
+  dpyinfo->mouse_face_overlay = Qnil;
+  dpyinfo->mouse_face_hidden = 0;
 
   dpyinfo->xrdb = mac_make_rdb (xrm_option);
 
@@ -10538,6 +12578,7 @@ mac_term_init (display_name, xrm_option, resource_name)
 
   return dpyinfo;
 }
+\f
 /* Get rid of display DPYINFO, assuming all frames are already gone.  */
 
 void
@@ -10587,11 +12628,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)
     {
@@ -10601,85 +12645,11 @@ x_delete_display (dpyinfo)
 }
 
 \f
-#ifdef MAC_OSX
-void
-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)
-    return;
-
-  appsBundle = CFBundleGetMainBundle();
-  if (appsBundle != NULL)
-    {
-      CFStringRef cfBI = CFSTR("CFBundleIdentifier");
-      CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
-      /* We found the bundle identifier, now we know we are valid. */
-      if (res != NULL)
-       {
-         CFRelease(res);
-         return;
-       }
-    }
-  /* MAC_TODO:  Have this start the bundled executable */
-
-  /* For now, prevent the fatal error by bringing it up in the terminal */
-  inhibit_window_system = 1;
-}
-
-void
-MakeMeTheFrontProcess ()
-{
-  ProcessSerialNumber psn;
-  OSErr err;
-
-  err = GetCurrentProcess (&psn);
-  if (err == noErr)
-    (void) SetFrontProcess (&psn);
-}
-
-/***** Code to handle C-g testing  *****/
-
-/* Contains the Mac modifier formed from quit_char */
-int mac_quit_char_modifiers = 0;
-int mac_quit_char_keycode;
-extern int quit_char;
-
-static void
-mac_determine_quit_char_modifiers()
-{
-  /* Todo: Determine modifiers from quit_char. */
-  UInt32 qc_modifiers = ctrl_modifier;
-
-  /* Map modifiers */
-  mac_quit_char_modifiers = 0;
-  if (qc_modifiers & ctrl_modifier)  mac_quit_char_modifiers |= controlKey;
-  if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
-  if (qc_modifiers & alt_modifier)   mac_quit_char_modifiers |= optionKey;
-}
-
-static void
-init_quit_char_handler ()
-{
-  /* TODO: Let this support keys other the 'g' */
-  mac_quit_char_keycode = 5;
-  /* Look at <architecture/adb_kb_map.h> for details */
-  /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
-
-  mac_determine_quit_char_modifiers();
-}
-#endif /* MAC_OSX */
-
 static void
 init_menu_bar ()
 {
 #ifdef MAC_OSX
-  OSErr err;
+  OSStatus err;
   MenuRef menu;
   MenuItemIndex menu_index;
 
@@ -10687,7 +12657,6 @@ init_menu_bar ()
                                     &menu, &menu_index);
   if (err == noErr)
     SetMenuItemCommandKey (menu, menu_index, false, 0);
-#if USE_CARBON_EVENTS
   EnableMenuCommand (NULL, kHICommandPreferences);
   err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
                                     &menu, &menu_index);
@@ -10699,14 +12668,27 @@ init_menu_bar ()
       InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
                                      0, 0, kHICommandAbout);
     }
-#endif /* USE_CARBON_EVENTS */
 #else  /* !MAC_OSX */
-#if USE_CARBON_EVENTS
-  SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout);
+#if TARGET_API_MAC_CARBON
+  SetMenuItemCommandID (GetMenuRef (M_APPLE), I_ABOUT, kHICommandAbout);
 #endif
 #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.  */
 
@@ -10725,13 +12707,22 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   x_cursor_to,
   x_flush,
+#if USE_CG_DRAWING
+  mac_flush_display_optional,
+#else
   0, /* flush_display_optional */
+#endif
   x_clear_window_mouse_face,
   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,
@@ -10786,27 +12777,36 @@ mac_initialize ()
 
 #if TARGET_API_MAC_CARBON
 
-#if USE_CARBON_EVENTS
-#ifdef MAC_OSX
-  init_service_handler ();
-
-  init_quit_char_handler ();
-#endif /* MAC_OSX */
-
-  init_command_handler ();
+  install_application_handler ();
 
   init_menu_bar ();
-#endif /* USE_CARBON_EVENTS */
+
+#if USE_MAC_TSM
+  init_tsm ();
+#endif
 
 #ifdef MAC_OSX
   init_coercion_handler ();
 
   init_apple_event_handler ();
 
+  init_dm_notification_handler ();
+
   if (!inhibit_window_system)
-    MakeMeTheFrontProcess ();
+    {
+      static const ProcessSerialNumber psn = {0, kCurrentProcess};
+
+      SetFrontProcess (&psn);
+    }
 #endif
 #endif
+
+#if USE_CG_DRAWING
+  init_cg_color ();
+
+  mac_init_fringe ();
+#endif
+
   UNBLOCK_INPUT;
 }
 
@@ -10833,13 +12833,27 @@ syms_of_macterm ()
   Fput (Qhyper,   Qmodifier_value, make_number (hyper_modifier));
   Fput (Qsuper,   Qmodifier_value, make_number (super_modifier));
 
-#if USE_CARBON_EVENTS
-  Qhicommand   = intern ("hicommand");    staticpro (&Qhicommand);
+#if TARGET_API_MAC_CARBON
+  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
@@ -10861,6 +12875,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
@@ -10868,15 +12890,23 @@ syms_of_macterm ()
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
-nil means ignore them.  If you encounter fonts with bogus
+A value of nil means ignore them.  If you encounter fonts with bogus
 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
 to 4.1, set this to nil.
 
 NOTE: Not supported on Mac yet.  */);
   x_use_underline_position_properties = 0;
 
+  DEFVAR_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.
+A value of 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
@@ -10919,8 +12949,8 @@ unexpected results for some keys on non-US/GB keyboards.  */);
               &Vmac_emulate_three_button_mouse,
     doc: /* *Specify a way of three button mouse emulation.
 The value can be nil, t, or the symbol `reverse'.
-nil means that no emulation should be done and the modifiers should be
-placed on the mouse-1 event.
+A value of nil means that no emulation should be done and the modifiers
+should be placed on the mouse-1 event.
 t means that when the option-key is held down while pressing the mouse
 button, the click will register as mouse-2 and while the command-key
 is held down, the click will register as mouse-3.
@@ -10928,34 +12958,38 @@ The symbol `reverse' means that the option-key will register for
 mouse-3 and the command-key will register for mouse-2.  */);
   Vmac_emulate_three_button_mouse = Qnil;
 
-#if USE_CARBON_EVENTS
+#if TARGET_API_MAC_CARBON
   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)
@@ -10966,6 +13000,21 @@ 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_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