]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
*** empty log message ***
[gnu-emacs] / src / macterm.c
index ebebb129bb8304c997f5974179463190ed41f14f..535d433bb37d902c3efe811716a19cda2dd845e4 100644 (file)
@@ -1,5 +1,6 @@
 /* Implementation of GUI terminal on the Mac OS.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004,
+                 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -15,17 +16,17 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* Contributed by Andrew Choi (akochoi@mac.com).  */
 
 #include <config.h>
 #include <signal.h>
+
 #include <stdio.h>
-#include <stdlib.h>
+
 #include "lisp.h"
-#include "charset.h"
 #include "blockinput.h"
 
 #include "macterm.h"
@@ -34,12 +35,12 @@ Boston, MA 02111-1307, USA.  */
 #include <alloca.h>
 #endif
 
-#ifdef MAC_OSX
+#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 MAC_OSX */
+#else /* not TARGET_API_MAC_CARBON */
 #include <Quickdraw.h>
 #include <ToolUtils.h>
 #include <Sound.h>
@@ -58,42 +59,31 @@ Boston, MA 02111-1307, USA.  */
 #if __profile__
 #include <profiler.h>
 #endif
-#endif /* not MAC_OSX */
+#endif /* not TARGET_API_MAC_CARBON */
 
 #include "systty.h"
 #include "systime.h"
-#include "atimer.h"
-#include "keymap.h"
 
 #include <ctype.h>
 #include <errno.h>
 #include <setjmp.h>
 #include <sys/stat.h>
-#include <sys/param.h>
 
-#include "keyboard.h"
+#include "charset.h"
+#include "coding.h"
 #include "frame.h"
 #include "dispextern.h"
 #include "fontset.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
-#include "gnu.h"
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
+#include "keyboard.h"
 #include "intervals.h"
-#include "composite.h"
-#include "coding.h"
-
-/* Set of macros that handle mapping of Mac modifier keys to emacs.  */
-#define macCtrlKey     (NILP (Vmac_reverse_ctrl_meta) ? controlKey :   \
-                       (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
-#define macShiftKey    (shiftKey)
-#define macMetaKey     (NILP (Vmac_reverse_ctrl_meta) ?                        \
-                       (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
-                       : controlKey)
-#define macAltKey      (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
+#include "atimer.h"
+#include "keymap.h"
 
 \f
 
@@ -101,8 +91,9 @@ Boston, MA 02111-1307, USA.  */
 
 Lisp_Object Vx_toolkit_scroll_bars;
 
-/* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text.  */
-Lisp_Object Vmac_use_core_graphics;
+/* If non-zero, the text will be rendered using Core Graphics text
+   rendering which may anti-alias the text.  */
+int mac_use_core_graphics;
 
 
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
@@ -110,28 +101,25 @@ Lisp_Object Vmac_use_core_graphics;
 
 static int any_help_event_p;
 
-/* Non-zero means autoselect window with the mouse cursor.  */
-
-int x_autoselect_window_p;
-
-/* Non-zero means make use of UNDERLINE_POSITION font properties.  */
+/* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
+static Lisp_Object last_window;
 
+/* Non-zero means make use of UNDERLINE_POSITION font properties.
+   (Not yet supported.)  */
 int x_use_underline_position_properties;
 
-/* Non-zero means draw block and hollow cursor as wide as the glyph
-   under it.  For example, if a block cursor is over a tab, it will be
-   drawn as wide as that tab on the display.  */
-
-
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
 struct x_display_info *x_display_list;
 
 /* This is a list of cons cells, each of the form (NAME
-   . FONT-LIST-CACHE), one for each element of x_display_list and in
-   the same order.  NAME is the name of the frame.  FONT-LIST-CACHE
-   records previous values returned by x-list-fonts.  */
+   FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
+   x_display_list and in the same order.  NAME is the name of the
+   frame.  FONT-LIST-CACHE records previous values returned by
+   x-list-fonts.  RESOURCE-DATABASE preserves the X Resource Database
+   equivalent, which is implemented with a Lisp object, for the
+   display. */
 
 Lisp_Object x_display_name_list;
 
@@ -145,16 +133,10 @@ struct mac_display_info one_mac_display_info;
 
 extern struct frame *updating_frame;
 
-extern int waiting_for_input;
-
 /* This is a frame waiting to be auto-raised, within XTread_socket.  */
 
 struct frame *pending_autoraise_frame;
 
-/* Non-zero means user is interacting with a toolkit scroll bar.  */
-
-static int toolkit_scroll_bar_interaction;
-
 /* Mouse movement.
 
    Formerly, we used PointerMotionHintMask (in standard_event_mask)
@@ -178,7 +160,7 @@ static int toolkit_scroll_bar_interaction;
 /* Where the mouse was last time we reported a mouse event.  */
 
 static Rect last_mouse_glyph;
-static Lisp_Object last_mouse_press_frame;
+static FRAME_PTR last_mouse_glyph_frame;
 
 /* The scroll bar in which the last X motion event occurred.
 
@@ -212,49 +194,26 @@ static int volatile input_signal_count;
 static int input_signal_count;
 #endif
 
-/* Used locally within XTread_socket.  */
-
-static int x_noop_count;
-
-/* Initial values of argv and argc.  */
-
-extern char **initial_argv;
-extern int initial_argc;
-
-extern Lisp_Object Vcommand_line_args, Vsystem_name;
-
-/* Tells if a window manager is present or not.  */
-
-extern Lisp_Object Vx_no_window_manager;
-
-extern int errno;
+extern Lisp_Object Vsystem_name;
 
 /* A mask of extra modifier bits to put into every keyboard char.  */
 
-extern int extra_keyboard_modifiers;
+extern EMACS_INT extra_keyboard_modifiers;
 
 /* The keysyms to use for the various modifiers.  */
 
-static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
-
-static Lisp_Object Qvendor_specific_keysyms;
-
-#if 0
-extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
-#endif
+static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
 
 extern int inhibit_window_system;
 
-#if __MRC__
+#if __MRC__ && !TARGET_API_MAC_CARBON
 QDGlobals qd;  /* QuickDraw global information structure.  */
 #endif
 
+#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
 
-struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
 struct mac_display_info *mac_display_info_for_display (Display *);
 static void x_update_window_end P_ ((struct window *, int, int));
-static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
-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 *));
@@ -270,14 +229,16 @@ static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
-static void XTreassert_line_highlight P_ ((int, int));
-static void x_change_line_highlight P_ ((int, int, int, int));
 static void XTset_terminal_modes P_ ((void));
 static void XTreset_terminal_modes P_ ((void));
 static void x_clear_frame P_ ((void));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 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 *));
 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 *));
@@ -289,88 +250,185 @@ static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
 static void x_after_update_window_line P_ ((struct glyph_row *));
+static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
+                                           enum scroll_bar_part *,
+                                           Lisp_Object *, Lisp_Object *,
+                                           unsigned long *));
 
-void activate_scroll_bars (FRAME_PTR);
-void deactivate_scroll_bars (FRAME_PTR);
-
-static int is_emacs_window (WindowPtr);
-
-int x_bitmap_icon (struct frame *, Lisp_Object);
-void x_make_frame_visible (struct frame *);
-
-extern void window_scroll (Lisp_Object, int, int, int);
+static int is_emacs_window P_ ((WindowPtr));
+static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
+static void XSetFont P_ ((Display *, GC, XFontStruct *));
 
 /* Defined in macmenu.h.  */
 extern void menubar_selection_callback (FRAME_PTR, int);
-extern void set_frame_menubar (FRAME_PTR, int, int);
-
-/* X display function emulation */
 
-void
-XFreePixmap (display, pixmap)
-     Display *display;         /* not used */
-     Pixmap pixmap;
+#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)
+#define CG_SET_STROKE_COLOR(context, color)            \
+  CGContextSetRGBStrokeColor (context,                                 \
+                             RED_FROM_ULONG (color) / 255.0f,          \
+                             GREEN_FROM_ULONG (color) / 255.0f,        \
+                             BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
+#if USE_CG_DRAWING
+#define FRAME_CG_CONTEXT(f)    ((f)->output_data.mac->cg_context)
+
+/* Fringe bitmaps.  */
+
+static int max_fringe_bmp = 0;
+static CGImageRef *fringe_bmp = 0;
+
+static CGContextRef
+mac_begin_cg_clip (f, gc)
+     struct frame *f;
+     GC gc;
 {
-  DisposeGWorld (pixmap);
-}
+  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);
 
-/* Set foreground color for subsequent QuickDraw commands.  Assume
-   graphic port has already been set.  */
+  return context;
+}
 
 static void
-mac_set_forecolor (unsigned long color)
+mac_end_cg_clip (f)
+     struct frame *f;
 {
-  RGBColor fg_color;
+  CGContextRestoreGState (FRAME_CG_CONTEXT (f));
+}
 
-  fg_color.red = RED16_FROM_ULONG (color);
-  fg_color.green = GREEN16_FROM_ULONG (color);
-  fg_color.blue = BLUE16_FROM_ULONG (color);
+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);
 
-  RGBForeColor (&fg_color);
+      if (context)
+       {
+         CGContextSynchronize (context);
+         QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
+                         &FRAME_CG_CONTEXT (f));
+       }
+    }
 }
+#endif
 
-
-/* Set background color for subsequent QuickDraw commands.  Assume
-   graphic port has already been set.  */
+static RgnHandle saved_port_clip_region = NULL;
 
 static void
-mac_set_backcolor (unsigned long color)
+mac_begin_clip (gc)
+     GC gc;
 {
-  RGBColor bg_color;
+  static RgnHandle new_region = NULL;
 
-  bg_color.red = RED16_FROM_ULONG (color);
-  bg_color.green = GREEN16_FROM_ULONG (color);
-  bg_color.blue = BLUE16_FROM_ULONG (color);
+  if (saved_port_clip_region == NULL)
+    saved_port_clip_region = NewRgn ();
+  if (new_region == NULL)
+    new_region = NewRgn ();
 
-  RGBBackColor (&bg_color);
+  if (gc->n_clip_rects)
+    {
+      GetClip (saved_port_clip_region);
+      SectRgn (saved_port_clip_region, gc->clip_region, new_region);
+      SetClip (new_region);
+    }
 }
 
-/* Set foreground and background color for subsequent QuickDraw
-   commands.  Assume that the graphic port has already been set.  */
-
 static void
-mac_set_colors (GC gc)
+mac_end_clip (gc)
+     GC gc;
+{
+  if (gc->n_clip_rects)
+    SetClip (saved_port_clip_region);
+}
+
+
+/* X display function emulation */
+
+void
+XFreePixmap (display, pixmap)
+     Display *display;         /* not used */
+     Pixmap pixmap;
 {
-  mac_set_forecolor (gc->foreground);
-  mac_set_backcolor (gc->background);
+  DisposeGWorld (pixmap);
 }
 
+
 /* Mac version of XDrawLine.  */
 
 static void
-XDrawLine (display, w, gc, x1, y1, x2, y2)
-     Display *display;
-     WindowPtr w;
+mac_draw_line (f, gc, x1, y1, x2, y2)
+     struct frame *f;
      GC gc;
      int x1, y1, x2, y2;
 {
-  SetPortWindowPort (w);
+#if USE_CG_DRAWING
+  CGContextRef context;
+  float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
+
+  if (y1 != y2)
+    gx1 += 0.5f, gx2 += 0.5f;
+  if (x1 != x2)
+    gy1 += 0.5f, gy2 += 0.5f;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CGContextBeginPath (context);
+  CGContextMoveToPoint (context, gx1, gy1);
+  CGContextAddLineToPoint (context, gx2, gy2);
+  CGContextClosePath (context);
+  CGContextStrokePath (context);
+  mac_end_cg_clip (f);
+#else
+  if (x1 == x2)
+    {
+      if (y1 > y2)
+       y1--;
+      else if (y2 > y1)
+       y2--;
+    }
+  else if (y1 == y2)
+    {
+      if (x1 > x2)
+       x1--;
+      else
+       x2--;
+    }
+
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
 
+  mac_begin_clip (gc);
   MoveTo (x1, y1);
   LineTo (x2, y2);
+  mac_end_clip (gc);
+#endif
 }
 
 void
@@ -383,10 +441,25 @@ 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);
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
 
   LockPixels (GetGWorldPixMap (p));
   MoveTo (x1, y1);
@@ -396,67 +469,126 @@ mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
   SetGWorld (old_port, old_gdh);
 }
 
-/* Mac version of XClearArea.  */
 
-void
-XClearArea (display, w, x, y, width, height, exposures)
-     Display *display;
-     WindowPtr w;
+static void
+mac_erase_rectangle (f, gc, x, y, width, height)
+     struct frame *f;
+     GC gc;
      int x, y;
      unsigned int width, height;
-     int exposures;
 {
-  struct mac_output *mwp = (mac_output *) GetWRefCon (w);
-  Rect r;
-  XGCValues xgc;
+#if USE_CG_DRAWING
+  CGContextRef context;
 
-  xgc.foreground = mwp->x_compatible.foreground_pixel;
-  xgc.background = mwp->x_compatible.background_pixel;
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
+  Rect r;
 
-  SetPortWindowPort (w);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  mac_set_colors (&xgc);
+  RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
+  mac_begin_clip (gc);
   EraseRect (&r);
+  mac_end_clip (gc);
+
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+#endif
+}
+
+
+/* Mac version of XClearArea.  */
+
+void
+mac_clear_area (f, x, y, width, height)
+     struct frame *f;
+     int x, y;
+     unsigned int width, height;
+{
+  mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
 }
 
 /* Mac version of XClearWindow.  */
 
 static void
-XClearWindow (display, w)
-     Display *display;
-     WindowPtr w;
+mac_clear_window (f)
+     struct frame *f;
 {
-  struct mac_output *mwp = (mac_output *) GetWRefCon (w);
-  XGCValues xgc;
+#if USE_CG_DRAWING
+  CGContextRef context;
+  GC gc = FRAME_NORMAL_GC (f);
 
-  xgc.foreground = mwp->x_compatible.foreground_pixel;
-  xgc.background = mwp->x_compatible.background_pixel;
-
-  SetPortWindowPort (w);
+  context = mac_begin_cg_clip (f, NULL);
+  CG_SET_FILL_COLOR (context, gc->xgcv.background);
+  CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
+                                         FRAME_PIXEL_HEIGHT (f)));
+  mac_end_cg_clip (f);
+#else
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  mac_set_colors (&xgc);
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 
 #if TARGET_API_MAC_CARBON
   {
     Rect r;
 
-    GetWindowPortBounds (w, &r);
+    GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
     EraseRect (&r);
   }
 #else /* not TARGET_API_MAC_CARBON */
-  EraseRect (&(w->portRect));
+  EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
 #endif /* not TARGET_API_MAC_CARBON */
+#endif
 }
 
 
 /* Mac replacement for XCopyArea.  */
 
+#if USE_CG_DRAWING
 static void
-mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
-     Display *display;
-     WindowPtr w;
+mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
+                  dest_x, dest_y, overlay_p)
+     CGImageRef image;
+     struct frame *f;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y, overlay_p;
+{
+  CGContextRef context;
+  float port_height = FRAME_PIXEL_HEIGHT (f);
+  CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
+
+  context = mac_begin_cg_clip (f, gc);
+  if (!overlay_p)
+    {
+      CG_SET_FILL_COLOR (context, gc->xgcv.background);
+      CGContextFillRect (context, dest_rect);
+    }
+  CGContextClipToRect (context, dest_rect);
+  CGContextScaleCTM (context, 1, -1);
+  CGContextTranslateCTM (context, 0, -port_height);
+  if (CGImageIsMask (image))
+    CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextDrawImage (context,
+                     CGRectMake (dest_x - src_x,
+                                 port_height - (dest_y - src_y
+                                                + CGImageGetHeight (image)),
+                                 CGImageGetWidth (image),
+                                 CGImageGetHeight (image)),
+                     image);
+  mac_end_cg_clip (f);
+}
+
+#else  /* !USE_CG_DRAWING */
+
+static void
+mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
+     struct frame *f;
      GC gc;
      int x, y, width, height;
      unsigned short *bits;
@@ -469,51 +601,32 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
   bitmap.baseAddr = (char *)bits;
   SetRect (&(bitmap.bounds), 0, 0, width, height);
 
-  SetPortWindowPort (w);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  mac_set_colors (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
-  LockPortBits (GetWindowPort (w));
-  CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
-           &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
-  UnlockPortBits (GetWindowPort (w));
+  {
+    CGrafPtr port;
+
+    GetPort (&port);
+    LockPortBits (port);
+    CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
+             &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
+    UnlockPortBits (port);
+  }
 #else /* not TARGET_API_MAC_CARBON */
-  CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
+  CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
            overlay_p ? srcOr : srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
-}
-
-
-/* Mac replacement for XSetClipRectangles.  */
-
-static void
-mac_set_clip_rectangle (display, w, r)
-     Display *display;
-     WindowPtr w;
-     Rect *r;
-{
-  SetPortWindowPort (w);
-
-  ClipRect (r);
-}
-
-
-/* Mac replacement for XSetClipMask.  */
-
-static void
-mac_reset_clipping (display, w)
-     Display *display;
-     WindowPtr w;
-{
-  Rect r;
-
-  SetPortWindowPort (w);
+  mac_end_clip (gc);
 
-  SetRect (&r, -32767, -32767, 32767, 32767);
-  ClipRect (&r);
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
+#endif /* !USE_CG_DRAWING */
 
 
 /* Mac replacement for XCreateBitmapFromBitmapData.  */
@@ -574,7 +687,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;
@@ -588,12 +709,16 @@ XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
      char *data;
      unsigned int width, height;
      unsigned long fg, bg;
-     unsigned int depth;       /* not used */
+     unsigned int depth;
 {
   Pixmap pixmap;
   BitMap bitmap;
   CGrafPtr old_port;
   GDHandle old_gdh;
+  static GC gc = NULL;         /* not reentrant */
+
+  if (gc == NULL)
+    gc = XCreateGC (display, w, 0, NULL);
 
   pixmap = XCreatePixmap (display, w, width, height, depth);
   if (pixmap == NULL)
@@ -602,8 +727,10 @@ XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
   GetGWorld (&old_port, &old_gdh);
   SetGWorld (pixmap, NULL);
   mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
-  mac_set_forecolor (fg);
-  mac_set_backcolor (bg);
+  XSetForeground (display, gc, fg);
+  XSetBackground (display, gc, bg);
+  RGBForeColor (GC_FORE_COLOR (gc));
+  RGBBackColor (GC_BACK_COLOR (gc));
   LockPixels (GetGWorldPixMap (pixmap));
 #if TARGET_API_MAC_CARBON
   CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
@@ -623,206 +750,641 @@ XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
 /* Mac replacement for XFillRectangle.  */
 
 static void
-XFillRectangle (display, w, gc, x, y, width, height)
-     Display *display;
-     WindowPtr w;
+mac_fill_rectangle (f, gc, x, y, width, height)
+     struct frame *f;
      GC gc;
      int x, y;
      unsigned int width, height;
 {
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextFillRect (context, CGRectMake (x, y, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
-  SetPortWindowPort (w);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  mac_set_colors (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
 }
 
 
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
+/* Mac replacement for XDrawRectangle: dest is a window.  */
+
 static void
-mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
-     Display *display;
-     Pixmap p;
+mac_draw_rectangle (f, gc, x, y, width, height)
+     struct frame *f;
      GC gc;
      int x, y;
      unsigned int width, height;
 {
-  CGrafPtr old_port;
-  GDHandle old_gdh;
+#if USE_CG_DRAWING
+  CGContextRef context;
+
+  context = mac_begin_cg_clip (f, gc);
+  CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
+  CGContextStrokeRect (context,
+                      CGRectMake (x + 0.5f, y + 0.5f, width, height));
+  mac_end_cg_clip (f);
+#else
   Rect r;
 
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (p, NULL);
-  mac_set_colors (gc);
-  SetRect (&r, x, y, x + width, y + height);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  LockPixels (GetGWorldPixMap (p));
-  PaintRect (&r); /* using foreground color of gc */
-  UnlockPixels (GetGWorldPixMap (p));
+  RGBForeColor (GC_FORE_COLOR (gc));
+  SetRect (&r, x, y, x + width + 1, y + height + 1);
 
-  SetGWorld (old_port, old_gdh);
+  mac_begin_clip (gc);
+  FrameRect (&r); /* using foreground color of gc */
+  mac_end_clip (gc);
+#endif
 }
+
+
+#if USE_ATSUI
+static OSStatus
+atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
+     ConstUniCharArrayPtr text;
+     UniCharCount text_length;
+     ATSUStyle style;
+     ATSUTextLayout *text_layout;
+{
+  OSStatus err;
+  static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */
+
+  if (saved_text_layout == NULL)
+    {
+      UniCharCount lengths[] = {kATSUToTextEnd};
+      ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
+      ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
+      static ATSLineLayoutOptions line_layout =
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+       kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
+       | kATSLineUseQDRendering
+#else
+       kATSLineIsDisplayOnly | kATSLineFractDisable
 #endif
+       ;
+      ATSUAttributeValuePtr values[] = {&line_layout};
+
+      err = ATSUCreateTextLayoutWithTextPtr (text,
+                                            kATSUFromTextBeginning,
+                                            kATSUToTextEnd,
+                                            text_length,
+                                            1, lengths, &style,
+                                            &saved_text_layout);
+      if (err == noErr)
+       err = ATSUSetLayoutControls (saved_text_layout,
+                                    sizeof (tags) / sizeof (tags[0]),
+                                    tags, sizes, values);
+      /* XXX: Should we do this? */
+      if (err == noErr)
+       err = ATSUSetTransientFontMatching (saved_text_layout, true);
+    }
+  else
+    {
+      err = ATSUSetRunStyle (saved_text_layout, style,
+                            kATSUFromTextBeginning, kATSUToTextEnd);
+      if (err == noErr)
+       err = ATSUSetTextPointerLocation (saved_text_layout, text,
+                                         kATSUFromTextBeginning,
+                                         kATSUToTextEnd,
+                                         text_length);
+    }
 
+  if (err == noErr)
+    *text_layout = saved_text_layout;
+  return err;
+}
+#endif
 
-/* Mac replacement for XDrawRectangle: dest is a window.  */
 
 static void
-mac_draw_rectangle (display, w, gc, x, y, width, height)
-     Display *display;
-     WindowPtr w;
-     GC gc;
+mac_invert_rectangle (f, x, y, width, height)
+     struct frame *f;
      int x, y;
      unsigned int width, height;
 {
   Rect r;
 
-  SetPortWindowPort (w);
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  mac_set_colors (gc);
-  SetRect (&r, x, y, x + width + 1, y + height + 1);
+  SetRect (&r, x, y, x + width, y + height);
 
-  FrameRect (&r); /* using foreground color of gc */
+  InvertRect (&r);
 }
 
 
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-/* Mac replacement for XDrawRectangle: dest is a Pixmap.  */
-
 static void
-mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
-     Display *display;
-     Pixmap p;
+mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, bytes_per_char)
+     struct frame *f;
      GC gc;
      int x, y;
-     unsigned int width, height;
+     char *buf;
+     int nchars, bg_width, bytes_per_char;
 {
-  CGrafPtr old_port;
-  GDHandle old_gdh;
-  Rect r;
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (p, NULL);
-  mac_set_colors (gc);
-  SetRect (&r, x, y, x + width + 1, y + height + 1);
+#if USE_ATSUI
+  if (GC_FONT (gc)->mac_style)
+    {
+      OSErr err;
+      ATSUTextLayout text_layout;
 
-  LockPixels (GetGWorldPixMap (p));
-  FrameRect (&r); /* using foreground color of gc */
-  UnlockPixels (GetGWorldPixMap (p));
-
-  SetGWorld (old_port, old_gdh);
-}
-#endif
+      xassert (bytes_per_char == 2);
 
+#ifndef WORDS_BIG_ENDIAN
+      {
+       int i;
+       UniChar *text = (UniChar *)buf;
 
-static void
-mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
-                       bytes_per_char)
-     Display *display;
-     WindowPtr w;
-     GC gc;
-     int x, y;
-     char *buf;
-     int nchars, mode, bytes_per_char;
-{
-  SetPortWindowPort (w);
-#ifdef MAC_OS_X_VERSION_10_2
-  UInt32 textFlags, savedFlags;
-  if (!NILP(Vmac_use_core_graphics)) {
-    textFlags = kQDUseCGTextRendering;
-    savedFlags = SwapQDTextFlags(textFlags);
-  }
+       for (i = 0; i < nchars; i++)
+         text[i] = EndianU16_BtoN (text[i]);
+      }
+#endif
+      err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
+                                               nchars,
+                                               GC_FONT (gc)->mac_style,
+                                               &text_layout);
+      if (err != noErr)
+       return;
+#ifdef MAC_OSX
+      if (!mac_use_core_graphics)
+       {
 #endif
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
+#endif
+         mac_begin_clip (gc);
+         RGBForeColor (GC_FORE_COLOR (gc));
+         if (bg_width)
+           {
+             Rect r;
 
-  mac_set_colors (gc);
+             SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
+                      x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
+             RGBBackColor (GC_BACK_COLOR (gc));
+             EraseRect (&r);
+             RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+           }
+         MoveTo (x, y);
+         ATSUDrawText (text_layout,
+                       kATSUFromTextBeginning, kATSUToTextEnd,
+                       kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
+         mac_end_clip (gc);
+#ifdef MAC_OSX
+       }
+      else
+       {
+         CGrafPtr port;
+         CGContextRef context;
+         float port_height = FRAME_PIXEL_HEIGHT (f);
+         ATSUAttributeTag tags[] = {kATSUCGContextTag};
+         ByteCount sizes[] = {sizeof (CGContextRef)};
+         ATSUAttributeValuePtr values[] = {&context};
+
+#if USE_CG_DRAWING
+         context = mac_begin_cg_clip (f, gc);
+#else
+         GetPort (&port);
+         QDBeginCGContext (port, &context);
+         if (gc->n_clip_rects || bg_width)
+           {
+             CGContextTranslateCTM (context, 0, port_height);
+             CGContextScaleCTM (context, 1, -1);
+             if (gc->n_clip_rects)
+               CGContextClipToRects (context, gc->clip_rects,
+                                     gc->n_clip_rects);
+#endif
+             if (bg_width)
+               {
+                 CG_SET_FILL_COLOR (context, gc->xgcv.background);
+                 CGContextFillRect
+                   (context,
+                    CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
+                                bg_width, FONT_HEIGHT (GC_FONT (gc))));
+               }
+             CGContextScaleCTM (context, 1, -1);
+             CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
+           }
+#endif
+         CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+         err = ATSUSetLayoutControls (text_layout,
+                                      sizeof (tags) / sizeof (tags[0]),
+                                      tags, sizes, values);
+         if (err == noErr)
+           ATSUDrawText (text_layout,
+                         kATSUFromTextBeginning, kATSUToTextEnd,
+                         Long2Fix (x), Long2Fix (port_height - y));
+#if USE_CG_DRAWING
+         mac_end_cg_clip (f);
+         context = NULL;
+#else
+         CGContextSynchronize (context);
+         QDEndCGContext (port, &context);
+#endif
+#if 0
+         /* This doesn't work on Mac OS X 10.1.  */
+         ATSUClearLayoutControls (text_layout,
+                                  sizeof (tags) / sizeof (tags[0]), tags);
+#else
+         ATSUSetLayoutControls (text_layout,
+                                sizeof (tags) / sizeof (tags[0]),
+                                tags, sizes, values);
+#endif
+       }
+#endif /* MAC_OSX */
+    }
+  else
+#endif /* USE_ATSUI */
+    {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+      UInt32 savedFlags;
 
-  TextFont (gc->font->mac_fontnum);
-  TextSize (gc->font->mac_fontsize);
-  TextFace (gc->font->mac_fontface);
-  TextMode (mode);
+      if (mac_use_core_graphics)
+       savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
+#endif
+#if USE_CG_DRAWING
+      mac_prepare_for_quickdraw (f);
+#endif
+      mac_begin_clip (gc);
+      RGBForeColor (GC_FORE_COLOR (gc));
+#ifdef MAC_OS8
+      if (bg_width)
+       {
+         RGBBackColor (GC_BACK_COLOR (gc));
+         TextMode (srcCopy);
+       }
+      else
+       TextMode (srcOr);
+#else
+      /* We prefer not to use srcCopy text transfer mode on Mac OS X
+        because:
+        - Screen is double-buffered.  (In srcCopy mode, a text is
+          drawn into an offscreen graphics world first.  So
+          performance gain cannot be expected.)
+        - It lowers rendering quality.
+        - Some fonts leave garbage on cursor movement.  */
+      if (bg_width)
+       {
+         Rect r;
 
-  MoveTo (x, y);
-  DrawText (buf, 0, nchars * bytes_per_char);
-#ifdef MAC_OS_X_VERSION_10_2
-  if (!NILP(Vmac_use_core_graphics))
-    SwapQDTextFlags(savedFlags);
+         RGBBackColor (GC_BACK_COLOR (gc));
+         SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
+                  x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
+         EraseRect (&r);
+       }
+      TextMode (srcOr);
+#endif
+      TextFont (GC_FONT (gc)->mac_fontnum);
+      TextSize (GC_FONT (gc)->mac_fontsize);
+      TextFace (GC_FONT (gc)->mac_fontface);
+      MoveTo (x, y);
+      DrawText (buf, 0, nchars * bytes_per_char);
+      if (bg_width)
+       RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
+      mac_end_clip (gc);
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+      if (mac_use_core_graphics)
+       SwapQDTextFlags(savedFlags);
 #endif
+    }
 }
 
 
 /* Mac replacement for XDrawString.  */
 
 static void
-XDrawString (display, w, gc, x, y, buf, nchars)
-     Display *display;
-     WindowPtr w;
+mac_draw_string (f, gc, x, y, buf, nchars)
+     struct frame *f;
      GC gc;
      int x, y;
      char *buf;
      int nchars;
 {
-  mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
+  mac_draw_string_common (f, gc, x, y, buf, nchars, 0, 1);
 }
 
 
 /* Mac replacement for XDrawString16. */
 
 static void
-XDrawString16 (display, w, gc, x, y, buf, nchars)
-     Display *display;
-     WindowPtr w;
+mac_draw_string_16 (f, gc, x, y, buf, nchars)
+     struct frame *f;
      GC gc;
      int x, y;
      XChar2b *buf;
      int nchars;
 {
-  mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
-                         2);
+  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, 0, 2);
 }
 
 
 /* Mac replacement for XDrawImageString.  */
 
 static void
-XDrawImageString (display, w, gc, x, y, buf, nchars)
-     Display *display;
-     WindowPtr w;
+mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width)
+     struct frame *f;
      GC gc;
      int x, y;
      char *buf;
-     int nchars;
+     int nchars, bg_width;
 {
-  mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
+  mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, 1);
 }
 
 
 /* Mac replacement for XDrawString16.  */
 
 static void
-XDrawImageString16 (display, w, gc, x, y, buf, nchars)
-     Display *display;
-     WindowPtr w;
+mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width)
+     struct frame *f;
      GC gc;
      int x, y;
      XChar2b *buf;
+     int nchars, bg_width;
+{
+  mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width, 2);
+}
+
+
+/* Mac replacement for XQueryTextExtents, but takes a character.  If
+   STYLE is NULL, measurement is done by QuickDraw Text routines for
+   the font of the current graphics port.  If CG_GLYPH is not NULL,
+   *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained.  */
+
+static OSErr
+mac_query_char_extents (style, c,
+                       font_ascent_return, font_descent_return,
+                       overall_return, cg_glyph)
+#if USE_ATSUI
+     ATSUStyle style;
+#else
+     void *style;
+#endif
+     int c;
+     int *font_ascent_return, *font_descent_return;
+     XCharStruct *overall_return;
+#if USE_CG_TEXT_DRAWING
+     CGGlyph *cg_glyph;
+#else
+     void *cg_glyph;
+#endif
+{
+  OSErr err = noErr;
+  int width;
+  Rect char_bounds;
+
+#if USE_ATSUI
+  if (style)
+    {
+      ATSUTextLayout text_layout;
+      UniChar ch = c;
+
+      err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
+      if (err == noErr)
+       {
+         ATSTrapezoid glyph_bounds;
+
+         err = ATSUGetGlyphBounds (text_layout, 0, 0,
+                                   kATSUFromTextBeginning, kATSUToTextEnd,
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+                                   kATSUseFractionalOrigins,
+#else
+                                   kATSUseDeviceOrigins,
+#endif
+                                   1, &glyph_bounds, NULL);
+         if (err == noErr)
+           {
+             xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
+                      == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
+
+             width = Fix2Long (glyph_bounds.upperRight.x
+                               - glyph_bounds.upperLeft.x);
+             if (font_ascent_return)
+               *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
+             if (font_descent_return)
+               *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
+           }
+       }
+      if (err == noErr && overall_return)
+       {
+         err = ATSUMeasureTextImage (text_layout,
+                                     kATSUFromTextBeginning, kATSUToTextEnd,
+                                     0, 0, &char_bounds);
+         if (err == noErr)
+           STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
+#if USE_CG_TEXT_DRAWING
+         if (err == noErr && cg_glyph)
+           {
+             OSErr err1;
+             ATSUGlyphInfoArray glyph_info_array;
+             ByteCount count = sizeof (ATSUGlyphInfoArray);
+
+             err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
+                                          kATSUToTextEnd, NULL, NULL, NULL);
+             if (err1 == noErr)
+               err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
+                                        kATSUToTextEnd, &count,
+                                        &glyph_info_array);
+             if (err1 == noErr)
+               {
+                 xassert (glyph_info_array.glyphs[0].glyphID);
+                 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
+               }
+             else
+               *cg_glyph = 0;
+           }
+#endif
+       }
+    }
+  else
+#endif
+    {
+      if (font_ascent_return || font_descent_return)
+       {
+         FontInfo font_info;
+
+         GetFontInfo (&font_info);
+         if (font_ascent_return)
+           *font_ascent_return = font_info.ascent;
+         if (font_descent_return)
+           *font_descent_return = font_info.descent;
+       }
+      if (overall_return)
+       {
+         char ch = c;
+
+         width = CharWidth (ch);
+         QDTextBounds (1, &ch, &char_bounds);
+         STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
+       }
+    }
+
+  return err;
+}
+
+
+/* Mac replacement for XTextExtents16.  Only sets horizontal metrics.  */
+
+static int
+mac_text_extents_16 (font_struct, string, nchars, overall_return)
+     XFontStruct *font_struct;
+     XChar2b *string;
      int nchars;
+     XCharStruct *overall_return;
+{
+  int i;
+  short width = 0, lbearing = 0, rbearing = 0;
+  XCharStruct *pcm;
+
+  for (i = 0; i < nchars; i++)
+    {
+      pcm = mac_per_char_metric (font_struct, string, 0);
+      if (pcm == NULL)
+       width += FONT_WIDTH (font_struct);
+      else
+       {
+         lbearing = min (lbearing, width + pcm->lbearing);
+         rbearing = max (rbearing, width + pcm->rbearing);
+         width += pcm->width;
+       }
+      string++;
+    }
+
+  overall_return->lbearing = lbearing;
+  overall_return->rbearing = rbearing;
+  overall_return->width = width;
+
+  /* What's the meaning of the return value of XTextExtents16?  */
+}
+
+
+#if USE_CG_TEXT_DRAWING
+static int cg_text_anti_aliasing_threshold = 8;
+
+static void
+init_cg_text_anti_aliasing_threshold ()
+{
+  int threshold;
+  Boolean valid_p;
+
+  threshold =
+    CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
+                                    kCFPreferencesCurrentApplication,
+                                    &valid_p);
+  if (valid_p)
+    cg_text_anti_aliasing_threshold = threshold;
+}
+
+static int
+mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width)
+     struct frame *f;
+     GC gc;
+     int x, y;
+     XChar2b *buf;
+     int nchars, bg_width;
 {
-  mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
-                         2);
+  CGrafPtr port;
+  float port_height, gx, gy;
+  int i;
+  CGContextRef context;
+  CGGlyph *glyphs;
+  CGSize *advances;
+
+  if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
+    return 0;
+
+  port = GetWindowPort (FRAME_MAC_WINDOW (f));
+  port_height = FRAME_PIXEL_HEIGHT (f);
+  gx = x;
+  gy = port_height - y;
+  glyphs = (CGGlyph *)buf;
+  advances = alloca (sizeof (CGSize) * nchars);
+  if (advances == NULL)
+    return 0;
+  for (i = 0; i < nchars; i++)
+    {
+      XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
+
+      advances[i].width = pcm->width;
+      advances[i].height = 0;
+      glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
+      buf++;
+    }
+
+#if USE_CG_DRAWING
+  context = mac_begin_cg_clip (f, gc);
+#else
+  QDBeginCGContext (port, &context);
+  if (gc->n_clip_rects || bg_width)
+    {
+      CGContextTranslateCTM (context, 0, port_height);
+      CGContextScaleCTM (context, 1, -1);
+      if (gc->n_clip_rects)
+       CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
+#endif
+      if (bg_width)
+       {
+         CG_SET_FILL_COLOR (context, gc->xgcv.background);
+         CGContextFillRect
+           (context,
+            CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
+                        bg_width, FONT_HEIGHT (GC_FONT (gc))));
+       }
+      CGContextScaleCTM (context, 1, -1);
+      CGContextTranslateCTM (context, 0, -port_height);
+#if !USE_CG_DRAWING
+    }
+#endif
+  CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
+  CGContextSetFont (context, GC_FONT (gc)->cg_font);
+  CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
+  if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
+    CGContextSetShouldAntialias (context, false);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+  CGContextSetTextPosition (context, gx, gy);
+  CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
+#else
+  for (i = 0; i < nchars; i++)
+    {
+      CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
+      gx += advances[i].width;
+    }
+#endif
+#if USE_CG_DRAWING
+  mac_end_cg_clip (f);
+#else
+  CGContextSynchronize (context);
+  QDEndCGContext (port, &context);
+#endif
+
+  return 1;
 }
+#endif
 
 
+#if !USE_CG_DRAWING
 /* Mac replacement for XCopyArea: dest must be window.  */
 
 static void
-mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
-              dest_y)
-     Display *display;
+mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
      Pixmap src;
-     WindowPtr dest;
+     struct frame *f;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
@@ -830,7 +1392,7 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
 {
   Rect src_r, dest_r;
 
-  SetPortWindowPort (dest);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -838,27 +1400,35 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
   ForeColor (blackColor);
   BackColor (whiteColor);
 
+  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
 #if TARGET_API_MAC_CARBON
-  LockPortBits (GetWindowPort (dest));
-  CopyBits (GetPortBitMapForCopyBits (src),
-           GetPortBitMapForCopyBits (GetWindowPort (dest)),
-           &src_r, &dest_r, srcCopy, 0);
-  UnlockPortBits (GetWindowPort (dest));
+  {
+    CGrafPtr port;
+
+    GetPort (&port);
+    LockPortBits (port);
+    CopyBits (GetPortBitMapForCopyBits (src),
+             GetPortBitMapForCopyBits (port),
+             &src_r, &dest_r, srcCopy, 0);
+    UnlockPortBits (port);
+  }
 #else /* not TARGET_API_MAC_CARBON */
-  CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
+  CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
            &src_r, &dest_r, srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (src));
+  mac_end_clip (gc);
+
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
 
 
 static void
-mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
+mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
                         width, height, dest_x, dest_y)
-     Display *display;
      Pixmap src, mask;
-     WindowPtr dest;
+     struct frame *f;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
@@ -866,7 +1436,7 @@ mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
 {
   Rect src_r, dest_r;
 
-  SetPortWindowPort (dest);
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
   SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
@@ -874,47 +1444,38 @@ mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
   ForeColor (blackColor);
   BackColor (whiteColor);
 
+  mac_begin_clip (gc);
   LockPixels (GetGWorldPixMap (src));
   LockPixels (GetGWorldPixMap (mask));
 #if TARGET_API_MAC_CARBON
-  LockPortBits (GetWindowPort (dest));
-  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
-           GetPortBitMapForCopyBits (GetWindowPort (dest)),
-           &src_r, &src_r, &dest_r);
-  UnlockPortBits (GetWindowPort (dest));
+  {
+    CGrafPtr port;
+
+    GetPort (&port);
+    LockPortBits (port);
+    CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
+             GetPortBitMapForCopyBits (port),
+             &src_r, &src_r, &dest_r);
+    UnlockPortBits (port);
+  }
 #else /* not TARGET_API_MAC_CARBON */
   CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
-           &(dest->portBits), &src_r, &src_r, &dest_r);
+           &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (mask));
   UnlockPixels (GetGWorldPixMap (src));
-}
-
+  mac_end_clip (gc);
 
-#if 0
-/* Convert a pair of local coordinates to global (screen) coordinates.
-   Assume graphic port has been properly set.  */
-static void
-local_to_global_coord (short *h, short *v)
-{
-  Point p;
-
-  p.h = *h;
-  p.v = *v;
-
-  LocalToGlobal (&p);
-
-  *h = p.h;
-  *v = p.v;
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 }
-#endif
+#endif /* !USE_CG_DRAWING */
+
 
 /* Mac replacement for XCopyArea: used only for scrolling.  */
 
 static void
-mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
-     Display *display;
-     WindowPtr w;
+mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
+     struct frame *f;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
@@ -925,149 +1486,66 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
   RgnHandle dummy = NewRgn (); /* For avoiding update events.  */
 
   SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
-  ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
+  ScrollWindowRect (FRAME_MAC_WINDOW (f),
+                   &src_r, dest_x - src_x, dest_y - src_y,
                    kScrollWindowNoOptions, dummy);
   DisposeRgn (dummy);
 #else /* not TARGET_API_MAC_CARBON */
   Rect src_r, dest_r;
+  WindowPtr w = FRAME_MAC_WINDOW (f);
 
   SetPort (w);
-#if 0
-  mac_set_colors (gc);
-#endif
 
   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);
 
-#if 0
-  /* Need to use global coordinates and screenBits since src and dest
-     areas overlap in general.  */
-  local_to_global_coord (&src_r.left, &src_r.top);
-  local_to_global_coord (&src_r.right, &src_r.bottom);
-  local_to_global_coord (&dest_r.left, &dest_r.top);
-  local_to_global_coord (&dest_r.right, &dest_r.bottom);
-
-  CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
-#else
   /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
      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);
 
-  mac_set_colors (gc);
-#endif
+  RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
 #endif /* not TARGET_API_MAC_CARBON */
 }
 
 
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-/* Mac replacement for XCopyArea: dest must be Pixmap.  */
-
-static void
-mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
-                     dest_x, dest_y)
-     Display *display;
-     Pixmap src, dest;
-     GC gc;
-     int src_x, src_y;
-     unsigned int width, height;
-     int dest_x, dest_y;
-{
-  CGrafPtr old_port;
-  GDHandle old_gdh;
-  Rect src_r, dest_r;
-
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (dest, NULL);
-  ForeColor (blackColor);
-  BackColor (whiteColor);
-
-  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
-  LockPixels (GetGWorldPixMap (src));
-  LockPixels (GetGWorldPixMap (dest));
-#if TARGET_API_MAC_CARBON
-  CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
-           &src_r, &dest_r, srcCopy, 0);
-#else /* not TARGET_API_MAC_CARBON */
-  CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
-           &src_r, &dest_r, srcCopy, 0);
-#endif /* not TARGET_API_MAC_CARBON */
-  UnlockPixels (GetGWorldPixMap (dest));
-  UnlockPixels (GetGWorldPixMap (src));
-
-  SetGWorld (old_port, old_gdh);
-}
-
+/* Mac replacement for XChangeGC.  */
 
 static void
-mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
-                                  width, height, dest_x, dest_y)
+XChangeGC (display, gc, mask, xgcv)
      Display *display;
-     Pixmap src, mask, dest;
      GC gc;
-     int src_x, src_y;
-     unsigned int width, height;
-     int dest_x, dest_y;
-{
-  CGrafPtr old_port;
-  GDHandle old_gdh;
-  Rect src_r, dest_r;
-
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (dest, NULL);
-  ForeColor (blackColor);
-  BackColor (whiteColor);
-
-  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
-  LockPixels (GetGWorldPixMap (src));
-  LockPixels (GetGWorldPixMap (mask));
-  LockPixels (GetGWorldPixMap (dest));
-#if TARGET_API_MAC_CARBON
-  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
-           GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
-#else /* not TARGET_API_MAC_CARBON */
-  CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
-           &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
-#endif /* not TARGET_API_MAC_CARBON */
-  UnlockPixels (GetGWorldPixMap (dest));
-  UnlockPixels (GetGWorldPixMap (mask));
-  UnlockPixels (GetGWorldPixMap (src));
-
-  SetGWorld (old_port, old_gdh);
-}
-#endif
-
-
-/* Mac replacement for XChangeGC.  */
-
-static void
-XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
-                XGCValues *xgcv)
+     unsigned long mask;
+     XGCValues *xgcv;
 {
   if (mask & GCForeground)
-    gc->foreground = xgcv->foreground;
+    XSetForeground (display, gc, xgcv->foreground);
   if (mask & GCBackground)
-    gc->background = xgcv->background;
+    XSetBackground (display, gc, xgcv->background);
   if (mask & GCFont)
-    gc->font = xgcv->font;
+    XSetFont (display, gc, xgcv->font);
 }
 
 
 /* Mac replacement for XCreateGC.  */
 
-XGCValues *
-XCreateGC (void * ignore, Window window, unsigned long mask,
-                      XGCValues *xgcv)
+GC
+XCreateGC (display, window, mask, xgcv)
+     Display *display;
+     Window window;
+     unsigned long mask;
+     XGCValues *xgcv;
 {
-  XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
-  bzero (gc, sizeof (XGCValues));
+  GC gc = xmalloc (sizeof (*gc));
 
-  XChangeGC (ignore, gc, mask, xgcv);
+  bzero (gc, sizeof (*gc));
+  XChangeGC (display, gc, mask, xgcv);
 
   return gc;
 }
@@ -1080,6 +1558,8 @@ XFreeGC (display, gc)
      Display *display;
      GC gc;
 {
+  if (gc->clip_region)
+    DisposeRgn (gc->clip_region);
   xfree (gc);
 }
 
@@ -1087,10 +1567,18 @@ XFreeGC (display, gc)
 /* Mac replacement for XGetGCValues.  */
 
 static void
-XGetGCValues (void* ignore, XGCValues *gc,
-                   unsigned long mask, XGCValues *xgcv)
+XGetGCValues (display, gc, mask, xgcv)
+     Display *display;
+     GC gc;
+     unsigned long mask;
+     XGCValues *xgcv;
 {
-  XChangeGC (ignore, xgcv, mask, gc);
+  if (mask & GCForeground)
+    xgcv->foreground = gc->xgcv.foreground;
+  if (mask & GCBackground)
+    xgcv->background = gc->xgcv.background;
+  if (mask & GCFont)
+    xgcv->font = gc->xgcv.font;
 }
 
 
@@ -1102,7 +1590,13 @@ XSetForeground (display, gc, color)
      GC gc;
      unsigned long color;
 {
-  gc->foreground = color;
+  if (gc->xgcv.foreground != color)
+    {
+      gc->xgcv.foreground = 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);
+    }
 }
 
 
@@ -1114,7 +1608,80 @@ XSetBackground (display, gc, color)
      GC gc;
      unsigned long color;
 {
-  gc->background = color;
+  if (gc->xgcv.background != color)
+    {
+      gc->xgcv.background = 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);
+    }
+}
+
+
+/* Mac replacement for XSetFont.  */
+
+static void
+XSetFont (display, gc, font)
+     Display *display;
+     GC gc;
+     XFontStruct *font;
+{
+  gc->xgcv.font = font;
+}
+
+
+/* Mac replacement for XSetClipRectangles.  */
+
+static void
+mac_set_clip_rectangles (display, gc, rectangles, n)
+     Display *display;
+     GC gc;
+     Rect *rectangles;
+     int n;
+{
+  int i;
+
+  xassert (n >= 0 && n <= MAX_CLIP_RECTS);
+
+  gc->n_clip_rects = n;
+  if (n > 0)
+    {
+      if (gc->clip_region == NULL)
+       gc->clip_region = NewRgn ();
+      RectRgn (gc->clip_region, rectangles);
+      if (n > 1)
+       {
+         RgnHandle region = NewRgn ();
+
+         for (i = 1; i < n; i++)
+           {
+             RectRgn (region, rectangles + i);
+             UnionRgn (gc->clip_region, region, gc->clip_region);
+           }
+         DisposeRgn (region);
+       }
+    }
+#if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
+  for (i = 0; i < n; i++)
+    {
+      Rect *rect = rectangles + i;
+
+      gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
+                                     rect->right - rect->left,
+                                     rect->bottom - rect->top);
+    }
+#endif
+}
+
+
+/* Mac replacement for XSetClipMask.  */
+
+static INLINE void
+mac_reset_clip_rectangles (display, gc)
+     Display *display;
+     GC gc;
+{
+  gc->n_clip_rects = 0;
 }
 
 
@@ -1161,36 +1728,6 @@ XSetWindowBackground (display, w, color)
 #endif
 }
 
-
-/* Mac replacement for XSetFont.  */
-
-static void
-XSetFont (display, gc, font)
-     Display *display;
-     GC gc;
-     XFontStruct *font;
-{
-  gc->font = font;
-}
-
-
-static void
-XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
-                     int *direction,int *font_ascent,
-                     int *font_descent, XCharStruct *cs)
-{
-  /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
-}
-
-
-/* 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
@@ -1199,6 +1736,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
@@ -1322,11 +1862,15 @@ mac_draw_vertical_window_border (w, x, y0, y1)
      int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct face *face;
 
-  XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-            f->output_data.mac->normal_gc, x, y0, x, y1);
-}
+  face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+  if (face)
+    XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
+                   face->foreground);
 
+  mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
+}
 
 /* End update of window W (which is equal to updated_window).
 
@@ -1339,7 +1883,7 @@ mac_draw_vertical_window_border (w, x, y0, y1)
 
    W may be a menu bar pseudo-window in case we don't have X toolkit
    support.  Such windows don't have a cursor, so don't display it
-   here. */
+   here.  */
 
 static void
 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
@@ -1372,14 +1916,6 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
       dpyinfo->mouse_face_window = Qnil;
     }
 
-#if 0
-  /* Unhide the caret.  This won't actually show the cursor, unless it
-     was visible before the corresponding call to HideCaret in
-     x_update_window_begin.  */
-  if (w32_use_visible_system_caret)
-    SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
-#endif
-
   updated_window = NULL;
 }
 
@@ -1395,13 +1931,6 @@ x_update_end (f)
   FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
 
   BLOCK_INPUT;
-  /* Reset the background color of Mac OS Window to that of the frame after
-     update so that it is used by Mac Toolbox to clear the update region before
-     an update event is generated.  */
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
-  mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
-
 #if TARGET_API_MAC_CARBON
   EnableScreenUpdates ();
 #endif
@@ -1472,19 +2001,15 @@ x_after_update_window_line (desired_row)
          height > 0))
     {
       int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
+
       /* Internal border is drawn below the tool bar.  */
       if (WINDOWP (f->tool_bar_window)
          && w == XWINDOW (f->tool_bar_window))
        y -= width;
 
       BLOCK_INPUT;
-
-      XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 0, y, width, height, 0);
-      XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 FRAME_PIXEL_WIDTH (f) - width, y,
-                 width, height, 0);
-
+      mac_clear_area (f, 0, y, width, height);
+      mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
       UNBLOCK_INPUT;
     }
 }
@@ -1503,9 +2028,6 @@ x_draw_fringe_bitmap (w, row, p)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Display *display = FRAME_MAC_DISPLAY (f);
-  WindowPtr window = FRAME_MAC_WINDOW (f);
-  XGCValues gcv;
-  GC gc = f->output_data.mac->normal_gc;
   struct face *face = p->face;
   int rowY;
 
@@ -1519,18 +2041,15 @@ x_draw_fringe_bitmap (w, row, p)
       int oldVH = row->visible_height;
       row->visible_height = p->h;
       row->y -= rowY - p->y;
-      x_clip_to_row (w, row, -1, gc);
+      x_clip_to_row (w, row, -1, face->gc);
       row->y = oldY;
       row->visible_height = oldVH;
     }
   else
-    x_clip_to_row (w, row, -1, gc);
+    x_clip_to_row (w, row, -1, face->gc);
 
   if (p->bx >= 0 && !p->overlay_p)
     {
-      XGCValues gcv;
-      gcv.foreground = face->background;
-
 #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
@@ -1542,9 +2061,7 @@ x_draw_fringe_bitmap (w, row, p)
        XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
 #endif
 
-      XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                     &gcv,
-                     p->bx, p->by, p->nx, p->ny);
+      mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
 
 #if 0  /* MAC_TODO: stipple */
       if (!face->stipple)
@@ -1552,24 +2069,79 @@ x_draw_fringe_bitmap (w, row, p)
 #endif
     }
 
-  if (p->which)
+  if (p->which
+#if USE_CG_DRAWING
+      && p->which < max_fringe_bmp
+#endif
+      )
     {
-      unsigned short *bits = p->bits + p->dh;
+      XGCValues gcv;
 
-      gcv.foreground = (p->cursor_p
-                       ? (p->overlay_p ? face->background
-                          : f->output_data.mac->cursor_pixel)
-                       : face->foreground);
-      gcv.background = face->background;
+      XGetGCValues (display, face->gc, GCForeground, &gcv);
+      XSetForeground (display, face->gc,
+                     (p->cursor_p
+                      ? (p->overlay_p ? face->background
+                         : f->output_data.mac->cursor_pixel)
+                      : face->foreground));
+#if USE_CG_DRAWING
+      mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
+                        p->wd, p->h, p->x, p->y, p->overlay_p);
+#else
+      mac_draw_bitmap (f, face->gc, p->x, p->y,
+                      p->wd, p->h, p->bits + p->dh, p->overlay_p);
+#endif
+      XSetForeground (display, face->gc, gcv.foreground);
+    }
+
+  mac_reset_clip_rectangles (display, face->gc);
+}
+
+#if USE_CG_DRAWING
+static void
+mac_define_fringe_bitmap (which, bits, h, wd)
+     int which;
+     unsigned short *bits;
+     int h, wd;
+{
+  int i;
+  CGDataProviderRef provider;
 
-      mac_draw_bitmap (display, window, &gcv, p->x, p->y,
-                      p->wd, p->h, bits, p->overlay_p);
+  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;
     }
 
-  mac_reset_clipping (display, window);
+  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
    suspend.  When starting Emacs, no window is mapped.  And nothing
    must be done to Emacs's own window if it is suspended (though that
@@ -1588,6 +2160,7 @@ XTreset_terminal_modes ()
 {
 }
 
+
 \f
 /***********************************************************************
                           Display Iterator
@@ -1599,18 +2172,28 @@ static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
 
 
-/* Return a pointer to per-char metric information in FONT of a
-   character pointed by B which is a pointer to an XChar2b.  */
+static void
+pcm_init (pcm, count)
+     XCharStruct *pcm;
+     int count;
+{
+  bzero (pcm, sizeof (XCharStruct) * count);
+  while (--count >= 0)
+    {
+      pcm->descent = PCM_INVALID;
+      pcm++;
+    }
+}
 
-#define PER_CHAR_METRIC(font, b)                                          \
-  ((font)->per_char                                                       \
-   ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2                   \
-      + (((font)->min_byte1 || (font)->max_byte1)                         \
-        ? (((b)->byte1 - (font)->min_byte1)                               \
-           * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
-        : 0))                                                             \
-   : &((font)->max_bounds))
+static enum pcm_status
+pcm_get_status (pcm)
+     XCharStruct *pcm;
+{
+  int height = pcm->ascent + pcm->descent;
 
+  /* Negative height means some special status.  */
+  return height >= 0 ? PCM_VALID : height;
+}
 
 /* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
    is not contained in the font.  */
@@ -1625,7 +2208,30 @@ x_per_char_metric (font, char2b)
 
   xassert (font && char2b);
 
-  if (font->per_char != NULL)
+#if USE_ATSUI
+  if (font->mac_style)
+    {
+      XCharStruct **row = font->bounds.rows + char2b->byte1;
+
+      if (*row == NULL)
+       {
+         *row = xmalloc (sizeof (XCharStruct) * 0x100);
+         pcm_init (*row, 0x100);
+       }
+      pcm = *row + char2b->byte2;
+      if (pcm_get_status (pcm) != PCM_VALID)
+       {
+         BLOCK_INPUT;
+         mac_query_char_extents (font->mac_style,
+                                 (char2b->byte1 << 8) + char2b->byte2,
+                                 NULL, NULL, pcm, NULL);
+         UNBLOCK_INPUT;
+       }
+    }
+  else
+    {
+#endif
+  if (font->bounds.per_char != NULL)
     {
       if (font->min_byte1 == 0 && font->max_byte1 == 0)
        {
@@ -1638,7 +2244,8 @@ x_per_char_metric (font, char2b)
          if (char2b->byte1 == 0
              && char2b->byte2 >= font->min_char_or_byte2
              && char2b->byte2 <= font->max_char_or_byte2)
-           pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
+           pcm = font->bounds.per_char
+             + (char2b->byte2 - font->min_char_or_byte2);
        }
       else
        {
@@ -1660,7 +2267,7 @@ x_per_char_metric (font, char2b)
              && char2b->byte2 >= font->min_char_or_byte2
              && char2b->byte2 <= font->max_char_or_byte2)
            {
-             pcm = (font->per_char
+             pcm = (font->bounds.per_char
                     + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
                        * (char2b->byte1 - font->min_byte1))
                     + (char2b->byte2 - font->min_char_or_byte2));
@@ -1676,9 +2283,16 @@ x_per_char_metric (font, char2b)
          && char2b->byte2 <= font->max_char_or_byte2)
        pcm = &font->max_bounds;
     }
+#if USE_ATSUI
+    }
+#endif
 
   return ((pcm == NULL
-          || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
+          || (pcm->width == 0
+#if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics.  */
+              && (pcm->rbearing - pcm->lbearing) == 0
+#endif
+              ))
          ? NULL : pcm);
 }
 
@@ -1716,10 +2330,12 @@ mac_encode_char (c, char2b, font_info, two_byte_p)
       /* It's a program.  */
       struct ccl_program *ccl = font_info->font_encoder;
 
+      check_ccl_update (ccl);
       if (CHARSET_DIMENSION (charset) == 1)
        {
          ccl->reg[0] = charset;
          ccl->reg[1] = char2b->byte2;
+         ccl->reg[2] = -1;
        }
       else
        {
@@ -1773,6 +2389,7 @@ mac_encode_char (c, char2b, font_info, two_byte_p)
  ***********************************************************************/
 
 
+
 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
@@ -1781,6 +2398,7 @@ static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
 static void x_draw_glyph_string  P_ ((struct glyph_string *));
+static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
 static void x_set_cursor_gc P_ ((struct glyph_string *));
 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
@@ -1792,7 +2410,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,
@@ -1977,9 +2594,11 @@ static INLINE void
 x_set_glyph_string_clipping (s)
      struct glyph_string *s;
 {
-  Rect r;
-  get_glyph_string_clip_rect (s, &r);
-  mac_set_clip_rectangle (s->display, s->window, &r);
+  Rect rects[MAX_CLIP_RECTS];
+  int n;
+
+  n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
+  mac_set_clip_rectangles (s->display, s->gc, rects, n);
 }
 
 
@@ -1991,20 +2610,36 @@ static void
 mac_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-#if 0
-  /* MAC_TODO: XTextExtents16 does nothing yet... */
+  if (!(s->cmp == NULL
+       && s->first_glyph->type == CHAR_GLYPH))
+    return;
 
-  if (s->cmp == NULL
-      && s->first_glyph->type == CHAR_GLYPH)
+  if (!s->two_byte_p
+#if USE_ATSUI
+      || s->font->mac_style
+#endif
+      )
     {
       XCharStruct cs;
-      int direction, font_ascent, font_descent;
-      XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
-                     &font_ascent, &font_descent, &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;
     }
-#endif
+  else
+    {
+      Rect r;
+      MacFontStruct *font = s->font;
+
+      TextFont (font->mac_fontnum);
+      TextSize (font->mac_fontsize);
+      TextFace (font->mac_fontface);
+
+      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;
+    }
 }
 
 
@@ -2015,21 +2650,10 @@ x_clear_glyph_string_rect (s, x, y, w, h)
      struct glyph_string *s;
      int x, y, w, h;
 {
-  XGCValues xgcv;
-
-  xgcv.foreground = s->gc->background;
-  XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
+  mac_erase_rectangle (s->f, s->gc, x, y, w, h);
 }
 
 
-/* We prefer not to use XDrawImageString (srcCopy text transfer mode)
-   on Mac OS X because:
-   - Screen is double-buffered.  (In srcCopy mode, a text is drawn
-     into an offscreen graphics world first.  So performance gain
-     cannot be expected.)
-   - It lowers rendering quality.
-   - Some fonts leave garbage on cursor movement.  */
-
 /* Draw the background of glyph_string S.  If S->background_filled_p
    is non-zero don't draw it.  FORCE_P non-zero means draw the
    background even if it wouldn't be drawn normally.  This is used
@@ -2061,12 +2685,10 @@ x_draw_glyph_string_background (s, force_p)
        }
       else
 #endif
-#ifdef MAC_OS8
         if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
               || force_p)
-#endif
        {
          x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
                                     s->background_width,
@@ -2083,7 +2705,7 @@ static void
 x_draw_glyph_string_foreground (s)
      struct glyph_string *s;
 {
-  int i, x;
+  int i, x, bg_width;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
@@ -2100,9 +2722,8 @@ x_draw_glyph_string_foreground (s)
       for (i = 0; i < s->nchars; ++i)
        {
          struct glyph *g = s->first_glyph + i;
-         mac_draw_rectangle (s->display, s->window,
-                           s->gc, x, s->y, g->pixel_width - 1,
-                           s->height - 1);
+         mac_draw_rectangle (s->f, s->gc, x, s->y,
+                             g->pixel_width - 1, s->height - 1);
          x += g->pixel_width;
        }
     }
@@ -2115,39 +2736,42 @@ x_draw_glyph_string_foreground (s)
        boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
 
       /* If we can use 8-bit functions, condense S->char2b.  */
-      if (!s->two_byte_p)
+      if (!s->two_byte_p
+#if USE_ATSUI
+         && GC_FONT (s->gc)->mac_style == NULL
+#endif
+         )
        for (i = 0; i < s->nchars; ++i)
          char1b[i] = s->char2b[i].byte2;
 
-#ifdef MAC_OS8
       /* Draw text with XDrawString if background has already been
         filled.  Otherwise, use XDrawImageString.  (Note that
         XDrawImageString is usually faster than XDrawString.)  Always
         use XDrawImageString when drawing the cursor so that there is
         no chance that characters under a box cursor are invisible.  */
-      if (s->for_overlaps_p
+      if (s->for_overlaps
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
-#endif
-       {
-         /* Draw characters with 16-bit or 8-bit functions.  */
-         if (s->two_byte_p)
-           XDrawString16 (s->display, s->window, s->gc, x,
-                          s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawString (s->display, s->window, s->gc, x,
-                        s->ybase - boff, char1b, s->nchars);
-       }
-#ifdef MAC_OS8
+       bg_width = 0;           /* Corresponds to XDrawString.  */
       else
-       {
-         if (s->two_byte_p)
-           XDrawImageString16 (s->display, s->window, s->gc, x,
-                               s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawImageString (s->display, s->window, s->gc, x,
-                             s->ybase - boff, char1b, s->nchars);
-       }
+       bg_width = s->background_width; /* Corresponds to XDrawImageString.  */
+
+      if (s->two_byte_p
+#if USE_ATSUI
+         || GC_FONT (s->gc)->mac_style
 #endif
+         )
+#if USE_CG_TEXT_DRAWING
+       if (!s->two_byte_p
+           && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
+                                        s->char2b, s->nchars, bg_width))
+         ;
+       else
+#endif
+         mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
+                                   s->char2b, s->nchars, bg_width);
+      else
+       mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
+                              char1b, s->nchars, bg_width);
     }
 }
 
@@ -2177,16 +2801,16 @@ x_draw_composite_glyph_string_foreground (s)
   if (s->font_not_found_p)
     {
       if (s->gidx == 0)
-       mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
-                         s->width - 1, s->height - 1);
+       mac_draw_rectangle (s->f, s->gc, x, s->y,
+                           s->width - 1, s->height - 1);
     }
   else
     {
       for (i = 0; i < s->nchars; i++, ++s->gidx)
-       XDrawString16 (s->display, s->window, s->gc,
-                      x + s->cmp->offsets[s->gidx * 2],
-                      s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                      s->char2b + i, 1);
+       mac_draw_string_16 (s->f, s->gc,
+                           x + s->cmp->offsets[s->gidx * 2],
+                           s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
+                           s->char2b + i, 1);
     }
 }
 
@@ -2542,7 +3166,6 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
      Rect *clip_rect;
 {
   Display *dpy = FRAME_MAC_DISPLAY (f);
-  Window window = FRAME_MAC_WINDOW (f);
   int i;
   GC gc;
 
@@ -2550,43 +3173,42 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
     gc = f->output_data.mac->white_relief.gc;
   else
     gc = f->output_data.mac->black_relief.gc;
-  mac_set_clip_rectangle (dpy, window, clip_rect);
+  mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
 
   /* Top.  */
   if (top_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                left_x + i * left_p, top_y + i,
-                right_x - i * right_p, top_y + i);
+      mac_draw_line (f, gc,
+                    left_x + i * left_p, top_y + i,
+                    right_x + 1 - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                left_x + i, top_y + i, left_x + i, bottom_y - i);
+      mac_draw_line (f, gc,
+                    left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
 
-  mac_reset_clipping (dpy, window);
+  mac_reset_clip_rectangles (dpy, gc);
   if (raised_p)
     gc = f->output_data.mac->black_relief.gc;
   else
     gc = f->output_data.mac->white_relief.gc;
-  mac_set_clip_rectangle (dpy, window,
-                         clip_rect);
+  mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
 
   /* Bottom.  */
   if (bot_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                left_x + i * left_p, bottom_y - i,
-                right_x - i * right_p, bottom_y - i);
+      mac_draw_line (f, gc,
+                    left_x + i * left_p, bottom_y - i,
+                    right_x + 1 - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
+      mac_draw_line (f, gc,
+                    right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
 
-  mac_reset_clipping (dpy, window);
+  mac_reset_clip_rectangles (dpy, gc);
 }
 
 
@@ -2606,28 +3228,30 @@ x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
 {
   XGCValues xgcv;
 
-  xgcv.foreground = s->face->box_color;
-  mac_set_clip_rectangle (s->display, s->window, clip_rect);
+  XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+  XSetForeground (s->display, s->gc, s->face->box_color);
+  mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
 
   /* Top.  */
-  XFillRectangle (s->display, s->window, &xgcv,
-                 left_x, top_y, right_x - left_x + 1, width);
+  mac_fill_rectangle (s->f, s->gc, left_x, top_y,
+                     right_x - left_x + 1, width);
 
   /* Left.  */
   if (left_p)
-    XFillRectangle (s->display, s->window, &xgcv,
-                   left_x, top_y, width, bottom_y - top_y + 1);
+    mac_fill_rectangle (s->f, s->gc, left_x, top_y,
+                       width, bottom_y - top_y + 1);
 
   /* Bottom.  */
-  XFillRectangle (s->display, s->window, &xgcv,
-                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+  mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
+                     right_x - left_x + 1, width);
 
   /* Right.  */
   if (right_p)
-    XFillRectangle (s->display, s->window, &xgcv,
-                   right_x - width + 1, top_y, width, bottom_y - top_y + 1);
+    mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
+                       top_y, width, bottom_y - top_y + 1);
 
-  mac_reset_clipping (s->display, s->window);
+  XSetForeground (s->display, s->gc, xgcv.foreground);
+  mac_reset_clip_rectangles (s->display, s->gc);
 }
 
 
@@ -2642,15 +3266,9 @@ x_draw_glyph_string_box (s)
   struct glyph *last_glyph;
   Rect clip_rect;
 
-  last_x = window_box_right (s->w, s->area);
-  if (s->row->full_width_p
-      && !s->w->pseudo_window_p)
-    {
-      last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
-      if (s->area != RIGHT_MARGIN_AREA
-         || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
-       last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
-    }
+  last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
+           ? WINDOW_RIGHT_EDGE_X (s->w)
+           : window_box_right (s->w, s->area));
 
   /* The glyph that may have a right box line.  */
   last_glyph = (s->cmp || s->img
@@ -2716,15 +3334,26 @@ x_draw_image_foreground (s)
     {
       x_set_glyph_string_clipping (s);
 
+#if USE_CG_DRAWING
+      mac_draw_cg_image (s->img->data.ptr_val,
+                        s->f, s->gc, s->slice.x, s->slice.y,
+                        s->slice.width, s->slice.height, x, y, 1);
+#endif
       if (s->img->mask)
-       mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
-                                s->window, s->gc, s->slice.x, s->slice.y,
+#if !USE_CG_DRAWING
+       mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
+                                s->f, s->gc, s->slice.x, s->slice.y,
                                 s->slice.width, s->slice.height, x, y);
+#else
+       ;
+#endif
       else
        {
-         mac_copy_area (s->display, s->img->pixmap,
-                        s->window, s->gc, s->slice.x, s->slice.y,
+#if !USE_CG_DRAWING
+         mac_copy_area (s->img->pixmap,
+                        s->f, s->gc, s->slice.x, s->slice.y,
                         s->slice.width, s->slice.height, x, y);
+#endif
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2736,8 +3365,7 @@ x_draw_image_foreground (s)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             mac_draw_rectangle (s->display, s->window, s->gc,
-                                 x - r, y - r,
+             mac_draw_rectangle (s->f, s->gc, x - r, y - r,
                                  s->slice.width + r*2 - 1,
                                  s->slice.height + r*2 - 1);
            }
@@ -2745,7 +3373,7 @@ x_draw_image_foreground (s)
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
-    mac_draw_rectangle (s->display, s->window, s->gc, x, y,
+    mac_draw_rectangle (s->f, s->gc, x, y,
                        s->slice.width - 1, s->slice.height - 1);
 }
 
@@ -2803,70 +3431,6 @@ x_draw_image_relief (s)
 }
 
 
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-/* Draw the foreground of image glyph string S to PIXMAP.  */
-
-static void
-x_draw_image_foreground_1 (s, pixmap)
-     struct glyph_string *s;
-     Pixmap pixmap;
-{
-  int x = 0;
-  int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
-
-  /* If first glyph of S has a left box line, start drawing it to the
-     right of that line.  */
-  if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p
-      && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
-
-  /* If there is a margin around the image, adjust x- and y-position
-     by that margin.  */
-  if (s->slice.x == 0)
-    x += s->img->hmargin;
-  if (s->slice.y == 0)
-    y += s->img->vmargin;
-
-  if (s->img->pixmap)
-    {
-      if (s->img->mask)
-       mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
-                                          s->img->mask, pixmap, s->gc,
-                                          s->slice.x, s->slice.y,
-                                          s->slice.width, s->slice.height,
-                                          x, y);
-      else
-       {
-         mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
-                                  s->slice.x, s->slice.y,
-                                  s->slice.width, s->slice.height,
-                                  x, y);
-
-         /* When the image has a mask, we can expect that at
-            least part of a mouse highlight or a block cursor will
-            be visible.  If the image doesn't have a mask, make
-            a block cursor visible by drawing a rectangle around
-            the image.  I believe it's looking better if we do
-            nothing here for mouse-face.  */
-         if (s->hl == DRAW_CURSOR)
-           {
-             int r = s->img->relief;
-             if (r < 0) r = -r;
-             mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
-                                 s->slice.width + r*2 - 1,
-                                 s->slice.height + r*2 - 1);
-           }
-       }
-    }
-  else
-    /* Draw a rectangle if image could not be loaded.  */
-    mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
-                                 s->slice.width - 1, s->slice.height - 1);
-}
-#endif
-
-
 /* Draw part of the background of glyph string S.  X, Y, W, and H
    give the rectangle to draw.  */
 
@@ -2911,7 +3475,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;
 
@@ -2936,63 +3499,13 @@ x_draw_image_glyph_string (s)
       if (s->slice.y == 0)
        y += box_line_vwidth;
 
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-      if (s->img->mask)
-       {
-         /* Create a pixmap as large as the glyph string.  Fill it
-            with the background color.  Copy the image to it, using
-            its mask.  Copy the temporary pixmap to the display.  */
-         int depth = one_mac_display_info.n_planes;
-
-         /* Create a pixmap as large as the glyph string.  */
-         pixmap = XCreatePixmap (s->display, s->window,
-                                 s->background_width,
-                                 s->height, depth);
-
-         /* Fill the pixmap with the background color/stipple.  */
-#if 0 /* TODO: stipple */
-         if (s->stippled_p)
-           {
-             /* Fill background with a stipple pattern.  */
-             XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
-             XFillRectangle (s->display, pixmap, s->gc,
-                             0, 0, s->background_width, s->height);
-             XSetFillStyle (s->display, s->gc, FillSolid);
-           }
-         else
-#endif
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
-                           &xgcv);
-             XSetForeground (s->display, s->gc, xgcv.background);
-             mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
-                                           0, 0, s->background_width,
-                                           s->height);
-             XSetForeground (s->display, s->gc, xgcv.foreground);
-           }
-       }
-      else
-#endif
-       x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+      x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
 
       s->background_filled_p = 1;
     }
 
   /* Draw the foreground.  */
-#if 0 /* TODO: figure out if we need to do this on Mac.  */
-  if (pixmap != 0)
-    {
-      x_draw_image_foreground_1 (s, pixmap);
-      x_set_glyph_string_clipping (s);
-      mac_copy_area (s->display, pixmap, s->window, s->gc,
-                    0, 0, s->background_width, s->height, s->x, s->y);
-      mac_reset_clipping (s->display, s->window);
-      XFreePixmap (s->display, pixmap);
-    }
-  else
-#endif
-    x_draw_image_foreground (s);
+  x_draw_image_foreground (s);
 
   /* If we must draw a relief around the image, do it.  */
   if (s->img->relief
@@ -3039,7 +3552,7 @@ x_draw_stretch_glyph_string (s)
            gc = s->face->gc;
 
          get_glyph_string_clip_rect (s, &r);
-         mac_set_clip_rectangle (s->display, s->window, &r);
+         mac_set_clip_rectangles (s->display, gc, &r, 1);
 
 #if 0 /* MAC_TODO: stipple */
          if (s->face->stipple)
@@ -3051,15 +3564,7 @@ x_draw_stretch_glyph_string (s)
            }
          else
 #endif /* MAC_TODO */
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
-             XSetForeground (s->display, gc, xgcv.background);
-             XFillRectangle (s->display, s->window, gc, x, y, w, h);
-             XSetForeground (s->display, gc, xgcv.foreground);
-           }
-
-         mac_reset_clipping (s->display, s->window);
+           mac_erase_rectangle (s->f, gc, x, y, w, h);
        }
     }
   else if (!s->background_filled_p)
@@ -3078,10 +3583,12 @@ x_draw_glyph_string (s)
 {
   int relief_drawn_p = 0;
 
-  /* If S draws into the background of its successor, draw the
-     background of the successor first so that S can draw into it.
-     This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps_p)
+  /* If S draws into the background of its successor that does not
+     draw a cursor, draw the background of the successor first so that
+     S can draw into it.  This makes S->next use XDrawString instead
+     of XDrawImageString.  */
+  if (s->next && s->right_overhang && !s->for_overlaps
+      && s->next->hl != DRAW_CURSOR)
     {
       xassert (s->next->img == NULL);
       x_set_glyph_string_gc (s->next);
@@ -3094,7 +3601,7 @@ x_draw_glyph_string (s)
 
   /* Draw relief (if any) in advance for char/composition so that the
      glyph string can be drawn over it.  */
-  if (!s->for_overlaps_p
+  if (!s->for_overlaps
       && s->face->box != FACE_NO_BOX
       && (s->first_glyph->type == CHAR_GLYPH
          || s->first_glyph->type == COMPOSITE_GLYPH))
@@ -3120,7 +3627,7 @@ x_draw_glyph_string (s)
       break;
 
     case CHAR_GLYPH:
-      if (s->for_overlaps_p)
+      if (s->for_overlaps)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 0);
@@ -3128,7 +3635,7 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps_p || s->gidx > 0)
+      if (s->for_overlaps || s->gidx > 0)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -3139,7 +3646,7 @@ x_draw_glyph_string (s)
       abort ();
     }
 
-  if (!s->for_overlaps_p)
+  if (!s->for_overlaps)
     {
       /* Draw underline.  */
       if (s->face->underline_p)
@@ -3148,15 +3655,15 @@ x_draw_glyph_string (s)
           unsigned long dy = s->height - h;
 
          if (s->face->underline_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
+           mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                               s->width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->underline_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
+             mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                                 s->width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3167,15 +3674,15 @@ x_draw_glyph_string (s)
          unsigned long dy = 0, h = 1;
 
          if (s->face->overline_color_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
+           mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                               s->width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->overline_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
+             mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                                 s->width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3187,15 +3694,15 @@ x_draw_glyph_string (s)
          unsigned long dy = (s->height - h) / 2;
 
          if (s->face->strike_through_color_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
+           mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                               s->width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->strike_through_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
+             mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                                 s->width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3206,7 +3713,7 @@ x_draw_glyph_string (s)
     }
 
   /* Reset clipping.  */
-  mac_reset_clipping (s->display, s->window);
+  mac_reset_clip_rectangles (s->display, s->gc);
 }
 
 /* Shift display to make room for inserted glyphs.   */
@@ -3216,8 +3723,7 @@ mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
      struct frame *f;
      int x, y, width, height, shift_by;
 {
-  mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                  f->output_data.mac->normal_gc,
+  mac_scroll_area (f, f->output_data.mac->normal_gc,
                   x, y, width, height,
                   x + shift_by, y);
 }
@@ -3255,13 +3761,11 @@ x_clear_frame ()
   /* We don't set the output cursor here because there will always
      follow an explicit cursor_to.  */
   BLOCK_INPUT;
-  XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+  mac_clear_window (f);
 
-#if 0  /* Clearing frame on Mac OS clears scroll bars.  */
   /* We have to clear the scroll bars, too.  If we have changed
      colors or something like that, then they should be notified.  */
   x_scroll_bar_clear (f);
-#endif
 
   XFlush (FRAME_MAC_DISPLAY (f));
   UNBLOCK_INPUT;
@@ -3314,9 +3818,54 @@ void
 XTflash (f)
      struct frame *f;
 {
+  /* Get the height not including a menu bar widget.  */
+  int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
+  /* Height of each line to flash.  */
+  int flash_height = FRAME_LINE_HEIGHT (f);
+  /* These will be the left and right margins of the rectangles.  */
+  int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
+  int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
+
+  int width;
+
+  /* Don't flash the area between a scroll bar and the frame
+     edge it is next to.  */
+  switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
+    {
+    case vertical_scroll_bar_left:
+      flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+      break;
+
+    case vertical_scroll_bar_right:
+      flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+      break;
+
+    default:
+      break;
+    }
+
+  width = flash_right - flash_left;
+
   BLOCK_INPUT;
 
-  FlashMenuBar (0);
+  /* If window is tall, flash top and bottom line.  */
+  if (height > 3 * FRAME_LINE_HEIGHT (f))
+    {
+      mac_invert_rectangle (f, flash_left,
+                           (FRAME_INTERNAL_BORDER_WIDTH (f)
+                            + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
+                           width, flash_height);
+      mac_invert_rectangle (f, flash_left,
+                           (height - flash_height
+                            - FRAME_INTERNAL_BORDER_WIDTH (f)),
+                           width, flash_height);
+    }
+  else
+    /* If it is short, flash it all.  */
+    mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                         width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+
+  x_flush (f);
 
   {
     struct timeval wakeup;
@@ -3328,24 +3877,46 @@ XTflash (f)
     wakeup.tv_sec += (wakeup.tv_usec / 1000000);
     wakeup.tv_usec %= 1000000;
 
-    /* Keep waiting until past the time wakeup.  */
-    while (1)
+    /* Keep waiting until past the time wakeup or any input gets
+       available.  */
+    while (! detect_input_pending ())
       {
-        struct timeval timeout;
+       struct timeval current;
+       struct timeval timeout;
+
+       EMACS_GET_TIME (current);
 
-        EMACS_GET_TIME (timeout);
+       /* Break if result would be negative.  */
+       if (timeval_subtract (&current, wakeup, current))
+         break;
 
-        /* In effect, timeout = wakeup - timeout.
-           Break if result would be negative.  */
-        if (timeval_subtract (&timeout, wakeup, timeout))
-          break;
+       /* How long `select' should wait.  */
+       timeout.tv_sec = 0;
+       timeout.tv_usec = 10000;
 
-        /* Try to wait that long--but we might wake up sooner.  */
-        select (0, NULL, NULL, NULL, &timeout);
+       /* Try to wait that long--but we might wake up sooner.  */
+       select (0, NULL, NULL, NULL, &timeout);
       }
   }
 
-  FlashMenuBar (0);
+  /* If window is tall, flash top and bottom line.  */
+  if (height > 3 * FRAME_LINE_HEIGHT (f))
+    {
+      mac_invert_rectangle (f, flash_left,
+                           (FRAME_INTERNAL_BORDER_WIDTH (f)
+                            + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
+                           width, flash_height);
+      mac_invert_rectangle (f, flash_left,
+                           (height - flash_height
+                            - FRAME_INTERNAL_BORDER_WIDTH (f)),
+                           width, flash_height);
+    }
+  else
+    /* If it is short, flash it all.  */
+    mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                         width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+
+  x_flush (f);
 
   UNBLOCK_INPUT;
 }
@@ -3373,7 +3944,6 @@ XTring_bell ()
     }
 }
 
-
 \f
 /* Specify how many text lines, from the top of the window,
    should be affected by insert-lines and delete-lines operations.
@@ -3448,11 +4018,10 @@ x_scroll_run (w, run)
   updated_window = w;
   x_clear_cursor (w);
 
-  mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                f->output_data.mac->normal_gc,
-                x, from_y,
-                width, height,
-                x, to_y);
+  mac_scroll_area (f, f->output_data.mac->normal_gc,
+                  x, from_y,
+                  width, height,
+                  x, to_y);
 
   UNBLOCK_INPUT;
 }
@@ -3468,6 +4037,14 @@ static void
 frame_highlight (f)
      struct frame *f;
 {
+  OSErr err;
+  ControlRef root_control;
+
+  BLOCK_INPUT;
+  err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
+  if (err == noErr)
+    ActivateControl (root_control);
+  UNBLOCK_INPUT;
   x_update_cursor (f, 1);
 }
 
@@ -3475,6 +4052,14 @@ static void
 frame_unhighlight (f)
      struct frame *f;
 {
+  OSErr err;
+  ControlRef root_control;
+
+  BLOCK_INPUT;
+  err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
+  if (err == noErr)
+    DeactivateControl (root_control);
+  UNBLOCK_INPUT;
   x_update_cursor (f, 1);
 }
 
@@ -3517,6 +4102,68 @@ x_new_focus_frame (dpyinfo, frame)
   x_frame_rehighlight (dpyinfo);
 }
 
+/* Handle FocusIn and FocusOut state changes for FRAME.
+   If FRAME has focus and there exists more than one frame, puts
+   a FOCUS_IN_EVENT into *BUFP.  */
+
+static void
+mac_focus_changed (type, dpyinfo, frame, bufp)
+     int type;
+     struct mac_display_info *dpyinfo;
+     struct frame *frame;
+     struct input_event *bufp;
+{
+  if (type == activeFlag)
+    {
+      if (dpyinfo->x_focus_event_frame != frame)
+        {
+          x_new_focus_frame (dpyinfo, frame);
+          dpyinfo->x_focus_event_frame = frame;
+
+          /* Don't stop displaying the initial startup message
+             for a switch-frame event we don't need.  */
+          if (GC_NILP (Vterminal_frame)
+              && GC_CONSP (Vframe_list)
+              && !GC_NILP (XCDR (Vframe_list)))
+            {
+              bufp->kind = FOCUS_IN_EVENT;
+              XSETFRAME (bufp->frame_or_window, frame);
+            }
+        }
+    }
+  else
+    {
+      if (dpyinfo->x_focus_event_frame == frame)
+        {
+          dpyinfo->x_focus_event_frame = 0;
+          x_new_focus_frame (dpyinfo, 0);
+        }
+    }
+}
+
+/* The focus may have changed.  Figure out if it is a real focus change,
+   by checking both FocusIn/Out and Enter/LeaveNotify events.
+
+   Returns FOCUS_IN_EVENT event in *BUFP. */
+
+static void
+x_detect_focus_change (dpyinfo, event, bufp)
+     struct mac_display_info *dpyinfo;
+     EventRecord *event;
+     struct input_event *bufp;
+{
+  struct frame *frame;
+
+  frame = mac_window_to_frame ((WindowPtr) event->message);
+  if (! frame)
+    return;
+
+  /* On Mac, this is only called from focus events, so no switch needed.  */
+  mac_focus_changed ((event->modifiers & activeFlag),
+                    dpyinfo, frame, bufp);
+}
+
+
 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
 void
@@ -3566,149 +4213,13 @@ x_frame_rehighlight (dpyinfo)
     {
       if (old_highlight)
        frame_unhighlight (old_highlight);
-      if (dpyinfo->x_highlight_frame)
-       frame_highlight (dpyinfo->x_highlight_frame);
-    }
-}
-
-
-\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 (dpyinfo->x_highlight_frame)
+       frame_highlight (dpyinfo->x_highlight_frame);
+    }
 }
 
-#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 */
 
+\f
 /* Convert a keysym to its name.  */
 
 char *
@@ -3729,43 +4240,6 @@ x_get_keysym_name (keysym)
 }
 
 
-\f
-#if 0
-/* Mouse clicks and mouse movement.  Rah.  */
-
-/* Prepare a mouse-event in *RESULT for placement in the input queue.
-
-   If the event is a button press, then note that we have grabbed
-   the mouse.  */
-
-static Lisp_Object
-construct_mouse_click (result, event, f)
-     struct input_event *result;
-     EventRecord *event;
-     struct frame *f;
-{
-  Point mouseLoc;
-
-  result->kind = MOUSE_CLICK_EVENT;
-  result->code = 0;  /* only one mouse button */
-  result->timestamp = event->when;
-  result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
-
-  mouseLoc = event->where;
-
-  SetPortWindowPort (FRAME_MAC_WINDOW (f));
-
-  GlobalToLocal (&mouseLoc);
-  XSETINT (result->x, mouseLoc.h);
-  XSETINT (result->y, mouseLoc.v);
-
-  XSETFRAME (result->frame_or_window, f);
-
-  result->arg = Qnil;
-  return Qnil;
-}
-#endif
-
 \f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
@@ -3778,7 +4252,7 @@ construct_mouse_click (result, event, f)
 static Point last_mouse_motion_position;
 static Lisp_Object last_mouse_motion_frame;
 
-static void
+static int
 note_mouse_movement (frame, pos)
      FRAME_PTR frame;
      Point *pos;
@@ -3809,34 +4283,29 @@ note_mouse_movement (frame, pos)
            rif->define_frame_cursor (frame,
                                      frame->output_data.mac->nontext_cursor);
        }
+      return 1;
     }
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (pos->h < last_mouse_glyph.left
-          || pos->h >= last_mouse_glyph.right
-          || pos->v < last_mouse_glyph.top
-          || pos->v >= last_mouse_glyph.bottom)
+  if (frame != last_mouse_glyph_frame
+      || !PtInRect (*pos, &last_mouse_glyph))
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, pos->h, pos->v);
+      /* Remember which glyph we're now on.  */
+      remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
+      last_mouse_glyph_frame = frame;
+      return 1;
     }
-}
-
-/* This is used for debugging, to turn off note_mouse_highlight.  */
-
-int disable_mouse_highlight;
 
+  return 0;
+}
 
 \f
 /************************************************************************
                              Mouse Face
  ************************************************************************/
 
-static struct scroll_bar *x_window_to_scroll_bar ();
-static void x_scroll_bar_report_motion ();
-static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
-
-
 /* MAC TODO:  This should be called from somewhere (or removed)  ++KFS */
 
 static void
@@ -3850,223 +4319,389 @@ redo_mouse_highlight ()
 }
 
 
-/* Try to determine frame pixel position and size of the glyph under
-   frame pixel coordinates X/Y on frame F .  Return the position and
-   size in *RECT.  Value is non-zero if we could compute these
-   values.  */
+static struct frame *
+mac_focus_frame (dpyinfo)
+     struct mac_display_info *dpyinfo;
+{
+  if (dpyinfo->x_focus_frame)
+    return dpyinfo->x_focus_frame;
+  else
+    /* Mac version may get events, such as a menu bar click, even when
+       all the frames are invisible.  In this case, we regard the
+       event came to the selected frame.  */
+    return SELECTED_FRAME ();
+}
+
 
-static int
-glyph_rect (f, x, y, rect)
-     struct frame *f;
-     int x, y;
-     Rect *rect;
+/* Return the current position of the mouse.
+   *FP should be a frame which indicates which display to ask about.
+
+   If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
+   and *PART to the frame, window, and scroll bar part that the mouse
+   is over.  Set *X and *Y to the portion and whole of the mouse's
+   position on the scroll bar.
+
+   If the mouse movement started elsewhere, set *FP to the frame the
+   mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
+   the mouse is over.
+
+   Set *TIME to the server time-stamp for the time at which the mouse
+   was at this position.
+
+   Don't store anything if we don't have a valid set of values to report.
+
+   This clears the mouse_moved flag, so we can wait for the next mouse
+   movement.  */
+
+static void
+XTmouse_position (fp, insist, bar_window, part, x, y, time)
+     FRAME_PTR *fp;
+     int insist;
+     Lisp_Object *bar_window;
+     enum scroll_bar_part *part;
+     Lisp_Object *x, *y;
+     unsigned long *time;
 {
-  Lisp_Object window;
+  FRAME_PTR f1;
 
-  window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
+  BLOCK_INPUT;
 
-  if (!NILP (window))
+  if (! NILP (last_mouse_scroll_bar) && insist == 0)
+    x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+  else
     {
-      struct window *w = XWINDOW (window);
-      struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-      struct glyph_row *end = r + w->current_matrix->nrows - 1;
-
-      for (; r < end && r->enabled_p; ++r)
-       if (r->y <= y && r->y + r->height > y)
-         {
-           /* Found the row at y.  */
-           struct glyph *g = r->glyphs[TEXT_AREA];
-           struct glyph *end = g + r->used[TEXT_AREA];
-           int gx;
+      Lisp_Object frame, tail;
 
-           rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
-           rect->bottom = rect->top + r->height;
+      /* Clear the mouse-moved flag for every frame on this display.  */
+      FOR_EACH_FRAME (tail, frame)
+       XFRAME (frame)->mouse_moved = 0;
 
-           if (x < r->x)
-             {
-               /* x is to the left of the first glyph in the row.  */
-               /* Shouldn't this be a pixel value?
-                  WINDOW_LEFT_EDGE_X (w) seems to be the right value.
-                  ++KFS */
-               rect->left = WINDOW_LEFT_EDGE_COL (w);
-               rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
-               return 1;
-             }
+      last_mouse_scroll_bar = Qnil;
 
-           for (gx = r->x; g < end; gx += g->pixel_width, ++g)
-             if (gx <= x && gx + g->pixel_width > x)
-               {
-                 /* x is on a glyph.  */
-                 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-                 rect->right = rect->left + g->pixel_width;
-                 return 1;
-               }
+      if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
+         && FRAME_LIVE_P (last_mouse_frame))
+       f1 = last_mouse_frame;
+      else
+       f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
 
-           /* x is to the right of the last glyph in the row.  */
-           rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-           /* Shouldn't this be a pixel value?
-              WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
-              ++KFS */
-           rect->right = WINDOW_RIGHT_EDGE_COL (w);
-           return 1;
-         }
+      if (f1)
+       {
+         /* Ok, we found a frame.  Store all the values.
+            last_mouse_glyph is a rectangle used to reduce the
+            generation of mouse events.  To not miss any motion
+            events, we must divide the frame into rectangles of the
+            size of the smallest character that could be displayed
+            on it, i.e. into the same rectangles that matrices on
+            the frame are divided into.  */
+         Point mouse_pos;
+
+         SetPortWindowPort (FRAME_MAC_WINDOW (f1));
+         GetMouse (&mouse_pos);
+         remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
+                               &last_mouse_glyph);
+         last_mouse_glyph_frame = f1;
+
+         *bar_window = Qnil;
+         *part = 0;
+         *fp = f1;
+         XSETINT (*x, mouse_pos.h);
+         XSETINT (*y, mouse_pos.v);
+         *time = last_mouse_movement_time;
+       }
     }
 
-  /* The y is not on any row.  */
-  return 0;
+  UNBLOCK_INPUT;
 }
 
-/* MAC TODO:  This should be called from somewhere (or removed)  ++KFS */
+\f
+/************************************************************************
+                        Toolkit scroll bars
+ ************************************************************************/
 
-/* Record the position of the mouse in last_mouse_glyph.  */
-static void
-remember_mouse_glyph (f1, gx, gy)
-     struct frame * f1;
-     int gx, gy;
-{
-  if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
-    {
-      int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
-      int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
+#ifdef USE_TOOLKIT_SCROLL_BARS
 
-      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
-        round down even for negative values.  */
-      if (gx < 0)
-       gx -= width - 1;
-      if (gy < 0)
-       gy -= height - 1;
-#if 0
-      /* This was the original code from XTmouse_position, but it seems
-        to give the position of the glyph diagonally next to the one
-        the mouse is over.  */
-      gx = (gx + width - 1) / width * width;
-      gy = (gy + height - 1) / height * height;
-#else
-      gx = gx / width * width;
-      gy = gy / height * height;
-#endif
+static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
+static OSStatus install_scroll_bar_timer P_ ((void));
+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,
+                                            Rect *));
+static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
+                                          ControlPartCode,
+                                          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 *,
+                                         Point, struct input_event *));
+static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
+                                               int, int, int));
 
-      last_mouse_glyph.left = gx;
-      last_mouse_glyph.top = gy;
-      last_mouse_glyph.right  = gx + width;
-      last_mouse_glyph.bottom = gy + height;
-    }
+/* Last scroll bar part sent in x_scroll_bar_handle_*.  */
+
+static int last_scroll_bar_part;
+
+static EventLoopTimerRef scroll_bar_timer;
+
+static int scroll_bar_timer_event_posted_p;
+
+#define SCROLL_BAR_FIRST_DELAY 0.5
+#define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
+
+static pascal void
+scroll_bar_timer_callback (timer, data)
+     EventLoopTimerRef timer;
+     void *data;
+{
+  OSStatus err;
+
+  err = mac_post_mouse_moved_event ();
+  if (err == noErr)
+    scroll_bar_timer_event_posted_p = 1;
 }
 
+static OSStatus
+install_scroll_bar_timer ()
+{
+  static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
+
+  if (scroll_bar_timer_callbackUPP == NULL)
+    scroll_bar_timer_callbackUPP =
+      NewEventLoopTimerUPP (scroll_bar_timer_callback);
+
+  if (scroll_bar_timer == NULL)
+    /* Mac OS X and CarbonLib 1.5 and later allow us to specify
+       kEventDurationForever as delays.  */
+    return
+      InstallEventLoopTimer (GetCurrentEventLoop (),
+                            kEventDurationForever, kEventDurationForever,
+                            scroll_bar_timer_callbackUPP, NULL,
+                            &scroll_bar_timer);
+}
 
-static WindowPtr
-front_emacs_window ()
+static OSStatus
+set_scroll_bar_timer (delay)
+     EventTimerInterval delay;
 {
-#if TARGET_API_MAC_CARBON
-  WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
+  if (scroll_bar_timer == NULL)
+    install_scroll_bar_timer ();
 
-  while (wp && !is_emacs_window (wp))
-    wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
-#else
-  WindowPtr wp = FrontWindow ();
+  scroll_bar_timer_event_posted_p = 0;
 
-  while (wp && (wp == tip_window || !is_emacs_window (wp)))
-    wp = GetNextWindow (wp);
-#endif
+  return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
+}
+
+static int
+control_part_code_to_scroll_bar_part (part_code)
+     ControlPartCode part_code;
+{
+  switch (part_code)
+    {
+    case kControlUpButtonPart:         return scroll_bar_up_arrow;
+    case kControlDownButtonPart:       return scroll_bar_down_arrow;
+    case kControlPageUpPart:           return scroll_bar_above_handle;
+    case kControlPageDownPart:         return scroll_bar_below_handle;
+    case kControlIndicatorPart:                return scroll_bar_handle;
+    }
 
-  return wp;
+  return -1;
 }
 
-#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
+static void
+construct_scroll_bar_click (bar, part, bufp)
+     struct scroll_bar *bar;
+     int part;
+     struct input_event *bufp;
+{
+  bufp->kind = SCROLL_BAR_CLICK_EVENT;
+  bufp->frame_or_window = bar->window;
+  bufp->arg = Qnil;
+  bufp->part = part;
+  bufp->code = 0;
+  XSETINT (bufp->x, 0);
+  XSETINT (bufp->y, 0);
+  bufp->modifiers = 0;
+}
 
-/* Return the current position of the mouse.
-   *fp should be a frame which indicates which display to ask about.
+static OSStatus
+get_control_part_bounds (ch, part_code, rect)
+     ControlHandle ch;
+     ControlPartCode part_code;
+     Rect *rect;
+{
+  RgnHandle region = NewRgn ();
+  OSStatus err;
 
-   If the mouse movement started in a scroll bar, set *fp, *bar_window,
-   and *part to the frame, window, and scroll bar part that the mouse
-   is over.  Set *x and *y to the portion and whole of the mouse's
-   position on the scroll bar.
+  err = GetControlRegion (ch, part_code, region);
+  if (err == noErr)
+    GetRegionBounds (region, rect);
+  DisposeRgn (region);
 
-   If the mouse movement started elsewhere, set *fp to the frame the
-   mouse is on, *bar_window to nil, and *x and *y to the character cell
-   the mouse is over.
+  return err;
+}
 
-   Set *time to the server time-stamp for the time at which the mouse
-   was at this position.
+static void
+x_scroll_bar_handle_press (bar, part_code, bufp)
+     struct scroll_bar *bar;
+     ControlPartCode part_code;
+     struct input_event *bufp;
+{
+  int part = control_part_code_to_scroll_bar_part (part_code);
 
-   Don't store anything if we don't have a valid set of values to report.
+  if (part < 0)
+    return;
 
-   This clears the mouse_moved flag, so we can wait for the next mouse
-   movement.  */
+  if (part != scroll_bar_handle)
+    {
+      construct_scroll_bar_click (bar, part, bufp);
+      HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
+      set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
+    }
+
+  last_scroll_bar_part = part;
+  bar->dragging = Qnil;
+  tracked_scroll_bar = bar;
+}
 
 static void
-XTmouse_position (fp, insist, bar_window, part, x, y, time)
-     FRAME_PTR *fp;
-     int insist;
-     Lisp_Object *bar_window;
-     enum scroll_bar_part *part;
-     Lisp_Object *x, *y;
-     unsigned long *time;
+x_scroll_bar_handle_release (bar, bufp)
+     struct scroll_bar *bar;
+     struct input_event *bufp;
 {
-  Point mouse_pos;
-  int ignore1, ignore2;
-  WindowPtr wp = front_emacs_window ();
-  struct frame *f;
-  Lisp_Object frame, tail;
+  if (last_scroll_bar_part != scroll_bar_handle
+      || !GC_NILP (bar->dragging))
+    construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
 
-  if (is_emacs_window(wp))
-    f = mac_window_to_frame (wp);
+  HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
+  set_scroll_bar_timer (kEventDurationForever);
 
-  BLOCK_INPUT;
+  last_scroll_bar_part = -1;
+  bar->dragging = Qnil;
+  tracked_scroll_bar = NULL;
+}
 
-  if (! NILP (last_mouse_scroll_bar) && insist == 0)
-    x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
-  else
+static void
+x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
+     WindowPtr win;
+     struct scroll_bar *bar;
+     Point mouse_pos;
+     struct input_event *bufp;
+{
+  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+
+  if (last_scroll_bar_part == scroll_bar_handle)
     {
-      /* Clear the mouse-moved flag for every frame on this display.  */
-      FOR_EACH_FRAME (tail, frame)
-        XFRAME (frame)->mouse_moved = 0;
+      int top, top_range;
+      Rect r;
 
-      last_mouse_scroll_bar = Qnil;
+      get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
+                              kControlIndicatorPart, &r);
 
-      SetPortWindowPort (wp);
+      if (GC_NILP (bar->dragging))
+       XSETINT (bar->dragging, mouse_pos.v - r.top);
 
-      GetMouse (&mouse_pos);
+      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;
 
-      pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
-                             &last_mouse_glyph, insist);
+      if (top < 0)
+       top = 0;
+      if (top > top_range)
+       top = top_range;
 
-      *bar_window = Qnil;
-      *part = scroll_bar_handle;
-      *fp = f;
-      XSETINT (*x, mouse_pos.h);
-      XSETINT (*y, mouse_pos.v);
-      *time = last_mouse_movement_time;
+      construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
+      XSETINT (bufp->x, top);
+      XSETINT (bufp->y, top_range);
     }
+  else
+    {
+      ControlPartCode part_code;
+      int unhilite_p = 0, part;
 
-  UNBLOCK_INPUT;
-}
+      if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
+       unhilite_p = 1;
+      else
+       {
+         part = control_part_code_to_scroll_bar_part (part_code);
 
-\f
-/***********************************************************************
-                              Tool-bars
- ***********************************************************************/
+         switch (last_scroll_bar_part)
+           {
+           case scroll_bar_above_handle:
+           case scroll_bar_below_handle:
+             if (part != scroll_bar_above_handle
+                 && part != scroll_bar_below_handle)
+               unhilite_p = 1;
+             break;
+
+           case scroll_bar_up_arrow:
+           case scroll_bar_down_arrow:
+             if (part != scroll_bar_up_arrow
+                 && part != scroll_bar_down_arrow)
+               unhilite_p = 1;
+             break;
+           }
+       }
+
+      if (unhilite_p)
+       HiliteControl (SCROLL_BAR_CONTROL_HANDLE (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);
+         set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
+       }
+    }
+}
 
-/* Handle mouse button event on the tool-bar of frame F, at
-   frame-relative coordinates X/Y.  EVENT_TYPE is either ButtionPress
-   or ButtonRelase.  */
+/* Set the thumb size and position of scroll bar BAR.  We are currently
+   displaying PORTION out of a whole WHOLE, and our position POSITION.  */
 
 static void
-mac_handle_tool_bar_click (f, button_event)
-     struct frame *f;
-     EventRecord *button_event;
+x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
+     struct scroll_bar *bar;
+     int portion, position, whole;
 {
-  int x = button_event->where.h;
-  int y = button_event->where.v;
+  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+  int value, viewsize, maximum;
+
+  if (XINT (bar->track_height) == 0)
+    return;
 
-  if (button_event->what == mouseDown)
-    handle_tool_bar_click (f, x, y, 1, 0);
+  if (whole == 0)
+    value = 0, viewsize = 1, maximum = 0;
   else
-    handle_tool_bar_click (f, x, y, 0,
-                          x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
-                                                    button_event->modifiers));
+    {
+      value = position;
+      viewsize = portion;
+      maximum = max (0, whole - portion);
+    }
+
+  BLOCK_INPUT;
+
+  if (GetControlViewSize (ch) != viewsize
+      || GetControl32BitValue (ch) != value
+      || GetControl32BitMaximum (ch) != maximum)
+    {
+      /* Temporarily hide the scroll bar to avoid multiple redraws.  */
+      SetControlVisibility (ch, false, false);
+
+      SetControl32BitMaximum (ch, maximum);
+      SetControl32BitValue (ch, value);
+      SetControlViewSize (ch, viewsize);
+
+      SetControlVisibility (ch, true, true);
+    }
+
+  UNBLOCK_INPUT;
 }
 
+#endif /* USE_TOOLKIT_SCROLL_BARS */
+
+
 \f
 /************************************************************************
                         Scroll bars, general
@@ -4095,15 +4730,22 @@ 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", 1, 0, 0, 0,
-                  kControlScrollBarProc, 0L);
+  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
+#if USE_TOOLKIT_SCROLL_BARS
+                  false,
+#else
+                  width < disp_height,
+#endif
+                  0, 0, 0, kControlScrollBarProc, (long) bar);
 #else
-  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
-                  0L);
+  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);
-  SetControlReference (ch, (long) bar);
 
   XSETWINDOW (bar->window, w);
   XSETINT (bar->top, top);
@@ -4113,6 +4755,10 @@ 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 USE_TOOLKIT_SCROLL_BARS
+  bar->track_top = Qnil;
+  bar->track_height = Qnil;
+#endif
 
   /* Add bar to its frame's list of scroll bars.  */
   bar->next = FRAME_SCROLL_BARS (f);
@@ -4139,6 +4785,8 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
    the bar's top is as far down as it goes; otherwise, there's no way
    to move to the very end of the buffer.  */
 
+#ifndef USE_TOOLKIT_SCROLL_BARS
+
 static void
 x_scroll_bar_set_handle (bar, start, end, rebuild)
      struct scroll_bar *bar;
@@ -4198,6 +4846,7 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
   UNBLOCK_INPUT;
 }
 
+#endif /* !USE_TOOLKIT_SCROLL_BARS */
 
 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
    nil.  */
@@ -4210,6 +4859,9 @@ x_scroll_bar_remove (bar)
 
   BLOCK_INPUT;
 
+#if USE_CG_DRAWING
+  mac_prepare_for_quickdraw (f);
+#endif
   /* Destroy the Mac scroll bar control  */
   DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
 
@@ -4219,10 +4871,12 @@ x_scroll_bar_remove (bar)
   UNBLOCK_INPUT;
 }
 
+
 /* Set the handle of the vertical scroll bar for WINDOW to indicate
    that we are displaying PORTION characters out of a total of WHOLE
    characters, starting at POSITION.  If WINDOW has no scroll bar,
    create one.  */
+
 static void
 XTset_vertical_scroll_bar (w, portion, whole, position)
      struct window *w;
@@ -4236,11 +4890,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   /* Get window dimensions.  */
   window_box (w, -1, 0, &window_y, 0, &window_height);
   top = window_y;
-#ifdef MAC_OSX
-  width = 16;
-#else
   width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
-#endif
   height = window_height;
 
   /* Compute the left edge of the scroll bar area.  */
@@ -4255,13 +4905,14 @@ 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 + width - sb_width - (width - sb_width) / 2;
+    sb_left = left;
   else
-    sb_left = left + (width - sb_width) / 2;
+    sb_left = left + width - sb_width;
 
   /* Adjustments according to Inside Macintosh to make it look nice */
   disp_top = top;
   disp_height = height;
+#ifdef MAC_OS8
   if (disp_top == 0)
     {
       disp_top = -1;
@@ -4275,13 +4926,13 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
   if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
     sb_left++;
+#endif
 
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
     {
       BLOCK_INPUT;
-      XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 left, top, width, height, 0);
+      mac_clear_area (f, left, top, width, height);
       UNBLOCK_INPUT;
       bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
                                 disp_height);
@@ -4298,43 +4949,83 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
       BLOCK_INPUT;
 
       /* If already correctly positioned, do nothing.  */
-      if (XINT (bar->left) == sb_left
-          && XINT (bar->top) == top
-          && XINT (bar->width) == sb_width
-          && XINT (bar->height) == height)
-        Draw1Control (ch);
-      else
-        {
-         /* Clear areas not covered by the scroll bar because it's not as
-            wide as the area reserved for it .  This makes sure a
-            previous mode line display is cleared after C-x 2 C-x 1, for
-            example.  */
-         int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
-         XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                     left, top, area_width, height, 0);
+      if (!(XINT (bar->left) == sb_left
+           && XINT (bar->top) == top
+           && XINT (bar->width) == sb_width
+           && XINT (bar->height) == height))
+       {
+         /* 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);
 
-#if 0
-          if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
-            XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                       sb_left - 1, top, 1, height, 0);
+#if USE_CG_DRAWING
+         mac_prepare_for_quickdraw (f);
 #endif
-
           HideControl (ch);
           MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
           SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                       disp_height);
-          ShowControl (ch);
+#ifndef USE_TOOLKIT_SCROLL_BARS
+         if (sb_width < disp_height)
+           ShowControl (ch);
+#endif
 
           /* Remember new settings.  */
           XSETINT (bar->left, sb_left);
           XSETINT (bar->top, top);
           XSETINT (bar->width, sb_width);
           XSETINT (bar->height, height);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+         bar->track_top = Qnil;
+         bar->track_height = Qnil;
+#endif
         }
 
-      UNBLOCK_INPUT;
+      UNBLOCK_INPUT;
+    }
+
+#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;
+
+         BLOCK_INPUT;
+
+         SetControl32BitMinimum (ch, 0);
+         SetControl32BitMaximum (ch, 1);
+         SetControlViewSize (ch, 1);
+
+         /* Move the scroll bar thumb to the top.  */
+         SetControl32BitValue (ch, 0);
+         get_control_part_bounds (ch, kControlIndicatorPart, &r0);
+
+         /* Move the scroll bar thumb to the bottom.  */
+         SetControl32BitValue (ch, 1);
+         get_control_part_bounds (ch, kControlIndicatorPart, &r1);
+
+         UnionRect (&r0, &r1, &r0);
+         XSETINT (bar->track_top, r0.top);
+         XSETINT (bar->track_height, r0.bottom - r0.top);
+
+         /* Don't show the scroll bar if its height is not enough to
+            display the scroll bar thumb.  */
+         if (r0.bottom - r0.top > 0)
+           ShowControl (ch);
+
+         UNBLOCK_INPUT;
+       }
     }
 
+  x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
+#else /* not USE_TOOLKIT_SCROLL_BARS */
   /* Set the scroll bar's current state, unless we're currently being
      dragged.  */
   if (NILP (bar->dragging))
@@ -4350,6 +5041,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
          x_scroll_bar_set_handle (bar, start, end, 0);
        }
     }
+#endif /* not USE_TOOLKIT_SCROLL_BARS */
 }
 
 
@@ -4392,6 +5084,7 @@ XTredeem_scroll_bar (window)
      struct window *window;
 {
   struct scroll_bar *bar;
+  struct frame *f;
 
   /* We can't redeem this window's scroll bar if it doesn't have one.  */
   if (NILP (window->vertical_scroll_bar))
@@ -4400,36 +5093,33 @@ XTredeem_scroll_bar (window)
   bar = XSCROLL_BAR (window->vertical_scroll_bar);
 
   /* Unlink it from the condemned list.  */
-  {
-    FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
-
-    if (NILP (bar->prev))
-      {
-       /* If the prev pointer is nil, it must be the first in one of
-           the lists.  */
-       if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
-         /* It's not condemned.  Everything's fine.  */
-         return;
-       else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
-                    window->vertical_scroll_bar))
-         FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
-       else
-         /* If its prev pointer is nil, it must be at the front of
-             one or the other!  */
-         abort ();
-      }
-    else
-      XSCROLL_BAR (bar->prev)->next = bar->next;
+  f = XFRAME (WINDOW_FRAME (window));
+  if (NILP (bar->prev))
+    {
+      /* If the prev pointer is nil, it must be the first in one of
+        the lists.  */
+      if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
+       /* It's not condemned.  Everything's fine.  */
+       return;
+      else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+                  window->vertical_scroll_bar))
+       FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
+      else
+       /* If its prev pointer is nil, it must be at the front of
+          one or the other!  */
+       abort ();
+    }
+  else
+    XSCROLL_BAR (bar->prev)->next = bar->next;
 
-    if (! NILP (bar->next))
-      XSCROLL_BAR (bar->next)->prev = bar->prev;
+  if (! NILP (bar->next))
+    XSCROLL_BAR (bar->next)->prev = bar->prev;
 
-    bar->next = FRAME_SCROLL_BARS (f);
-    bar->prev = Qnil;
-    XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
-    if (! NILP (bar->next))
-      XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-  }
+  bar->next = FRAME_SCROLL_BARS (f);
+  bar->prev = Qnil;
+  XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
+  if (! NILP (bar->next))
+    XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
 }
 
 /* Remove all scroll bars on FRAME that haven't been saved since the
@@ -4462,50 +5152,6 @@ XTjudge_scroll_bars (f)
 }
 
 
-void
-activate_scroll_bars (frame)
-     FRAME_PTR frame;
-{
-  Lisp_Object bar;
-  ControlHandle ch;
-
-  bar = FRAME_SCROLL_BARS (frame);
-  while (! NILP (bar))
-    {
-      ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
-#if 1 /* TARGET_API_MAC_CARBON */
-      ActivateControl (ch);
-#else
-      SetControlMaximum (ch,
-                        VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
-                                                       XINT (XSCROLL_BAR (bar)
-                                                             ->height)) - 1);
-#endif
-      bar = XSCROLL_BAR (bar)->next;
-    }
-}
-
-
-void
-deactivate_scroll_bars (frame)
-     FRAME_PTR frame;
-{
-  Lisp_Object bar;
-  ControlHandle ch;
-
-  bar = FRAME_SCROLL_BARS (frame);
-  while (! NILP (bar))
-    {
-      ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
-#if 1 /* TARGET_API_MAC_CARBON */
-      DeactivateControl (ch);
-#else
-      SetControlMaximum (ch, -1);
-#endif
-      bar = XSCROLL_BAR (bar)->next;
-    }
-}
-
 /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind
    is set to something other than NO_EVENT, it is enqueued.
 
@@ -4515,7 +5161,7 @@ deactivate_scroll_bars (frame)
 static void
 x_scroll_bar_handle_click (bar, part_code, er, bufp)
      struct scroll_bar *bar;
-     int part_code;
+     ControlPartCode part_code;
      EventRecord *er;
      struct input_event *bufp;
 {
@@ -4575,6 +5221,7 @@ x_scroll_bar_handle_click (bar, part_code, er, bufp)
   XSETINT (bufp->y, top_range);
 }
 
+#ifndef USE_TOOLKIT_SCROLL_BARS
 
 /* Handle some mouse motion while someone is dragging the scroll bar.
 
@@ -4609,9 +5256,10 @@ x_scroll_bar_note_movement (bar, y_pos, t)
     }
 }
 
+#endif /* !USE_TOOLKIT_SCROLL_BARS */
 
-/* Return information to the user about the current position of the
-   mouse on the scroll bar.  */
+/* Return information to the user about the current position of the mouse
+   on the scroll bar.  */
 
 static void
 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
@@ -4622,7 +5270,12 @@ 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);
-  WindowPtr wp = front_emacs_window ();
+  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+#if TARGET_API_MAC_CARBON
+  WindowPtr wp = GetControlOwner (ch);
+#else
+  WindowPtr wp = (*ch)->contrlOwner;
+#endif
   Point mouse_pos;
   struct frame *f = mac_window_to_frame (wp);
   int win_y, top_range;
@@ -4666,6 +5319,21 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
 
   *time = last_mouse_movement_time;
 }
+
+
+/* The screen has been cleared so we may have changed foreground or
+   background colors, and the scroll bars may need to be redrawn.
+   Clear out the scroll bars, and ask for expose events, so we can
+   redraw them.  */
+
+void
+x_scroll_bar_clear (f)
+     FRAME_PTR f;
+{
+  XTcondemn_scroll_bars (f);
+  XTjudge_scroll_bars (f);
+}
+
 \f
 /***********************************************************************
                             Text Cursor
@@ -4697,7 +5365,7 @@ x_clip_to_row (w, row, area, gc)
   clip_rect.right = clip_rect.left + window_width;
   clip_rect.bottom = clip_rect.top + row->visible_height;
 
-  mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
+  mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
 }
 
 
@@ -4722,29 +5390,10 @@ x_draw_hollow_cursor (w, row)
   if (cursor_glyph == NULL)
     return;
 
-  /* Compute the width of the rectangle to draw.  If on a stretch
-     glyph, and `x-stretch-block-cursor' is nil, don't draw a
-     rectangle as wide as the glyph, but use a canonical character
-     width instead.  */
-  wd = cursor_glyph->pixel_width - 1;
-  if (cursor_glyph->type == STRETCH_GLYPH
-      && !x_stretch_cursor_p)
-    wd = min (FRAME_COLUMN_WIDTH (f), wd);
-  w->phys_cursor_width = wd;
-
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
+  /* Compute frame-relative coordinates for phys cursor.  */
   x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
-
-  /* Compute the proper height and ascent of the rectangle, based
-     on the actual glyph.  Using the full height of the row looks
-     bad when there are tall images on that row.  */
-  h = max (min (FRAME_LINE_HEIGHT (f), row->height),
-          cursor_glyph->ascent + cursor_glyph->descent);
-  if (h < row->height)
-    y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
-  h--;
+  y = get_phys_cursor_geometry (w, row, cursor_glyph, &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.  */
@@ -4758,8 +5407,8 @@ x_draw_hollow_cursor (w, row)
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
   x_clip_to_row (w, row, TEXT_AREA, gc);
-  mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
-  mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
+  mac_draw_rectangle (f, gc, x, y, wd, h - 1);
+  mac_reset_clip_rectangles (dpy, gc);
 }
 
 
@@ -4831,19 +5480,19 @@ x_draw_bar_cursor (w, row, width, kind)
       x_clip_to_row (w, row, TEXT_AREA, gc);
 
       if (kind == BAR_CURSOR)
-       XFillRectangle (dpy, window, gc,
-                       WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
-                       WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                       width, row->height);
+       mac_fill_rectangle (f, gc,
+                           WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                           WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                           width, row->height);
       else
-       XFillRectangle (dpy, window, gc,
-                       WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
-                       WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
-                                                row->height - width),
-                       cursor_glyph->pixel_width,
-                       width);
+       mac_fill_rectangle (f, gc,
+                           WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                           WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+                                                    row->height - width),
+                           cursor_glyph->pixel_width,
+                           width);
 
-      mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
+      mac_reset_clip_rectangles (dpy, gc);
     }
 }
 
@@ -4855,11 +5504,10 @@ mac_define_frame_cursor (f, cursor)
      struct frame *f;
      Cursor cursor;
 {
-#if TARGET_API_MAC_CARBON
-  SetThemeCursor (cursor);
-#else
-  SetCursor (*cursor);
-#endif
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  if (dpyinfo->x_focus_frame == f)
+    SetThemeCursor (cursor);
 }
 
 
@@ -4870,8 +5518,7 @@ mac_clear_frame_area (f, x, y, width, height)
      struct frame *f;
      int x, y, width, height;
 {
-  XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-             x, y, width, height, 0);
+  mac_clear_area (f, x, y, width, height);
 }
 
 
@@ -5091,7 +5738,7 @@ x_new_fontset (f, fontsetname)
     return Qnil;
 
   /* Since x_new_font doesn't update any fontset information, do it now.  */
-  FRAME_FONTSET(f) = fontset;
+  FRAME_FONTSET (f) = fontset;
 
   return build_string (fontsetname);
 }
@@ -5132,6 +5779,7 @@ mac_get_window_bounds (f, inner, outer)
 }
 
 
+\f
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
 
@@ -5284,6 +5932,16 @@ 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)
+    {
+#if USE_CG_DRAWING
+      mac_prepare_for_quickdraw (f);
+#endif
+      MoveControl (f->output_data.mac->hourglass_control,
+                  pixelwidth - HOURGLASS_WIDTH, 0);
+    }
+#endif
 
   /* Now, strictly speaking, we can't be sure that this is accurate,
      but the window manager will get around to dealing with the size
@@ -5358,7 +6016,6 @@ x_set_mouse_pixel_position (f, pix_x, pix_y)
   UNBLOCK_INPUT;
 #endif
 }
-
 \f
 /* focus shifting, raising and lowering.  */
 
@@ -5385,6 +6042,7 @@ x_unfocus_frame (f)
 }
 
 /* Raise frame F.  */
+
 void
 x_raise_frame (f)
      struct frame *f;
@@ -5392,12 +6050,13 @@ x_raise_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-      SelectWindow (FRAME_MAC_WINDOW (f));
+      BringToFront (FRAME_MAC_WINDOW (f));
       UNBLOCK_INPUT;
     }
 }
 
 /* Lower frame F.  */
+
 void
 x_lower_frame (f)
      struct frame *f;
@@ -5405,7 +6064,7 @@ x_lower_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-      SendBehind (FRAME_MAC_WINDOW (f), nil);
+      SendBehind (FRAME_MAC_WINDOW (f), NULL);
       UNBLOCK_INPUT;
     }
 }
@@ -5423,6 +6082,55 @@ XTframe_raise_lower (f, raise_flag)
 \f
 /* Change of visibility.  */
 
+static void
+mac_handle_visibility_change (f)
+     struct frame *f;
+{
+  WindowPtr 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 (!f->async_visible && visible)
+    {
+      if (f->iconified)
+       {
+         /* wait_reading_process_output will notice this and update
+            the frame's display structures.  If we were made
+            invisible, we should not set garbaged, because that stops
+            redrawing on Update events.  */
+         SET_FRAME_GARBAGED (f);
+
+         EVENT_INIT (buf);
+         buf.kind = DEICONIFY_EVENT;
+         XSETFRAME (buf.frame_or_window, f);
+         kbd_buffer_store_event (&buf);
+       }
+      else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
+       /* Force a redisplay sooner or later to update the
+          frame titles in case this is the second frame.  */
+       record_asynch_buffer_change ();
+    }
+  else if (f->async_visible && !visible)
+    if (iconified)
+      {
+       EVENT_INIT (buf);
+       buf.kind = ICONIFY_EVENT;
+       XSETFRAME (buf.frame_or_window, f);
+       kbd_buffer_store_event (&buf);
+      }
+
+  f->async_visible = visible;
+  f->async_iconified = iconified;
+}
+
 /* This tries to wait until the frame is really visible.
    However, if the window manager asks the user where to position
    the frame, this will return before the user finishes doing that.
@@ -5434,9 +6142,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))
@@ -5447,29 +6152,33 @@ x_make_frame_visible (f)
         before the window gets really visible.  */
       if (! FRAME_ICONIFIED_P (f)
          && ! f->output_data.mac->asked_for_visible)
-       x_set_offset (f, f->left_pos, f->top_pos, 0);
-
-      f->output_data.mac->asked_for_visible = 1;
-
-#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),
-#ifdef MAC_OS_X_VERSION_10_2
-                             kWindowCascadeStartAtParentWindowScreen
+#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
+                                 kWindowCascadeOnParentWindowScreen
 #endif
-                             );
-         x_real_positions (f, &f->left_pos, &f->top_pos);
-       }
+                                 );
+             x_real_positions (f, &f->left_pos, &f->top_pos);
+           }
+         else
 #endif
+           x_set_offset (f, f->left_pos, f->top_pos, 0);
+       }
+
+      f->output_data.mac->asked_for_visible = 1;
+
+      CollapseWindow (FRAME_MAC_WINDOW (f), false);
       ShowWindow (FRAME_MAC_WINDOW (f));
     }
 
@@ -5528,25 +6237,31 @@ void
 x_make_frame_invisible (f)
      struct frame *f;
 {
+  /* A deactivate event does not occur when the last visible frame is
+     made invisible.  So if we clear the highlight here, it will not
+     be rehighlighted when it is made visible.  */
+#if 0
   /* Don't keep the highlight on an invisible frame.  */
   if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
     FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
+#endif
 
   BLOCK_INPUT;
 
-  HideWindow (FRAME_MAC_WINDOW (f));
+  /* 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);
 
-  /* We can't distinguish this from iconification
-     just by the event that we get from the server.
-     So we can't win using the usual strategy of letting
-     FRAME_SAMPLE_VISIBILITY set this.  So do it by hand,
-     and synchronize with the server to make sure we agree.  */
-  f->visible = 0;
-  FRAME_ICONIFIED_P (f) = 0;
-  f->async_visible = 0;
-  f->async_iconified = 0;
+  HideWindow (FRAME_MAC_WINDOW (f));
 
   UNBLOCK_INPUT;
+
+#if !USE_CARBON_EVENTS
+  mac_handle_visibility_change (f);
+#endif
 }
 
 /* Change window state from mapped to iconified.  */
@@ -5555,21 +6270,37 @@ void
 x_iconify_frame (f)
      struct frame *f;
 {
+  OSErr 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
+     rehighlighted when it is deiconified.  */
+#if 0
   /* Don't keep the highlight on an invisible frame.  */
   if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
     FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
+#endif
 
-#if 0
-  /* Review:  Since window is still visible in dock, still allow updates? */
   if (f->async_iconified)
     return;
-#endif
 
   BLOCK_INPUT;
 
-  CollapseWindow (FRAME_MAC_WINDOW (f), true);
+  FRAME_SAMPLE_VISIBILITY (f);
+
+  if (! FRAME_VISIBLE_P (f))
+    ShowWindow (FRAME_MAC_WINDOW (f));
+
+  err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
 
   UNBLOCK_INPUT;
+
+  if (err != noErr)
+    error ("Can't notify window manager of iconification");
+
+#if !USE_CARBON_EVENTS
+  mac_handle_visibility_change (f);
+#endif
 }
 
 \f
@@ -5584,6 +6315,9 @@ x_free_frame_resources (f)
 
   BLOCK_INPUT;
 
+  if (wp != tip_window)
+    remove_window_handler (wp);
+
   DisposeWindow (wp);
   if (wp == tip_window)
     /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
@@ -5600,6 +6334,11 @@ x_free_frame_resources (f)
   if (FRAME_SIZE_HINTS (f))
     xfree (FRAME_SIZE_HINTS (f));
 
+#if TARGET_API_MAC_CARBON
+  if (FRAME_FILE_NAME (f))
+    xfree (FRAME_FILE_NAME (f));
+#endif
+
   xfree (f->output_data.mac);
   f->output_data.mac = NULL;
 
@@ -5780,6 +6519,326 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 #endif /* MAC_TODO */
 }
 
+\f
+/***********************************************************************
+                         XLFD Pattern Match
+ ***********************************************************************/
+
+/* An XLFD pattern is divided into blocks delimited by '*'.  This
+   structure holds information for each block.  */
+struct xlfdpat_block
+{
+  /* Length of the pattern string in this block.  Non-zero except for
+     the first and the last blocks.  */
+  int len;
+
+  /* Pattern string except the last character in this block.  The last
+     character is replaced with NUL in order to use it as a
+     sentinel.  */
+  unsigned char *pattern;
+
+  /* Last character of the pattern string.  Must not be '?'.  */
+  unsigned char last_char;
+
+  /* One of the tables for the Boyer-Moore string search.  It
+     specifies the number of positions to proceed for each character
+     with which the match fails.  */
+  int skip[256];
+
+  /* The skip value for the last character in the above `skip' is
+     assigned to `infinity' in order to simplify a loop condition.
+     The original value is saved here.  */
+  int last_char_skip;
+};
+
+struct xlfdpat
+{
+  /* Normalized pattern string.  "Normalized" means that capital
+     letters are lowered, blocks are not empty except the first and
+     the last ones, and trailing '?'s in a block that is not the last
+     one are moved to the next one.  The last character in each block
+     is replaced with NUL.  */
+  unsigned char *buf;
+
+  /* Number of characters except '*'s and trailing '?'s in the
+     normalized pattern string.  */
+  int nchars;
+
+  /* Number of trailing '?'s in the normalized pattern string.  */
+  int trailing_anychars;
+
+  /* Number of blocks and information for each block.  The latter is
+     NULL if the pattern is exact (no '*' or '?' in it).  */
+  int nblocks;
+  struct xlfdpat_block *blocks;
+};
+
+static void
+xlfdpat_destroy (pat)
+     struct xlfdpat *pat;
+{
+  if (pat)
+    {
+      if (pat->buf)
+       {
+         if (pat->blocks)
+           xfree (pat->blocks);
+         xfree (pat->buf);
+       }
+      xfree (pat);
+    }
+}
+
+static struct xlfdpat *
+xlfdpat_create (pattern)
+     char *pattern;
+{
+  struct xlfdpat *pat;
+  int nblocks, i, skip;
+  unsigned char last_char, *p, *q, *anychar_head;
+  struct xlfdpat_block *blk;
+
+  pat = xmalloc (sizeof (struct xlfdpat));
+  pat->buf = xmalloc (strlen (pattern) + 1);
+
+  /* Normalize the pattern string and store it to `pat->buf'.  */
+  nblocks = 0;
+  anychar_head = NULL;
+  q = pat->buf;
+  last_char = '\0';
+  for (p = pattern; *p; p++)
+    {
+      unsigned char c = *p;
+
+      if (c == '*')
+       if (last_char == '*')
+         /*  ...a** -> ...a*  */
+         continue;
+       else
+         {
+           if (last_char == '?')
+             {
+               if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
+                 /*  ...*??* -> ...*??  */
+                 continue;
+               else
+                 /*  ...a??* -> ...a*??  */
+                 {
+                   *anychar_head++ = '*';
+                   c = '?';
+                 }
+             }
+           nblocks++;
+         }
+      else if (c == '?')
+       {
+         if (last_char != '?')
+           anychar_head = q;
+       }
+      else
+       /* On Mac OS X 10.3, tolower also converts non-ASCII
+          characters for some locales.  */
+       if (isascii (c))
+         c = tolower (c);
+
+      *q++ = last_char = c;
+    }
+  *q = '\0';
+  nblocks++;
+  pat->nblocks = nblocks;
+  if (last_char != '?')
+    pat->trailing_anychars = 0;
+  else
+    {
+      pat->trailing_anychars = q - anychar_head;
+      q = anychar_head;
+    }
+  pat->nchars = q - pat->buf - (nblocks - 1);
+
+  if (anychar_head == NULL && nblocks == 1)
+    {
+      /* The pattern is exact.  */
+      pat->blocks = NULL;
+      return pat;
+    }
+
+  pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
+
+  /* Divide the normalized pattern into blocks.  */
+  p = pat->buf;
+  for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
+    {
+      blk->pattern = p;
+      while (*p != '*')
+       p++;
+      blk->len = p - blk->pattern;
+      p++;
+    }
+  blk->pattern = p;
+  blk->len = q - blk->pattern;
+
+  /* Setup a table for the Boyer-Moore string search.  */
+  for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
+    if (blk->len != 0)
+      {
+       blk->last_char = blk->pattern[blk->len - 1];
+       blk->pattern[blk->len - 1] = '\0';
+
+       for (skip = 1; skip < blk->len; skip++)
+         if (blk->pattern[blk->len - skip - 1] == '?')
+           break;
+
+       for (i = 0; i < 256; i++)
+         blk->skip[i] = skip;
+
+       p = blk->pattern + (blk->len - skip);
+       while (--skip > 0)
+         blk->skip[*p++] = skip;
+
+       blk->last_char_skip = blk->skip[blk->last_char];
+      }
+
+  return pat;
+}
+
+static INLINE int
+xlfdpat_exact_p (pat)
+     struct xlfdpat *pat;
+{
+  return pat->blocks == NULL;
+}
+
+/* Return the first string in STRING + 0, ..., STRING + START_MAX such
+   that the pattern in *BLK matches with its prefix.  Return NULL
+   there is no such strings.  STRING must be lowered in advance.  */
+
+static char *
+xlfdpat_block_match_1 (blk, string, start_max)
+     struct xlfdpat_block *blk;
+     unsigned char *string;
+     int start_max;
+{
+  int start, infinity;
+  unsigned char *p, *s;
+
+  xassert (blk->len > 0);
+  xassert (start_max + blk->len <= strlen (string));
+  xassert (blk->last_char != '?');
+
+  /* See the comments in the function `boyer_moore' (search.c) for the
+     use of `infinity'.  */
+  infinity = start_max + blk->len + 1;
+  blk->skip[blk->last_char] = infinity;
+
+  start = 0;
+  do
+    {
+      /* Check the last character of the pattern. */
+      s = string + blk->len - 1;
+      do
+       {
+         start += blk->skip[*(s + start)];
+       }
+      while (start <= start_max);
+
+      if (start < infinity)
+       /* Couldn't find the last character.  */
+       return NULL;
+
+      /* No less than `infinity' means we could find the last
+        character at `s[start - infinity]'.  */
+      start -= infinity;
+
+      /* Check the remaining characters.  We prefer making no-'?'
+        cases faster because the use of '?' is really rare.  */
+      p = blk->pattern;
+      s = string + start;
+      do
+       {
+         while (*p++ == *s++)
+           ;
+       }
+      while (*(p - 1) == '?');
+
+      if (*(p - 1) == '\0')
+       /* Matched.  */
+       return string + start;
+
+      /* Didn't match.  */
+      start += blk->last_char_skip;
+    }
+  while (start <= start_max);
+
+  return NULL;
+}
+
+#define xlfdpat_block_match(b, s, m) \
+  ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
+   : xlfdpat_block_match_1 (b, s, m))
+
+/* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
+   matches with STRING.  STRING must be lowered in advance.  */
+
+static int
+xlfdpat_match (pat, string)
+     struct xlfdpat *pat;
+     unsigned char *string;
+{
+  int str_len, nblocks, i, start_max;
+  struct xlfdpat_block *blk;
+  unsigned char *s;
+
+  xassert (pat->nblocks > 0);
+
+  if (xlfdpat_exact_p (pat))
+    return strcmp (pat->buf, string) == 0;
+
+  /* The number of the characters in the string must not be smaller
+     than that in the pattern.  */
+  str_len = strlen (string);
+  if (str_len < pat->nchars + pat->trailing_anychars)
+    return 0;
+
+  /* Chop off the trailing '?'s.  */
+  str_len -= pat->trailing_anychars;
+
+  /* The last block.  When it is non-empty, it must match at the end
+     of the string.  */
+  nblocks = pat->nblocks;
+  blk = pat->blocks + (nblocks - 1);
+  if (nblocks == 1)
+    /* The last block is also the first one.  */
+    return (str_len == blk->len
+           && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
+  else if (blk->len != 0)
+    if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
+      return 0;
+
+  /* The first block.  When it is non-empty, it must match at the
+     beginning of the string.  */
+  blk = pat->blocks;
+  if (blk->len != 0)
+    {
+      s = xlfdpat_block_match (blk, string, 0);
+      if (s == NULL)
+       return 0;
+      string = s + blk->len;
+    }
+
+  /* The rest of the blocks.  */
+  start_max = str_len - pat->nchars;
+  for (i = 1, blk++; i < nblocks - 1; i++, blk++)
+    {
+      s = xlfdpat_block_match (blk, string, start_max);
+      if (s == NULL)
+       return 0;
+      start_max -= s - string;
+      string = s + blk->len;
+    }
+
+  return 1;
+}
+
 \f
 /***********************************************************************
                                Fonts
@@ -5796,259 +6855,209 @@ x_get_font_info (f, font_idx)
 }
 
 /* the global font name table */
-char **font_name_table = NULL;
-int font_name_table_size = 0;
-int font_name_count = 0;
-
-#if 0
-/* compare two strings ignoring case */
-static int
-stricmp (const char *s, const char *t)
-{
-  for ( ; tolower (*s) == tolower (*t); s++, t++)
-    if (*s == '\0')
-      return 0;
-  return tolower (*s) - tolower (*t);
-}
-
-/* compare two strings ignoring case and handling wildcard */
-static int
-wildstrieq (char *s1, char *s2)
-{
-  if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
-    return true;
+static char **font_name_table = NULL;
+static int font_name_table_size = 0;
+static int font_name_count = 0;
+
+/* Alist linking font family names to Font Manager font family
+   references (which can also be used as QuickDraw font IDs).  We use
+   an alist because hash tables are not ready when the terminal frame
+   for Mac OS Classic is created.  */
+static Lisp_Object fm_font_family_alist;
+#if USE_ATSUI
+/* Hash table linking font family names to ATSU font IDs.  */
+static Lisp_Object atsu_font_id_hash;
+#endif
 
-  return stricmp (s1, s2) == 0;
-}
+/* Alist linking character set strings to Mac text encoding and Emacs
+   coding system. */
+static Lisp_Object Vmac_charset_info_alist;
 
-/* Assume parameter 1 is fully qualified, no wildcards. */
-static int
-mac_font_pattern_match (fontname, pattern)
-    char * fontname;
-    char * pattern;
+static Lisp_Object
+create_text_encoding_info_alist ()
 {
-  char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
-  char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
-  char *ptr;
+  Lisp_Object result = Qnil, rest;
 
-  /* Copy fontname so we can modify it during comparison.  */
-  strcpy (font_name_copy, fontname);
+  for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
+    {
+      Lisp_Object charset_info = XCAR (rest);
+      Lisp_Object charset, coding_system, text_encoding;
+      Lisp_Object existing_info;
 
-  ptr = regex;
-  *ptr++ = '^';
+      if (!(CONSP (charset_info)
+           && STRINGP (charset = XCAR (charset_info))
+           && CONSP (XCDR (charset_info))
+           && INTEGERP (text_encoding = XCAR (XCDR (charset_info)))
+           && CONSP (XCDR (XCDR (charset_info)))
+           && SYMBOLP (coding_system = XCAR (XCDR (XCDR (charset_info))))))
+       continue;
 
-  /* Turn pattern into a regexp and do a regexp match.  */
-  for (; *pattern; pattern++)
-    {
-      if (*pattern == '?')
-        *ptr++ = '.';
-      else if (*pattern == '*')
-        {
-          *ptr++ = '.';
-          *ptr++ = '*';
-        }
+      existing_info = assq_no_quit (text_encoding, result);
+      if (NILP (existing_info))
+       result = Fcons (list3 (text_encoding, coding_system, charset),
+                       result);
       else
-        *ptr++ = *pattern;
+       if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
+         XSETCDR (XCDR (existing_info),
+                  Fcons (charset, XCDR (XCDR (existing_info))));
     }
-  *ptr = '$';
-  *(ptr + 1) = '\0';
-
-  return (fast_c_string_match_ignore_case (build_string (regex),
-                                           font_name_copy) >= 0);
-}
 
-/* Two font specs are considered to match if their foundry, family,
-   weight, slant, and charset match.  */
-static int
-mac_font_match (char *mf, char *xf)
-{
-  char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
-  char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
-
-  if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
-              m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
-    return mac_font_pattern_match (mf, xf);
-
-  if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
-              x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
-    return mac_font_pattern_match (mf, xf);
-
-  return (wildstrieq (m_foundry, x_foundry)
-          && wildstrieq (m_family, x_family)
-          && wildstrieq (m_weight, x_weight)
-          && wildstrieq (m_slant, x_slant)
-          && wildstrieq (m_charset, x_charset))
-         || mac_font_pattern_match (mf, xf);
+  return result;
 }
-#endif
 
-static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
 
 static void
-decode_mac_font_name (name, size, scriptcode)
+decode_mac_font_name (name, size, coding_system)
      char *name;
      int size;
-#if TARGET_API_MAC_CARBON
-     int scriptcode;
-#else
-     short scriptcode;
-#endif
+     Lisp_Object coding_system;
 {
-  Lisp_Object coding_system;
   struct coding_system coding;
-  char *buf;
+  char *buf, *p;
 
-  switch (scriptcode)
+  if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
     {
-    case smTradChinese:
-      coding_system = Qbig5;
-      break;
-    case smSimpChinese:
-      coding_system = Qcn_gb;
-      break;
-    case smJapanese:
-      coding_system = Qsjis;
-      break;
-    case smKorean:
-      coding_system = Qeuc_kr;
-      break;
-    default:
-      return;
+      for (p = name; *p; p++)
+       if (!isascii (*p) || iscntrl (*p))
+         break;
+
+      if (*p)
+       {
+         setup_coding_system (coding_system, &coding);
+         coding.src_multibyte = 0;
+         coding.dst_multibyte = 1;
+         coding.mode |= CODING_MODE_LAST_BLOCK;
+         coding.composing = COMPOSITION_DISABLED;
+         buf = (char *) alloca (size);
+
+         decode_coding (&coding, name, buf, strlen (name), size - 1);
+         bcopy (buf, name, coding.produced);
+         name[coding.produced] = '\0';
+       }
     }
 
-  setup_coding_system (coding_system, &coding);
-  coding.src_multibyte = 0;
-  coding.dst_multibyte = 1;
-  coding.mode |= CODING_MODE_LAST_BLOCK;
-  coding.composing = COMPOSITION_DISABLED;
-  buf = (char *) alloca (size);
+  /* If there's just one occurrence of '-' in the family name, it is
+     replaced with '_'.  (More than one occurrence of '-' means a
+     "FOUNDRY-FAMILY-CHARSET"-style name.)  */
+  p = strchr (name, '-');
+  if (p && strchr (p + 1, '-') == NULL)
+    *p = '_';
 
-  decode_coding (&coding, name, buf, strlen (name), size - 1);
-  bcopy (buf, name, coding.produced);
-  name[coding.produced] = '\0';
+  for (p = name; *p; p++)
+    /* On Mac OS X 10.3, tolower also converts non-ASCII characters
+       for some locales.  */
+    if (isascii (*p))
+      *p = tolower (*p);
 }
 
 
 static char *
-mac_to_x_fontname (name, size, style, scriptcode)
+mac_to_x_fontname (name, size, style, charset)
      char *name;
      int size;
      Style style;
-#if TARGET_API_MAC_CARBON
-     int scriptcode;
-#else
-     short scriptcode;
-#endif
+     char *charset;
 {
-  char foundry[32], family[32], cs[32];
-  char xf[256], *result, *p;
+  Str31 foundry, cs;
+  Str255 family;
+  char xf[256], *result;
+  unsigned char *p;
 
-  if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
+  if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
+    charset = cs;
+  else
     {
       strcpy(foundry, "Apple");
       strcpy(family, name);
-
-      switch (scriptcode)
-      {
-      case smTradChinese:      /* == kTextEncodingMacChineseTrad */
-        strcpy(cs, "big5-0");
-        break;
-      case smSimpChinese:      /* == kTextEncodingMacChineseSimp */
-        strcpy(cs, "gb2312.1980-0");
-        break;
-      case smJapanese:         /* == kTextEncodingMacJapanese */
-        strcpy(cs, "jisx0208.1983-sjis");
-        break;
-      case -smJapanese:
-       /* Each Apple Japanese font is entered into the font table
-          twice: once as a jisx0208.1983-sjis font and once as a
-          jisx0201.1976-0 font.  The latter can be used to display
-          the ascii charset and katakana-jisx0201 charset.  A
-          negative script code signals that the name of this latter
-          font is being built.  */
-       strcpy(cs, "jisx0201.1976-0");
-       break;
-      case smKorean:           /* == kTextEncodingMacKorean */
-        strcpy(cs, "ksc5601.1989-0");
-        break;
-#if TARGET_API_MAC_CARBON
-      case kTextEncodingMacCyrillic:
-       strcpy(cs, "mac-cyrillic");
-       break;
-      case kTextEncodingMacCentralEurRoman:
-       strcpy(cs, "mac-centraleurroman");
-       break;
-      case kTextEncodingMacSymbol:
-      case kTextEncodingMacDingbats:
-       strcpy(cs, "adobe-fontspecific");
-       break;
-#endif
-      default:
-       strcpy(cs, "mac-roman");
-       break;
-      }
     }
 
-  sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
-          foundry, family, style & bold ? "bold" : "medium",
-         style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
+  sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
+          style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
+          size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
 
-  result = (char *) xmalloc (strlen (xf) + 1);
-  strcpy (result, xf);
+  result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
+  sprintf (result, "-%s-%s-%s", foundry, family, xf);
   for (p = result; *p; p++)
-    *p = tolower(*p);
+    /* On Mac OS X 10.3, tolower also converts non-ASCII characters
+       for some locales.  */
+    if (isascii (*p))
+      *p = tolower (*p);
   return result;
 }
 
 
-/* Convert an X font spec to the corresponding mac font name, which
-   can then be passed to GetFNum after conversion to a Pascal string.
-   For ordinary Mac fonts, this should just be their names, like
-   "monaco", "Taipei", etc.  Fonts converted from the GNU intlfonts
-   collection contain their charset designation in their names, like
-   "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc.  Both types of font
-   names are handled accordingly.  */
-static void
-x_font_name_to_mac_font_name (char *xf, char *mf)
-{
-  char foundry[32], family[32], weight[20], slant[2], cs[32];
-  Lisp_Object coding_system = Qnil;
-  struct coding_system coding;
+/* Parse fully-specified and instantiated X11 font spec XF, and store
+   the results to FAMILY, *SIZE, *STYLE, and CHARSET.  Return 1 if the
+   parsing succeeded, and 0 otherwise.  For FAMILY and CHARSET, the
+   caller must allocate at least 256 and 32 bytes respectively.  For
+   ordinary Mac fonts, the value stored to FAMILY should just be their
+   names, like "monaco", "Taipei", etc.  Fonts converted from the GNU
+   intlfonts collection contain their charset designation in their
+   names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc.  Both
+   types of font names are handled accordingly.  */
 
-  strcpy (mf, "");
+const int kDefaultFontSize = 12;
 
-  if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
-              foundry, family, weight, slant, cs) != 5 &&
-      sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
-              foundry, family, weight, slant, cs) != 5)
-    return;
+static int
+parse_x_font_name (xf, family, size, style, charset)
+     char *xf, *family;
+     int *size;
+     Style *style;
+     char *charset;
+{
+  Str31 foundry, weight;
+  int point_size, avgwidth;
+  char slant[2], *p;
+
+  if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
+              foundry, family, weight, slant, size,
+             &point_size, &avgwidth, charset) != 8
+      && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
+                foundry, family, weight, slant, size,
+                &point_size, &avgwidth, charset) != 8)
+    return 0;
 
-  if (strcmp (cs, "big5-0") == 0)
-    coding_system = Qbig5;
-  else if (strcmp (cs, "gb2312.1980-0") == 0)
-    coding_system = Qcn_gb;
-  else if (strcmp (cs, "jisx0208.1983-sjis") == 0
-          || strcmp (cs, "jisx0201.1976-0") == 0)
-    coding_system = Qsjis;
-  else if (strcmp (cs, "ksc5601.1989-0") == 0)
-    coding_system = Qeuc_kr;
-  else if (strcmp (cs, "mac-roman") == 0
-          || strcmp (cs, "mac-cyrillic") == 0
-          || strcmp (cs, "mac-centraleurroman") == 0
-          || strcmp (cs, "adobe-fontspecific") == 0)
-    strcpy (mf, family);
-  else
-    sprintf (mf, "%s-%s-%s", foundry, family, cs);
+  if (*size == 0)
+    {
+      if (point_size > 0)
+       *size = point_size / 10;
+      else if (avgwidth > 0)
+       *size = avgwidth / 10;
+    }
+  if (*size == 0)
+    *size = kDefaultFontSize;
+
+  *style = normal;
+  if (strcmp (weight, "bold") == 0)
+    *style |= bold;
+  if (*slant == 'i')
+    *style |= italic;
 
-  if (!NILP (coding_system))
+  if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
     {
-      setup_coding_system (coding_system, &coding);
-      coding.src_multibyte = 1;
-      coding.dst_multibyte = 1;
-      coding.mode |= CODING_MODE_LAST_BLOCK;
-      encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
-      mf[coding.produced] = '\0';
+      int foundry_len = strlen (foundry), family_len = strlen (family);
+
+      if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
+       {
+         /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
+            but take overlap into account.  */
+         memmove (family + foundry_len + 1, family, family_len);
+         memcpy (family, foundry, foundry_len);
+         family[foundry_len] = '-';
+         family[foundry_len + 1 + family_len] = '-';
+         strcpy (family + foundry_len + 1 + family_len + 1, charset);
+       }
+      else
+       return 0;
     }
+
+  for (p = family; *p; p++)
+    /* On Mac OS X 10.3, tolower also converts non-ASCII characters
+       for some locales.  */
+    if (isascii (*p))
+      *p = tolower (*p);
+
+  return 1;
 }
 
 
@@ -6057,13 +7066,13 @@ add_font_name_table_entry (char *font_name)
 {
   if (font_name_table_size == 0)
     {
-      font_name_table_size = 16;
+      font_name_table_size = 256;
       font_name_table = (char **)
        xmalloc (font_name_table_size * sizeof (char *));
     }
   else if (font_name_count + 1 >= font_name_table_size)
     {
-      font_name_table_size += 16;
+      font_name_table_size *= 2;
       font_name_table = (char **)
        xrealloc (font_name_table,
                  font_name_table_size * sizeof (char *));
@@ -6072,6 +7081,25 @@ add_font_name_table_entry (char *font_name)
   font_name_table[font_name_count++] = font_name;
 }
 
+static void
+add_mac_font_name (name, size, style, charset)
+     char *name;
+     int size;
+     Style style;
+     char *charset;
+{
+  if (size > 0)
+    add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
+  else
+    {
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
+      add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
+                                                   charset));
+    }
+}
+
 /* Sets up the table font_name_table to contain the list of all fonts
    in the system the first time the table is used so that the Resource
    Manager need not be accessed every time this information is
@@ -6081,181 +7109,226 @@ static void
 init_font_name_table ()
 {
 #if TARGET_API_MAC_CARBON
-  SInt32 sv;
+  FMFontFamilyIterator ffi;
+  FMFontFamilyInstanceIterator ffii;
+  FMFontFamily ff;
+  Lisp_Object text_encoding_info_alist;
+  struct gcpro gcpro1;
 
-  if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
-    {
-      FMFontFamilyIterator ffi;
-      FMFontFamilyInstanceIterator ffii;
-      FMFontFamily ff;
+  text_encoding_info_alist = create_text_encoding_info_alist ();
 
-      /* Create a dummy instance iterator here to avoid creating and
-        destroying it in the loop.  */
-      if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
-       return;
-      /* Create an iterator to enumerate the font families.  */
-      if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
-         != noErr)
+#if USE_ATSUI
+#if USE_CG_TEXT_DRAWING
+  init_cg_text_anti_aliasing_threshold ();
+#endif
+  if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
+                          text_encoding_info_alist)))
+    {
+      OSErr err;
+      struct Lisp_Hash_Table *h;
+      unsigned hash_code;
+      ItemCount nfonts, i;
+      ATSUFontID *font_ids = NULL;
+      Ptr name;
+      ByteCount name_len;
+      Lisp_Object family;
+
+      atsu_font_id_hash =
+       make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
+                        make_float (DEFAULT_REHASH_SIZE),
+                        make_float (DEFAULT_REHASH_THRESHOLD),
+                        Qnil, Qnil, Qnil);;
+      h = XHASH_TABLE (atsu_font_id_hash);
+
+      err = ATSUFontCount (&nfonts);
+      if (err == noErr)
        {
-         FMDisposeFontFamilyInstanceIterator (&ffii);
-         return;
+         font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
+         err = ATSUGetFontIDs (font_ids, nfonts, NULL);
        }
+      if (err == noErr)
+       for (i = 0; i < nfonts; i++)
+         {
+           err = ATSUFindFontName (font_ids[i], kFontFamilyName,
+                                   kFontMacintoshPlatform, kFontNoScript,
+                                   kFontNoLanguage, 0, NULL, &name_len, NULL);
+           if (err != noErr)
+             continue;
+           name = xmalloc (name_len + 1);
+           name[name_len] = '\0';
+           err = ATSUFindFontName (font_ids[i], kFontFamilyName,
+                                   kFontMacintoshPlatform, kFontNoScript,
+                                   kFontNoLanguage, name_len, name,
+                                   NULL, NULL);
+           if (err == noErr)
+             {
+               decode_mac_font_name (name, name_len + 1, Qnil);
+               family = make_unibyte_string (name, name_len);
+               if (*name != '.'
+                   && hash_lookup (h, family, &hash_code) < 0)
+                 {
+                   add_mac_font_name (name, 0, normal, "iso10646-1");
+                   hash_put (h, family, long_to_cons (font_ids[i]),
+                             hash_code);
+                 }
+             }
+           xfree (name);
+         }
+      if (font_ids)
+       xfree (font_ids);
+    }
+#endif
+
+  /* Create a dummy instance iterator here to avoid creating and
+     destroying it in the loop.  */
+  if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
+    return;
+  /* Create an iterator to enumerate the font families.  */
+  if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
+      != noErr)
+    {
+      FMDisposeFontFamilyInstanceIterator (&ffii);
+      return;
+    }
 
-      while (FMGetNextFontFamily (&ffi, &ff) == noErr)
+  GCPRO1 (text_encoding_info_alist);
+
+  while (FMGetNextFontFamily (&ffi, &ff) == noErr)
+    {
+      Str255 name;
+      FMFont font;
+      FMFontStyle style;
+      FMFontSize size;
+      TextEncoding encoding;
+      TextEncodingBase sc;
+      Lisp_Object text_encoding_info, family;
+
+      if (FMGetFontFamilyName (ff, name) != noErr)
+       continue;
+      p2cstr (name);
+      if (*name == '.')
+       continue;
+
+      if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
+       continue;
+      sc = GetTextEncodingBase (encoding);
+      text_encoding_info = assq_no_quit (make_number (sc),
+                                        text_encoding_info_alist);
+      if (NILP (text_encoding_info))
+       text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
+                                          text_encoding_info_alist);
+      decode_mac_font_name (name, sizeof (name),
+                           XCAR (XCDR (text_encoding_info)));
+      family = build_string (name);
+      if (!NILP (Fassoc (family, fm_font_family_alist)))
+       continue;
+      fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
+                                   fm_font_family_alist);
+
+      /* Point the instance iterator at the current font family.  */
+      if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
+       continue;
+
+      while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
+            == noErr)
        {
-         Str255 name;
-         FMFont font;
-         FMFontStyle style;
-         FMFontSize size;
-         TextEncoding encoding;
-         TextEncodingBase sc;
-
-         if (FMGetFontFamilyName (ff, name) != noErr)
-           break;
-         p2cstr (name);
-         if (*name == '.')
-           continue;
+         Lisp_Object rest = XCDR (XCDR (text_encoding_info));
 
-         if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
-           break;
-         sc = GetTextEncodingBase (encoding);
-         decode_mac_font_name (name, sizeof (name), sc);
+         if (size > 0 || style == normal)
+           for (; !NILP (rest); rest = XCDR (rest))
+             add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
+       }
+    }
 
-         /* Point the instance iterator at the current font family.  */
-         if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
-           break;
+  UNGCPRO;
 
-         while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
-                == noErr)
-           {
-             /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
-                contained in Apple Japanese (SJIS) font.  */
-           again:
-             if (size == 0)
-               {
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               style, sc));
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               italic, sc));
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               bold, sc));
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               italic | bold,
-                                                               sc));
-               }
-             else
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             style, sc));
-             if (sc == smJapanese)
-               {
-                 sc = -smJapanese;
-                 goto again;
-               }
-             else if (sc == -smJapanese)
-               sc = smJapanese;
-           }
-       }
+  /* Dispose of the iterators.  */
+  FMDisposeFontFamilyIterator (&ffi);
+  FMDisposeFontFamilyInstanceIterator (&ffii);
+#else  /* !TARGET_API_MAC_CARBON */
+  GrafPtr port;
+  SInt16 fontnum, old_fontnum;
+  int num_mac_fonts = CountResources('FOND');
+  int i, j;
+  Handle font_handle, font_handle_2;
+  short id, scriptcode;
+  ResType type;
+  Str255 name;
+  struct FontAssoc *fat;
+  struct AsscEntry *assc_entry;
+  Lisp_Object text_encoding_info_alist, text_encoding_info, family;
+  struct gcpro gcpro1;
 
-      /* Dispose of the iterators.  */
-      FMDisposeFontFamilyIterator (&ffi);
-      FMDisposeFontFamilyInstanceIterator (&ffii);
-    }
-  else
-    {
-#endif  /* TARGET_API_MAC_CARBON */
-      GrafPtr port;
-      SInt16 fontnum, old_fontnum;
-      int num_mac_fonts = CountResources('FOND');
-      int i, j;
-      Handle font_handle, font_handle_2;
-      short id, scriptcode;
-      ResType type;
-      Str32 name;
-      struct FontAssoc *fat;
-      struct AsscEntry *assc_entry;
-
-      GetPort (&port);  /* save the current font number used */
-#if TARGET_API_MAC_CARBON
-      old_fontnum = GetPortTextFont (port);
-#else
-      old_fontnum = port->txFont;
-#endif
+  GetPort (&port);  /* save the current font number used */
+  old_fontnum = port->txFont;
 
-      for (i = 1; i <= num_mac_fonts; i++)  /* get all available fonts */
+  text_encoding_info_alist = create_text_encoding_info_alist ();
+
+  GCPRO1 (text_encoding_info_alist);
+
+  for (i = 1; i <= num_mac_fonts; i++)  /* get all available fonts */
+    {
+      font_handle = GetIndResource ('FOND', i);
+      if (!font_handle)
+       continue;
+
+      GetResInfo (font_handle, &id, &type, name);
+      GetFNum (name, &fontnum);
+      p2cstr (name);
+      if (fontnum == 0 || *name == '.')
+       continue;
+
+      TextFont (fontnum);
+      scriptcode = FontToScript (fontnum);
+      text_encoding_info = assq_no_quit (make_number (scriptcode),
+                                        text_encoding_info_alist);
+      if (NILP (text_encoding_info))
+       text_encoding_info = assq_no_quit (make_number (smRoman),
+                                          text_encoding_info_alist);
+      decode_mac_font_name (name, sizeof (name),
+                           XCAR (XCDR (text_encoding_info)));
+      family = build_string (name);
+      if (!NILP (Fassoc (family, fm_font_family_alist)))
+       continue;
+      fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
+                                   fm_font_family_alist);
+      do
        {
-         font_handle = GetIndResource ('FOND', i);
-         if (!font_handle)
-           continue;
-
-         GetResInfo (font_handle, &id, &type, name);
-         GetFNum (name, &fontnum);
-         p2cstr (name);
-         if (fontnum == 0)
-           continue;
+         HLock (font_handle);
 
-         TextFont (fontnum);
-         scriptcode = FontToScript (fontnum);
-         decode_mac_font_name (name, sizeof (name), scriptcode);
-         do
+         if (GetResourceSizeOnDisk (font_handle)
+             >= sizeof (struct FamRec))
            {
-             HLock (font_handle);
-
-             if (GetResourceSizeOnDisk (font_handle)
-                 >= sizeof (struct FamRec))
+             fat = (struct FontAssoc *) (*font_handle
+                                         + sizeof (struct FamRec));
+             assc_entry
+               = (struct AsscEntry *) (*font_handle
+                                       + sizeof (struct FamRec)
+                                       + sizeof (struct FontAssoc));
+
+             for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
                {
-                 fat = (struct FontAssoc *) (*font_handle
-                                             + sizeof (struct FamRec));
-                 assc_entry
-                   = (struct AsscEntry *) (*font_handle
-                                           + sizeof (struct FamRec)
-                                           + sizeof (struct FontAssoc));
-
-                 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
-                   {
-                     if (font_name_table_size == 0)
-                       {
-                         font_name_table_size = 16;
-                         font_name_table = (char **)
-                           xmalloc (font_name_table_size * sizeof (char *));
-                       }
-                     else if (font_name_count >= font_name_table_size)
-                       {
-                         font_name_table_size += 16;
-                         font_name_table = (char **)
-                           xrealloc (font_name_table,
-                                     font_name_table_size * sizeof (char *));
-                       }
-                     font_name_table[font_name_count++]
-                       = mac_to_x_fontname (name,
-                                            assc_entry->fontSize,
-                                            assc_entry->fontStyle,
-                                            scriptcode);
-                     /* Both jisx0208.1983-sjis and jisx0201.1976-0
-                        parts are contained in Apple Japanese (SJIS)
-                        font.  */
-                     if (smJapanese == scriptcode)
-                       {
-                         font_name_table[font_name_count++]
-                           = mac_to_x_fontname (name,
-                                                assc_entry->fontSize,
-                                                assc_entry->fontStyle,
-                                                -smJapanese);
-                       }
-                   }
-               }
+                 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
 
-             HUnlock (font_handle);
-             font_handle_2 = GetNextFOND (font_handle);
-             ReleaseResource (font_handle);
-             font_handle = font_handle_2;
+                 for (; !NILP (rest); rest = XCDR (rest))
+                   add_mac_font_name (name, assc_entry->fontSize,
+                                      assc_entry->fontStyle,
+                                      SDATA (XCAR (rest)));
+               }
            }
-         while (ResError () == noErr && font_handle);
-       }
 
-      TextFont (old_fontnum);
-#if TARGET_API_MAC_CARBON
+         HUnlock (font_handle);
+         font_handle_2 = GetNextFOND (font_handle);
+         ReleaseResource (font_handle);
+         font_handle = font_handle_2;
+       }
+      while (ResError () == noErr && font_handle);
     }
-#endif  /* TARGET_API_MAC_CARBON */
+
+  UNGCPRO;
+
+  TextFont (old_fontnum);
+#endif  /* !TARGET_API_MAC_CARBON */
 }
 
 
@@ -6269,6 +7342,7 @@ mac_clear_font_name_table ()
   xfree (font_name_table);
   font_name_table = NULL;
   font_name_table_size = font_name_count = 0;
+  fm_font_family_alist = Qnil;
 }
 
 
@@ -6288,41 +7362,17 @@ static int xlfd_scalable_fields[] =
     -1
   };
 
-static Lisp_Object
-mac_c_string_match (regexp, string, nonspecial, exact)
-     Lisp_Object regexp;
-     const char *string, *nonspecial;
-     int exact;
-{
-  if (exact)
-    {
-      if (strcmp (string, nonspecial) == 0)
-       return build_string (string);
-    }
-  else if (strstr (string, nonspecial))
-    {
-      Lisp_Object str = build_string (string);
-
-      if (fast_string_match (regexp, str) >= 0)
-       return str;
-    }
-
-  return Qnil;
-}
-
 static Lisp_Object
 mac_do_list_fonts (pattern, maxnames)
      char *pattern;
      int maxnames;
 {
   int i, n_fonts = 0;
-  Lisp_Object font_list = Qnil, pattern_regex, fontname;
-  char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
-  char scaled[256];
-  char *ptr;
+  Lisp_Object font_list = Qnil;
+  struct xlfdpat *pat;
+  char *scaled, *ptr;
   int scl_val[XLFD_SCL_LAST], *field, *val;
-  char *longest_start, *cur_start, *nonspecial;
-  int longest_len, exact;
+  int exact;
 
   if (font_name_table == NULL)  /* Initialize when first used.  */
     init_font_name_table ();
@@ -6343,7 +7393,7 @@ mac_do_list_fonts (pattern, maxnames)
        ptr++;
        if (i == *field)
          {
-           if ('1' <= *ptr && *ptr <= '9')
+           if ('0' <= *ptr && *ptr <= '9')
              {
                *val = *ptr++ - '0';
                while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
@@ -6361,154 +7411,126 @@ mac_do_list_fonts (pattern, maxnames)
 
   if (i == 14 && ptr == NULL)
     {
-      if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
-       {
-         scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
-         scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
-       }
-      else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
-       {
-         scl_val[XLFD_SCL_POINT_SIZE] =
-           scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
-       }
-      else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
-       {
-         scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
-         scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
-       }
+      if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
+       scl_val[XLFD_SCL_PIXEL_SIZE] =
+         (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
+          : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
+             : -1));
+      if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
+       scl_val[XLFD_SCL_POINT_SIZE] =
+         (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
+          : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
+             : -1));
+      if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
+       scl_val[XLFD_SCL_AVGWIDTH] =
+         (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
+          : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
+             : -1));
     }
   else
     scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
 
-  ptr = regex;
-  *ptr++ = '^';
-
-  longest_start = cur_start = ptr;
-  longest_len = 0;
-  exact = 1;
-
-  /* Turn pattern into a regexp and do a regexp match.  Also find the
-     longest substring containing no special characters.  */
-  for (; *pattern; pattern++)
-    {
-      if (*pattern == '?' || *pattern == '*')
-       {
-         if (ptr - cur_start > longest_len)
-           {
-             longest_start = cur_start;
-             longest_len = ptr - cur_start;
-           }
-         exact = 0;
-
-         if (*pattern == '?')
-           *ptr++ = '.';
-         else /* if (*pattern == '*') */
-           {
-             *ptr++ = '.';
-             *ptr++ = '*';
-           }
-         cur_start = ptr;
-       }
-      else
-       *ptr++ = tolower (*pattern);
-    }
-
-  if (ptr - cur_start > longest_len)
-    {
-      longest_start = cur_start;
-      longest_len = ptr - cur_start;
-    }
-
-  *ptr = '$';
-  *(ptr + 1) = '\0';
-
-  nonspecial = xmalloc (longest_len + 1);
-  strncpy (nonspecial, longest_start, longest_len);
-  nonspecial[longest_len] = '\0';
+  pat = xlfdpat_create (pattern);
+  if (pat == NULL)
+    return Qnil;
 
-  pattern_regex = build_string (regex);
+  exact = xlfdpat_exact_p (pat);
 
   for (i = 0; i < font_name_count; i++)
     {
-      fontname = mac_c_string_match (pattern_regex, font_name_table[i],
-                                    nonspecial, exact);
-      if (!NILP (fontname))
+      if (xlfdpat_match (pat, font_name_table[i]))
        {
-         font_list = Fcons (fontname, font_list);
-         if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+         font_list = Fcons (build_string (font_name_table[i]), font_list);
+         if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
            break;
        }
       else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
-              && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
+              && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
        {
          int former_len = ptr - font_name_table[i];
 
+         scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
          memcpy (scaled, font_name_table[i], former_len);
          sprintf (scaled + former_len,
-                  "-%d-%d-75-75-m-%d-%s",
+                  "-%d-%d-72-72-m-%d-%s",
                   scl_val[XLFD_SCL_PIXEL_SIZE],
                   scl_val[XLFD_SCL_POINT_SIZE],
                   scl_val[XLFD_SCL_AVGWIDTH],
-                  ptr + sizeof ("-0-0-75-75-m-0-") - 1);
-         fontname = mac_c_string_match (pattern_regex, scaled,
-                                        nonspecial, exact);
-         if (!NILP (fontname))
+                  ptr + sizeof ("-0-0-0-0-m-0-") - 1);
+
+         if (xlfdpat_match (pat, scaled))
            {
-             font_list = Fcons (fontname, font_list);
-             if (exact || maxnames > 0 && ++n_fonts >= maxnames)
-               break;
+             font_list = Fcons (build_string (scaled), font_list);
+             xfree (scaled);
+             if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
+                 break;
            }
+         else
+           xfree (scaled);
        }
     }
 
-  xfree (nonspecial);
+  xlfdpat_destroy (pat);
 
   return font_list;
 }
 
-/* Return a list of at most MAXNAMES font specs matching the one in
-   PATTERN.  Cache matching fonts for patterns in
-   dpyinfo->name_list_element to avoid looking them up again by
-   calling mac_font_pattern_match (slow).  Return as many matching
-   fonts as possible if MAXNAMES = -1.  */
+/* Return a list of names of available fonts matching PATTERN on frame F.
+
+   Frame F null means we have not yet created any frame on Mac, and
+   consult the first display in x_display_list.  MAXNAMES sets a limit
+   on how many fonts to match.  */
 
 Lisp_Object
-x_list_fonts (struct frame *f,
-              Lisp_Object pattern,
-              int size,
-              int maxnames)
+x_list_fonts (f, pattern, size, maxnames)
+     struct frame *f;
+     Lisp_Object pattern;
+     int size, maxnames;
 {
-  Lisp_Object newlist = Qnil, tem, key;
-  struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
+  Lisp_Object list = Qnil, patterns, tem, key;
+  struct mac_display_info *dpyinfo
+    = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
+
+  xassert (size <= 0);
 
-  if (dpyinfo)
+  patterns = Fassoc (pattern, Valternate_fontname_alist);
+  if (NILP (patterns))
+    patterns = Fcons (pattern, Qnil);
+
+  for (; CONSP (patterns); patterns = XCDR (patterns))
     {
-      tem = XCDR (dpyinfo->name_list_element);
+      pattern = XCAR (patterns);
+
+      if (!STRINGP (pattern))
+        continue;
+
+      tem = XCAR (XCDR (dpyinfo->name_list_element));
       key = Fcons (pattern, make_number (maxnames));
 
-      newlist = Fassoc (key, tem);
-      if (!NILP (newlist))
+      list = Fassoc (key, tem);
+      if (!NILP (list))
        {
-         newlist = Fcdr_safe (newlist);
+         list = Fcdr_safe (list);
+         /* We have a cashed list.  Don't have to get the list again.  */
          goto label_cached;
        }
-    }
 
-  BLOCK_INPUT;
-  newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
-  UNBLOCK_INPUT;
+      BLOCK_INPUT;
+      list = mac_do_list_fonts (SDATA (pattern), maxnames);
+      UNBLOCK_INPUT;
 
-  /* MAC_TODO: add code for matching outline fonts here */
+      /* MAC_TODO: add code for matching outline fonts here */
 
-  if (dpyinfo)
-    {
-      XSETCDR (dpyinfo->name_list_element,
-              Fcons (Fcons (key, newlist),
-                     XCDR (dpyinfo->name_list_element)));
+      /* Now store the result in the cache.  */
+      XSETCAR (XCDR (dpyinfo->name_list_element),
+              Fcons (Fcons (key, list),
+                     XCAR (XCDR (dpyinfo->name_list_element))));
+
+    label_cached:
+      if (NILP (list)) continue; /* Try the remaining alternatives.  */
     }
- label_cached:
 
-  return newlist;
+  return list;
 }
 
 
@@ -6559,7 +7581,7 @@ x_font_min_bounds (font, w, h)
    the values computed.  Value is non-zero if smallest_font_height or
    smallest_char_width become smaller than they were before.  */
 
-int
+static int
 x_compute_min_glyph_bounds (f)
      struct frame *f;
 {
@@ -6617,191 +7639,388 @@ is_fully_specified_xlfd (char *p)
       p = q;
     }
 
-  if (strchr (p + 1, '-') != NULL)
-    return 0;
+  if (strchr (p + 1, '-') != NULL)
+    return 0;
+
+  if (*(p + 1) == '*' && *(p + 2) == '\0')
+    return 0;
+
+  return 1;
+}
+
+
+/* XLoadQueryFont creates and returns an internal representation for a
+   font in a MacFontStruct struct.  There is really no concept
+   corresponding to "loading" a font on the Mac.  But we check its
+   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)
+{
+  int size;
+  char *name;
+  Str255 family;
+  Str31 charset;
+  SInt16 fontnum;
+#if USE_ATSUI
+  static ATSUFontID font_id;
+  ATSUStyle mac_style = NULL;
+#endif
+  Style fontface;
+#if TARGET_API_MAC_CARBON
+  TextEncoding encoding;
+  int scriptcode;
+#else
+  short scriptcode;
+#endif
+  MacFontStruct *font;
+  XCharStruct *space_bounds = NULL, *pcm;
+
+  if (is_fully_specified_xlfd (fontname))
+    name = fontname;
+  else
+    {
+      Lisp_Object matched_fonts;
+
+      matched_fonts = mac_do_list_fonts (fontname, 1);
+      if (NILP (matched_fonts))
+       return NULL;
+      name = SDATA (XCAR (matched_fonts));
+    }
+
+  if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
+    return NULL;
+
+#if USE_ATSUI
+  if (strcmp (charset, "iso10646-1") == 0) /* XXX */
+    {
+      OSErr err;
+      ATSUAttributeTag tags[] = {kATSUFontTag, kATSUSizeTag,
+                                kATSUQDBoldfaceTag, kATSUQDItalicTag};
+      ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed),
+                          sizeof (Boolean), sizeof (Boolean)};
+      static Fixed size_fixed;
+      static Boolean bold_p, italic_p;
+      ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
+                                       &bold_p, &italic_p};
+      ATSUFontFeatureType types[] = {kAllTypographicFeaturesType,
+                                    kDiacriticsType};
+      ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector,
+                                            kDecomposeDiacriticsSelector};
+      Lisp_Object font_id_cons;
+
+      font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
+                              atsu_font_id_hash, Qnil);
+      if (NILP (font_id_cons))
+       return NULL;
+      font_id = cons_to_long (font_id_cons);
+      size_fixed = Long2Fix (size);
+      bold_p = (fontface & bold) != 0;
+      italic_p = (fontface & italic) != 0;
+      err = ATSUCreateStyle (&mac_style);
+      if (err != noErr)
+       return NULL;
+      err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
+                                types, selectors);
+      if (err != noErr)
+       return NULL;
+      err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
+                              tags, sizes, values);
+      fontnum = -1;
+      scriptcode = kTextEncodingMacUnicode;
+    }
+  else
+#endif
+    {
+      Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
+
+      if (NILP (tmp))
+       return NULL;
+      fontnum = XINT (XCDR (tmp));
+#if TARGET_API_MAC_CARBON
+      if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
+       return NULL;
+      scriptcode = GetTextEncodingBase (encoding);
+#else
+      scriptcode = FontToScript (fontnum);
+#endif
+    }
+
+  font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
+
+  font->mac_fontnum = fontnum;
+  font->mac_fontsize = size;
+  font->mac_fontface = fontface;
+  font->mac_scriptcode = scriptcode;
+#if USE_ATSUI
+  font->mac_style = mac_style;
+#if USE_CG_TEXT_DRAWING
+  font->cg_font = NULL;
+  font->cg_glyphs = NULL;
+#endif
+#endif
+
+  /* Apple Japanese (SJIS) font is listed as both
+     "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
+     (Roman script) in init_font_name_table ().  The latter should be
+     treated as a one-byte font.  */
+  if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
+    font->mac_scriptcode = smRoman;
+
+  font->full_name = mac_to_x_fontname (family, size, fontface, charset);
 
-  if (*(p + 1) == '*' && *(p + 2) == '\0')
-    return 0;
+#if USE_ATSUI
+  if (font->mac_style)
+    {
+      OSErr err;
+      UniChar c;
 
-  return 1;
-}
+      font->min_byte1 = 0;
+      font->max_byte1 = 0xff;
+      font->min_char_or_byte2 = 0;
+      font->max_char_or_byte2 = 0xff;
 
+      font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
+      bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
+      font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
+      pcm_init (font->bounds.rows[0], 0x100);
 
-const int kDefaultFontSize = 9;
+#if USE_CG_TEXT_DRAWING
+      {
+       FMFontFamily font_family;
+       FMFontStyle style;
+       ATSFontRef ats_font;
 
+       err = FMGetFontFamilyInstanceFromFont (font_id, &font_family, &style);
+       if (err == noErr)
+         err = FMGetFontFromFontFamilyInstance (font_family, 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);
+         }
+      }
 
-/* XLoadQueryFont creates and returns an internal representation for a
-   font in a MacFontStruct struct.  There is really no concept
-   corresponding to "loading" a font on the Mac.  But we check its
-   existence and find the font number and all other information for it
-   and store them in the returned MacFontStruct.  */
+      if (font->cg_font)
+       {
+         font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
+         bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
+       }
+#endif
+      space_bounds = font->bounds.rows[0] + 0x20;
+      err = mac_query_char_extents (font->mac_style, 0x20,
+                                   &font->ascent, &font->descent,
+                                   space_bounds,
+#if USE_CG_TEXT_DRAWING
+                                   (font->cg_glyphs ? font->cg_glyphs + 0x20
+                                    : NULL)
+#else
+                                   NULL
+#endif
+                                   );
+      if (err != noErr)
+       {
+         mac_unload_font (&one_mac_display_info, font);
+         return NULL;
+       }
 
-static MacFontStruct *
-XLoadQueryFont (Display *dpy, char *fontname)
-{
-  int i, size, is_two_byte_font, char_width;
-  char *name;
-  GrafPtr port;
-  SInt16 old_fontnum, old_fontsize;
-  Style old_fontface;
-  Str32 mfontname;
-  SInt16 fontnum;
-  Style fontface = normal;
-  MacFontStruct *font;
-  FontInfo the_fontinfo;
-  char s_weight[7], c_slant;
+      pcm = font->bounds.rows[0];
+      for (c = 0x21; c <= 0xff; c++)
+       {
+         if (c == 0xad)
+           /* Soft hyphen is not supported in ATSUI.  */
+           continue;
+         else if (c == 0x7f)
+           {
+             c = 0x9f;
+             continue;
+           }
 
-  if (is_fully_specified_xlfd (fontname))
-    name = fontname;
-  else
-    {
-      Lisp_Object matched_fonts;
+         mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
+#if USE_CG_TEXT_DRAWING
+                                 (font->cg_glyphs ? font->cg_glyphs + c
+                                  : NULL)
+#else
+                                   NULL
+#endif
+                                 );
 
-      matched_fonts = mac_do_list_fonts (fontname, 1);
-      if (NILP (matched_fonts))
-       return NULL;
-      name = SDATA (XCAR (matched_fonts));
+#if USE_CG_TEXT_DRAWING
+         if (font->cg_glyphs && font->cg_glyphs[c] == 0)
+           {
+             /* Don't use CG text drawing if font substitution occurs in
+                ASCII or Latin-1 characters.  */
+             CGFontRelease (font->cg_font);
+             font->cg_font = NULL;
+             xfree (font->cg_glyphs);
+             font->cg_glyphs = NULL;
+           }
+#endif
+       }
     }
+  else
+#endif
+    {
+      GrafPtr port;
+      SInt16 old_fontnum, old_fontsize;
+      Style old_fontface;
+      FontInfo the_fontinfo;
+      int is_two_byte_font;
 
-  GetPort (&port);  /* save the current font number used */
+      /* 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);
+      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;
+      old_fontnum = port->txFont;
+      old_fontsize = port->txSize;
+      old_fontface = port->txFace;
 #endif
 
-  if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
-    size = kDefaultFontSize;
+      TextFont (fontnum);
+      TextSize (size);
+      TextFace (fontface);
 
-  if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
-    if (strcmp (s_weight, "bold") == 0)
-      fontface |= bold;
+      GetFontInfo (&the_fontinfo);
 
-  if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
-    if (c_slant == 'i')
-      fontface |= italic;
+      font->ascent = the_fontinfo.ascent;
+      font->descent = the_fontinfo.descent;
 
-  x_font_name_to_mac_font_name (name, mfontname);
-  c2pstr (mfontname);
-  GetFNum (mfontname, &fontnum);
-  if (fontnum == 0)
-    return NULL;
+      is_two_byte_font = (font->mac_scriptcode == smJapanese
+                         || font->mac_scriptcode == smTradChinese
+                         || font->mac_scriptcode == smSimpChinese
+                         || font->mac_scriptcode == smKorean);
 
-  font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
+      if (is_two_byte_font)
+       {
+         int char_width;
 
-  font->fontname = (char *) xmalloc (strlen (name) + 1);
-  bcopy (name, font->fontname, strlen (name) + 1);
+         font->min_byte1 = 0xa1;
+         font->max_byte1 = 0xfe;
+         font->min_char_or_byte2 = 0xa1;
+         font->max_char_or_byte2 = 0xfe;
 
-  font->mac_fontnum = fontnum;
-  font->mac_fontsize = size;
-  font->mac_fontface = fontface;
-  font->mac_scriptcode = FontToScript (fontnum);
+         /* Use the width of an "ideographic space" of that font
+            because the_fontinfo.widMax returns the wrong width for
+            some fonts.  */
+         switch (font->mac_scriptcode)
+           {
+           case smJapanese:
+             font->min_byte1 = 0x81;
+             font->max_byte1 = 0xfc;
+             font->min_char_or_byte2 = 0x40;
+             font->max_char_or_byte2 = 0xfc;
+             char_width = StringWidth("\p\x81\x40");
+             break;
+           case smTradChinese:
+             font->min_char_or_byte2 = 0x40;
+             char_width = StringWidth("\p\xa1\x40");
+             break;
+           case smSimpChinese:
+             char_width = StringWidth("\p\xa1\xa1");
+             break;
+           case smKorean:
+             char_width = StringWidth("\p\xa1\xa1");
+             break;
+           }
 
-  /* Apple Japanese (SJIS) font is listed as both
-     "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
-     (Roman script) in init_font_name_table ().  The latter should be
-     treated as a one-byte font.  */
-  {
-    char cs[32];
+         font->bounds.per_char = NULL;
 
-    if (sscanf (name,
-               "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
-               cs) == 1
-       && 0 == strcmp (cs, "jisx0201.1976-0"))
-      font->mac_scriptcode = smRoman;
-  }
+         if (fontface & italic)
+           font->max_bounds.rbearing = char_width + 1;
+         else
+           font->max_bounds.rbearing = char_width;
+         font->max_bounds.lbearing = 0;
+         font->max_bounds.width = char_width;
+         font->max_bounds.ascent = the_fontinfo.ascent;
+         font->max_bounds.descent = the_fontinfo.descent;
 
-  is_two_byte_font = font->mac_scriptcode == smJapanese ||
-                     font->mac_scriptcode == smTradChinese ||
-                     font->mac_scriptcode == smSimpChinese ||
-                     font->mac_scriptcode == smKorean;
+         font->min_bounds = font->max_bounds;
+       }
+      else
+       {
+         int c;
 
-  TextFont (fontnum);
-  TextSize (size);
-  TextFace (fontface);
+         font->min_byte1 = font->max_byte1 = 0;
+         font->min_char_or_byte2 = 0x20;
+         font->max_char_or_byte2 = 0xff;
 
-  GetFontInfo (&the_fontinfo);
+         font->bounds.per_char =
+           xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
+         bzero (font->bounds.per_char,
+                sizeof (XCharStruct) * (0xff - 0x20 + 1));
 
-  font->ascent = the_fontinfo.ascent;
-  font->descent = the_fontinfo.descent;
+         space_bounds = font->bounds.per_char;
+         mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
+                                 space_bounds, NULL);
 
-  font->min_byte1 = 0;
-  if (is_two_byte_font)
-    font->max_byte1 = 1;
-  else
-    font->max_byte1 = 0;
-  font->min_char_or_byte2 = 0x20;
-  font->max_char_or_byte2 = 0xff;
+         for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
+           mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
+       }
 
-  if (is_two_byte_font)
-    {
-      /* Use the width of an "ideographic space" of that font because
-         the_fontinfo.widMax returns the wrong width for some fonts.  */
-      switch (font->mac_scriptcode)
-        {
-        case smJapanese:
-          char_width = StringWidth("\p\x81\x40");
-          break;
-        case smTradChinese:
-          char_width = StringWidth("\p\xa1\x40");
-          break;
-        case smSimpChinese:
-          char_width = StringWidth("\p\xa1\xa1");
-          break;
-        case smKorean:
-          char_width = StringWidth("\p\xa1\xa1");
-          break;
-        }
+      /* Restore previous font number, size and face.  */
+      TextFont (old_fontnum);
+      TextSize (old_fontsize);
+      TextFace (old_fontface);
     }
-  else
-    /* Do this instead of use the_fontinfo.widMax, which incorrectly
-       returns 15 for 12-point Monaco! */
-    char_width = CharWidth ('m');
-
-  font->max_bounds.rbearing = char_width;
-  font->max_bounds.lbearing = 0;
-  font->max_bounds.width = char_width;
-  font->max_bounds.ascent = the_fontinfo.ascent;
-  font->max_bounds.descent = the_fontinfo.descent;
 
-  font->min_bounds = font->max_bounds;
-
-  if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
-    font->per_char = NULL;
-  else
+  if (space_bounds)
     {
-      font->per_char = (XCharStruct *)
-       xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
-      {
-        int c, min_width, max_width;
+      int c;
 
-       min_width = max_width = char_width;
-        for (c = 0x20; c <= 0xff; c++)
-          {
-           font->per_char[c - 0x20] = font->max_bounds;
-           char_width = CharWidth (c);
-           font->per_char[c - 0x20].width = char_width;
-           font->per_char[c - 0x20].rbearing = char_width;
-           /* Some Japanese fonts (in SJIS encoding) return 0 as the
-              character width of 0x7f.  */
-           if (char_width > 0)
-             {
-               min_width = min (min_width, char_width);
-               max_width = max (max_width, char_width);
-             }
-            }
-       font->min_bounds.width = min_width;
-       font->max_bounds.width = max_width;
-      }
+      font->min_bounds = font->max_bounds = *space_bounds;
+      for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
+       if (pcm->width > 0)
+         {
+           font->min_bounds.lbearing = min (font->min_bounds.lbearing,
+                                            pcm->lbearing);
+           font->min_bounds.rbearing = min (font->min_bounds.rbearing,
+                                            pcm->rbearing);
+           font->min_bounds.width    = min (font->min_bounds.width,
+                                            pcm->width);
+           font->min_bounds.ascent   = min (font->min_bounds.ascent,
+                                            pcm->ascent);
+
+           font->max_bounds.lbearing = max (font->max_bounds.lbearing,
+                                            pcm->lbearing);
+           font->max_bounds.rbearing = max (font->max_bounds.rbearing,
+                                            pcm->rbearing);
+           font->max_bounds.width    = max (font->max_bounds.width,
+                                            pcm->width);
+           font->max_bounds.ascent   = max (font->max_bounds.ascent,
+                                            pcm->ascent);
+         }
+      if (
+#if USE_ATSUI
+         font->mac_style == NULL &&
+#endif
+         font->max_bounds.width == font->min_bounds.width
+         && font->min_bounds.lbearing >= 0
+         && font->max_bounds.rbearing <= font->max_bounds.width)
+       {
+         /* Fixed width and no overhangs.  */
+         xfree (font->bounds.per_char);
+         font->bounds.per_char = NULL;
+       }
     }
 
-  TextFont (old_fontnum);  /* restore previous font number, size and face */
-  TextSize (old_fontsize);
-  TextFace (old_fontface);
+#if !defined (MAC_OS8) || USE_ATSUI
+  /* AppKit and WebKit do some adjustment to the heights of Courier,
+     Helvetica, and Times.  This only works on the environments where
+     srcCopy text transfer mode is never used.  */
+  if (
+#ifdef MAC_OS8                 /* implies USE_ATSUI */
+      font->mac_style &&
+#endif
+      (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
+       || strcmp (family, "times") == 0))
+    font->ascent += (font->ascent + font->descent) * .15 + 0.5;
+#endif
 
   return font;
 }
@@ -6812,9 +8031,28 @@ mac_unload_font (dpyinfo, font)
      struct mac_display_info *dpyinfo;
      XFontStruct *font;
 {
-  xfree (font->fontname);
-  if (font->per_char)
-    xfree (font->per_char);
+  xfree (font->full_name);
+#if USE_ATSUI
+  if (font->mac_style)
+    {
+      int i;
+
+      for (i = font->min_byte1; i <= font->max_byte1; i++)
+       if (font->bounds.rows[i])
+         xfree (font->bounds.rows[i]);
+      xfree (font->bounds.rows);
+      ATSUDisposeStyle (font->mac_style);
+    }
+  else
+#endif
+    if (font->bounds.per_char)
+      xfree (font->bounds.per_char);
+#if USE_CG_TEXT_DRAWING
+  if (font->cg_font)
+    CGFontRelease (font->cg_font);
+  if (font->cg_glyphs)
+    xfree (font->cg_glyphs);
+#endif
   xfree (font);
 }
 
@@ -6852,22 +8090,16 @@ x_load_font (f, fontname, size)
                              SDATA (XCAR (tail)))))
            return (dpyinfo->font_table + i);
     }
+  else
+    return NULL;
 
   /* Load the font and add it to the table.  */
   {
-    char *full_name;
     struct MacFontStruct *font;
     struct font_info *fontp;
-    unsigned long value;
     int i;
 
-    /* If we have found fonts by x_list_font, load one of them.  If
-       not, we still try to load a font by the name given as FONTNAME
-       because XListFonts (called in x_list_font) of some X server has
-       a bug of not finding a font even if the font surely exists and
-       is loadable by XLoadQueryFont.  */
-    if (size > 0 && !NILP (font_names))
-      fontname = (char *) SDATA (XCAR (font_names));
+    fontname = (char *) SDATA (XCAR (font_names));
 
     BLOCK_INPUT;
     font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
@@ -6900,8 +8132,8 @@ x_load_font (f, fontname, size)
     bzero (fontp, sizeof (*fontp));
     fontp->font = font;
     fontp->font_idx = i;
-    fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
-    bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
+    fontp->name = (char *) xmalloc (strlen (fontname) + 1);
+    bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
     if (font->min_bounds.width == font->max_bounds.width)
       {
@@ -6932,7 +8164,8 @@ x_load_font (f, fontname, size)
          fontp->average_width = FONT_WIDTH (font);
       }
 
-    fontp->full_name = fontp->name;
+    fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
+    bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
 
     fontp->size = font->max_bounds.width;
     fontp->height = FONT_HEIGHT (font);
@@ -6998,10 +8231,10 @@ x_load_font (f, fontname, size)
 
     /* Set global flag fonts_changed_p to non-zero if the font loaded
        has a character with a smaller width than any other character
-       before, or if the font loaded has a smalle>r height than any
+       before, or if the font loaded has a smaller height than any
        other font loaded before.  If this happens, it will make a
        glyph matrix reallocation necessary.  */
-    fonts_changed_p = x_compute_min_glyph_bounds (f);
+    fonts_changed_p |= x_compute_min_glyph_bounds (f);
     UNBLOCK_INPUT;
     return fontp;
   }
@@ -7062,7 +8295,7 @@ x_find_ccl_program (fontp)
 \f
 /* The Mac Event loop code */
 
-#ifndef MAC_OSX
+#if !TARGET_API_MAC_CARBON
 #include <Events.h>
 #include <Quickdraw.h>
 #include <Balloons.h>
@@ -7077,13 +8310,12 @@ x_find_ccl_program (fontp)
 #include <Dialogs.h>
 #include <Script.h>
 #include <Types.h>
-#include <TextEncodingConverter.h>
 #include <Resources.h>
 
 #if __MWERKS__
 #include <unix.h>
 #endif
-#endif /* ! MAC_OSX */
+#endif /* ! TARGET_API_MAC_CARBON */
 
 #define M_APPLE 128
 #define I_ABOUT 1
@@ -7096,100 +8328,74 @@ x_find_ccl_program (fontp)
 #define MIN_DOC_SIZE 64
 #define MAX_DOC_SIZE 32767
 
-/* sleep time for WaitNextEvent */
-#define WNE_SLEEP_AT_SUSPEND 10
-#define WNE_SLEEP_AT_RESUME  1
-
-/* true when cannot handle any Mac OS events */
-static int handling_window_update = 0;
-
-#if 0
-/* the flag appl_is_suspended is used both for determining the sleep
-   time to be passed to WaitNextEvent and whether the cursor should be
-   drawn when updating the display.  The cursor is turned off when
-   Emacs is suspended.  Redrawing it is unnecessary and what needs to
-   be done depends on whether the cursor lies inside or outside the
-   redraw region.  So we might as well skip drawing it when Emacs is
-   suspended.  */
-static Boolean app_is_suspended = false;
-static long app_sleep_time = WNE_SLEEP_AT_RESUME;
-#endif
-
 #define EXTRA_STACK_ALLOC (256 * 1024)
 
 #define ARGV_STRING_LIST_ID 129
 #define ABOUT_ALERT_ID 128
 #define RAM_TOO_LARGE_ALERT_ID 129
 
-Boolean        terminate_flag = false;
-
 /* Contains the string "reverse", which is a constant for mouse button emu.*/
 Lisp_Object Qreverse;
 
-/* True if using command key as meta key.  */
-Lisp_Object Vmac_command_key_is_meta;
 
-/* Modifier associated with the option key, or nil for normal behavior. */
+/* Modifier associated with the control key, or nil to ignore. */
+Lisp_Object Vmac_control_modifier;
+
+/* Modifier associated with the option key, or nil to ignore. */
 Lisp_Object Vmac_option_modifier;
 
-/* True if the ctrl and meta keys should be reversed.  */
-Lisp_Object Vmac_reverse_ctrl_meta;
+/* Modifier associated with the command key, or nil to ignore. */
+Lisp_Object Vmac_command_modifier;
+
+/* Modifier associated with the function key, or nil to ignore. */
+Lisp_Object Vmac_function_modifier;
 
 /* True if the option and command modifiers should be used to emulate
    a three button mouse */
 Lisp_Object Vmac_emulate_three_button_mouse;
 
 #if USE_CARBON_EVENTS
-/* True if the mouse wheel button (i.e. button 4) should map to
+/* Non-zero if the mouse wheel button (i.e. button 4) should map to
    mouse-2, instead of mouse-3.  */
-Lisp_Object Vmac_wheel_button_is_mouse_2;
+int mac_wheel_button_is_mouse_2;
 
-/* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
+/* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
    for processing before Emacs sees it.  */
-Lisp_Object Vmac_pass_command_to_system;
+int mac_pass_command_to_system;
 
-/* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
+/* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
    for processing before Emacs sees it.  */
-Lisp_Object Vmac_pass_control_to_system;
+int mac_pass_control_to_system;
 #endif
 
-/* convert input from Mac keyboard (assumed to be in Mac Roman coding)
-   to this text encoding */
-int mac_keyboard_text_encoding;
-int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
-
-/* Set in term/mac-win.el to indicate that event loop can now generate
-   drag and drop events.  */
-Lisp_Object Qmac_ready_for_drag_n_drop;
-
-Lisp_Object drag_and_drop_file_list;
+/* Points to the variable `inev' in the function XTread_socket.  It is
+   used for passing an input event to the function back from
+   Carbon/Apple event handlers.  */
+static struct input_event *read_socket_inev = NULL;
 
 Point saved_menu_event_location;
 
-#if !TARGET_API_MAC_CARBON
-/* Place holder for the default arrow cursor.  */
-CursPtr arrow_cursor;
-#endif
-
 /* Apple Events */
-static void init_required_apple_events (void);
-static pascal OSErr
-do_ae_open_application (const AppleEvent *, AppleEvent *, long);
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
+#if USE_CARBON_EVENTS
+static Lisp_Object Qhicommand;
+#endif
+extern int mac_ready_for_apple_events;
+extern Lisp_Object Qundefined;
+extern void init_apple_event_handler P_ ((void));
+extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
+                                          Lisp_Object *, Lisp_Object *,
+                                          Lisp_Object *));
+extern OSErr init_coercion_handler P_ ((void));
 
-#if TARGET_API_MAC_CARBON
 /* Drag and Drop */
-static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
-static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
-#endif
+OSErr install_drag_handler P_ ((WindowRef));
+void remove_drag_handler P_ ((WindowRef));
 
 #if USE_CARBON_EVENTS
-/* Preliminary Support for the OSX Services Menu */
-static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
-static void init_service_handler ();
+#ifdef MAC_OSX
+extern void init_service_handler ();
+static Lisp_Object Qservices, Qpaste, Qperform;
+#endif
 /* Window Event Handler */
 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
                                                EventRef, void *);
@@ -7198,7 +8404,6 @@ OSErr install_window_handler (WindowPtr);
 
 extern void init_emacs_passwd_dir ();
 extern int emacs_main (int, char **, char **);
-extern void check_alarm ();
 
 extern void initialize_applescript();
 extern void terminate_applescript();
@@ -7211,19 +8416,41 @@ mac_to_emacs_modifiers (EventModifiers mods)
 #endif
 {
   unsigned int result = 0;
-  if (mods & macShiftKey)
+  if (mods & shiftKey)
     result |= shift_modifier;
-  if (mods & macCtrlKey)
-    result |= ctrl_modifier;
-  if (mods & macMetaKey)
-    result |= meta_modifier;
-  if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
-    result |= alt_modifier;
+
+  /* Deactivated to simplify configuration:
+     if Vmac_option_modifier is non-NIL, we fully process the Option
+     key. Otherwise, we only process it if an additional Ctrl or Command
+     is pressed. That way the system may convert the character to a
+     composed one.
+     if ((mods & optionKey) &&
+      (( !NILP(Vmac_option_modifier) ||
+      ((mods & cmdKey) || (mods & controlKey))))) */
+
   if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
-      Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
-      if (!NILP(val))
-          result |= XUINT(val);
+    Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+  if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
+    Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+  if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
+    Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
+  }
+
+#ifdef MAC_OSX
+  if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
+    Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
+    if (INTEGERP(val))
+      result |= XUINT(val);
   }
+#endif
 
   return result;
 }
@@ -7245,7 +8472,7 @@ mac_get_emulated_btn ( UInt32 modifiers )
 #if USE_CARBON_EVENTS
 /* Obtains the event modifiers from the event ref and then calls
    mac_to_emacs_modifiers.  */
-static int
+static UInt32
 mac_event_to_emacs_modifiers (EventRef eventRef)
 {
   UInt32 mods = 0;
@@ -7279,10 +8506,10 @@ mac_get_mouse_btn (EventRef ref)
        return mac_get_emulated_btn(mods);
       }
     case kEventMouseButtonSecondary:
-      return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
+      return mac_wheel_button_is_mouse_2 ? 2 : 1;
     case kEventMouseButtonTertiary:
     case 4:  /* 4 is the number for the mouse wheel button */
-      return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
+      return mac_wheel_button_is_mouse_2 ? 1 : 2;
     default:
       return 0;
     }
@@ -7290,50 +8517,94 @@ 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.  This calls ConvertEventRef, but then
-   checks to see if it is a mouse up or down carbon event that has not
-   been converted, and if so, converts it by hand (to be picked up in
-   the XTread_socket loop).  */
+   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
+   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);
-  /* Do special case for mouse wheel button.  */
-  if (!result && GetEventClass (eventRef) == kEventClassMouse)
+
+  if (result)
+    return result;
+
+  switch (GetEventClass (eventRef))
     {
-      UInt32 kind = GetEventKind (eventRef);
-      if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
+    case kEventClassMouse:
+      switch (GetEventKind (eventRef))
        {
+       case kEventMouseDown:
          eventRec->what = mouseDown;
-         result=1;
-       }
-      if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
-       {
+         result = 1;
+         break;
+
+       case kEventMouseUp:
          eventRec->what = mouseUp;
-         result=1;
+         result = 1;
+         break;
+
+       default:
+         break;
        }
-      if (result)
+      break;
+
+    case kEventClassKeyboard:
+      switch (GetEventKind (eventRef))
        {
-         /* Need where and when.  */
-         UInt32 mods;
-         GetEventParameter (eventRef, kEventParamMouseLocation,
-                            typeQDPoint, NULL, sizeof (Point),
-                            NULL, &eventRec->where);
-         /* Use two step process because new event modifiers are
-            32-bit and old are 16-bit.  Currently, only loss is
-            NumLock & Fn. */
-         GetEventParameter (eventRef, kEventParamKeyModifiers,
-                            typeUInt32, NULL, sizeof (UInt32),
-                            NULL, &mods);
-         eventRec->modifiers = mods;
-
-         eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
+       case kEventRawKeyDown:
+         {
+           unsigned char char_codes;
+           UInt32 key_code;
+
+           err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
+                                    typeChar, NULL, sizeof (char),
+                                    NULL, &char_codes);
+           if (err == noErr)
+             err = GetEventParameter (eventRef, kEventParamKeyCode,
+                                      typeUInt32, NULL, sizeof (UInt32),
+                                      NULL, &key_code);
+           if (err == noErr)
+             {
+               eventRec->what = keyDown;
+               eventRec->message = char_codes | ((key_code & 0xff) << 8);
+               result = 1;
+             }
+         }
+         break;
+
+       default:
+         break;
        }
+      break;
+
+    default:
+      break;
     }
+
+  if (result)
+    {
+      /* Need where and when.  */
+      UInt32 mods = 0;
+
+      GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
+                        NULL, sizeof (Point), NULL, &eventRec->where);
+      /* Use two step process because new event modifiers are 32-bit
+        and old are 16-bit.  Currently, only loss is NumLock & Fn. */
+      GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
+                        NULL, sizeof (UInt32), NULL, &mods);
+      eventRec->modifiers = mods;
+
+      eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
+    }
+
   return result;
 }
 
 #endif
 
+#ifdef MAC_OS8
 static void
 do_get_menus (void)
 {
@@ -7346,11 +8617,13 @@ do_get_menus (void)
   SetMenuBar (menubar_handle);
   DrawMenuBar ();
 
+#if !TARGET_API_MAC_CARBON
   menu_handle = GetMenuHandle (M_APPLE);
   if(menu_handle != NULL)
     AppendResMenu (menu_handle,'DRVR');
   else
     abort ();
+#endif
 }
 
 
@@ -7369,8 +8642,6 @@ do_init_managers (void)
   InitCursor ();
 
 #if !TARGET_API_MAC_CARBON
-  arrow_cursor = &qd.arrow;
-
   /* set up some extra stack space for use by emacs */
   SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
 
@@ -7395,6 +8666,7 @@ do_check_ram_size (void)
       exit (1);
     }
 }
+#endif /* MAC_OS8 */
 
 static void
 do_window_update (WindowPtr win)
@@ -7409,40 +8681,30 @@ do_window_update (WindowPtr win)
     {
       if (f->async_visible == 0)
         {
+         /* Update events may occur when a frame gets iconified.  */
+#if 0
           f->async_visible = 1;
           f->async_iconified = 0;
           SET_FRAME_GARBAGED (f);
-
-          /* An update event is equivalent to MapNotify on X, so report
-             visibility changes properly.  */
-          if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
-            /* Force a redisplay sooner or later to update the
-               frame titles in case this is the second frame.  */
-            record_asynch_buffer_change ();
+#endif
         }
       else
-        {
+       {
          Rect r;
-
-          handling_window_update = 1;
-
 #if TARGET_API_MAC_CARBON
-         {
-           RgnHandle region = NewRgn ();
+         RgnHandle region = NewRgn ();
 
-           GetPortVisibleRegion (GetWindowPort (win), region);
-           UpdateControls (win, region);
-           GetRegionBounds (region, &r);
-           DisposeRgn (region);
-         }
+         GetPortVisibleRegion (GetWindowPort (win), region);
+         GetRegionBounds (region, &r);
+         expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
+         UpdateControls (win, region);
+         DisposeRgn (region);
 #else
-         UpdateControls (win, win->visRgn);
          r = (*win->visRgn)->rgnBBox;
-#endif
          expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
-
-          handling_window_update = 0;
-        }
+         UpdateControls (win, win->visRgn);
+#endif
+       }
     }
 
   EndUpdate (win);
@@ -7468,84 +8730,12 @@ static void
 do_app_resume ()
 {
   /* Window-activate events will do the job. */
-#if 0
-  WindowPtr wp;
-  struct frame *f;
-
-  wp = front_emacs_window ();
-  if (wp)
-    {
-      f = mac_window_to_frame (wp);
-
-      if (f)
-       {
-         x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
-         activate_scroll_bars (f);
-       }
-    }
-
-  app_is_suspended = false;
-  app_sleep_time = WNE_SLEEP_AT_RESUME;
-#endif
 }
 
 static void
 do_app_suspend ()
 {
   /* Window-deactivate events will do the job. */
-#if 0
-  WindowPtr wp;
-  struct frame *f;
-
-  wp = front_emacs_window ();
-  if (wp)
-    {
-      f = mac_window_to_frame (wp);
-
-      if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
-       {
-         x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
-         deactivate_scroll_bars (f);
-       }
-    }
-
-  app_is_suspended = true;
-  app_sleep_time = WNE_SLEEP_AT_SUSPEND;
-#endif
-}
-
-
-static void
-do_mouse_moved (mouse_pos, f)
-     Point mouse_pos;
-     FRAME_PTR *f;
-{
-  WindowPtr wp = front_emacs_window ();
-  struct x_display_info *dpyinfo;
-
-  if (wp)
-    {
-      *f = mac_window_to_frame (wp);
-      dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
-
-      if (dpyinfo->mouse_face_hidden)
-       {
-         dpyinfo->mouse_face_hidden = 0;
-         clear_mouse_face (dpyinfo);
-       }
-
-      SetPortWindowPort (wp);
-
-      GlobalToLocal (&mouse_pos);
-
-      if (dpyinfo->grabbed && tracked_scroll_bar)
-       x_scroll_bar_note_movement (tracked_scroll_bar,
-                                   mouse_pos.v
-                                   - XINT (tracked_scroll_bar->top),
-                                   TickCount() * (1000 / 60));
-      else
-       note_mouse_movement (*f, &mouse_pos);
-    }
 }
 
 
@@ -7574,18 +8764,18 @@ do_menu_choice (SInt32 menu_choice)
   menu_id = HiWord (menu_choice);
   menu_item = LoWord (menu_choice);
 
-  if (menu_id == 0)
-    return;
-
   switch (menu_id)
     {
+    case 0:
+      break;
+
     case M_APPLE:
       do_apple_menu (menu_item);
       break;
 
     default:
       {
-        struct frame *f = mac_window_to_frame (front_emacs_window ());
+        struct frame *f = mac_focus_frame (&one_mac_display_info);
         MenuHandle menu = GetMenuHandle (menu_id);
         if (menu)
           {
@@ -7658,41 +8848,41 @@ do_grow_window (WindowPtr w, EventRecord *e)
 static void
 do_zoom_window (WindowPtr w, int zoom_in_or_out)
 {
-  GrafPtr save_port;
   Rect zoom_rect, port_rect;
-  Point top_left;
-  int w_title_height, columns, rows, width, height;
+  int columns, rows, width, height;
   struct frame *f = mac_window_to_frame (w);
-
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
 #if TARGET_API_MAC_CARBON
-  {
-    Point standard_size;
+  Point standard_size;
 
-    standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-    standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
+  standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+  standard_size.v = dpyinfo->height;
 
-    if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
-      zoom_in_or_out = inZoomIn;
-    else
-      {
-       /* Adjust the standard size according to character boundaries.  */
-
-       columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
-       rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
-       standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
-       standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
-       GetWindowBounds (w, kWindowContentRgn, &port_rect);
-       if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
-           && port_rect.left == zoom_rect.left
-           && port_rect.top == zoom_rect.top)
-         zoom_in_or_out = inZoomIn;
-       else
-         zoom_in_or_out = inZoomOut;
-      }
+  if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
+    zoom_in_or_out = inZoomIn;
+  else
+    {
+      /* Adjust the standard size according to character boundaries.  */
 
-    ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
-  }
+      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
+      standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
+      standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+      GetWindowBounds (w, kWindowContentRgn, &port_rect);
+      if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
+         && port_rect.left == zoom_rect.left
+         && port_rect.top == zoom_rect.top)
+       zoom_in_or_out = inZoomIn;
+      else
+       zoom_in_or_out = inZoomOut;
+    }
+
+  ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
 #else /* not TARGET_API_MAC_CARBON */
+  GrafPtr save_port;
+  Point top_left;
+  int w_title_height;
+
   GetPort (&save_port);
 
   SetPortWindowPort (w);
@@ -7725,7 +8915,7 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
        = zoom_rect;
     }
 
-  ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
+  ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
 
   SetPort (save_port);
 #endif /* not TARGET_API_MAC_CARBON */
@@ -7755,176 +8945,112 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   x_real_positions (f, &f->left_pos, &f->top_pos);
 }
 
-/* Intialize AppleEvent dispatcher table for the required events.  */
 void
-init_required_apple_events ()
+mac_store_apple_event (class, id, desc)
+     Lisp_Object class, id;
+     const AEDesc *desc;
 {
-  OSErr err;
-  long result;
+  struct input_event buf;
 
-  /* Make sure we have apple events before starting.  */
-  err = Gestalt (gestaltAppleEventsAttr, &result);
-  if (err != noErr)
-    abort ();
-
-  if (!(result & (1 << gestaltAppleEventsPresent)))
-    abort ();
+  EVENT_INIT (buf);
 
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
-                             NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_open_application),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
-                             NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_open_application),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
+  buf.kind = MAC_APPLE_EVENT;
+  buf.x = class;
+  buf.y = id;
+  XSETFRAME (buf.frame_or_window,
+            mac_focus_frame (&one_mac_display_info));
+  /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
+     is safe to use them during read_socket_hook.  */
+  buf.arg = mac_aedesc_to_lisp (desc);
+  kbd_buffer_store_event (&buf);
+}
 
 #if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
-                              NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_open_documents),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
-                              NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_open_documents),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
+void
+mac_store_drag_event (window, mouse_pos, modifiers, desc)
+     WindowRef window;
+     Point mouse_pos;
+     SInt16 modifiers;
+     const AEDesc *desc;
+{
+  struct input_event buf;
 
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
-                              NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_print_documents),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
-                              NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_print_documents),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
+  EVENT_INIT (buf);
 
-#if TARGET_API_MAC_CARBON
-  err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
-                              NewAEEventHandlerUPP
-                             ((AEEventHandlerProcPtr) do_ae_quit_application),
-                              0L, false);
-#else
-  err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
-                              NewAEEventHandlerProc
-                             ((AEEventHandlerProcPtr) do_ae_quit_application),
-                              0L, false);
-#endif
-  if (err != noErr)
-    abort ();
+  buf.kind = DRAG_N_DROP_EVENT;
+  buf.modifiers = mac_to_emacs_modifiers (modifiers);
+  buf.timestamp = TickCount () * (1000 / 60);
+  XSETINT (buf.x, mouse_pos.h);
+  XSETINT (buf.y, mouse_pos.v);
+  XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
+  buf.arg = mac_aedesc_to_lisp (desc);
+  kbd_buffer_store_event (&buf);
 }
+#endif
 
 #if USE_CARBON_EVENTS
-
-void
-init_service_handler ()
+static pascal OSStatus
+mac_handle_command_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
 {
-  EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
-                          {kEventClassService, kEventServiceCopy},
-                          {kEventClassService, kEventServicePaste}};
-  InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
-                                 3, specs, NULL, NULL);
-}
+  OSStatus result, err;
+  HICommand command;
+  Lisp_Object class_key, id_key, binding;
 
-/*
-   MAC_TODO: Check to see if this is called by AEProcessDesc...
- */
-OSStatus
-mac_handle_service_event (EventHandlerCallRef callRef,
-                         EventRef event, void *data)
-{
-  OSStatus err = noErr;
-  switch (GetEventKind (event))
-    {
-    case kEventServiceGetTypes:
-      {
-       CFMutableArrayRef copyTypes, pasteTypes;
-       CFStringRef type;
-       Boolean selection = true;
-       /*
-         GetEventParameter(event, kEventParamServicePasteTypes,
-         typeCFMutableArrayRef, NULL,
-         sizeof (CFMutableArrayRef), NULL, &pasteTypes);
-       */
-       GetEventParameter(event, kEventParamServiceCopyTypes,
-                         typeCFMutableArrayRef, NULL,
-                         sizeof (CFMutableArrayRef), NULL, &copyTypes);
-       type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
-       if (type) {
-         CFArrayAppendValue (copyTypes, type);
-         //CFArrayAppendValue (pasteTypes, type);
-         CFRelease (type);
-       }
-      }
-    case kEventServiceCopy:
-      {
-       ScrapRef currentScrap, specificScrap;
-       char * buf = "";
-       Size byteCount = 0;
+  result = CallNextEventHandler (next_handler, event);
+  if (result != eventNotHandledErr)
+    return result;
 
-       GetCurrentScrap (&currentScrap);
+  err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
+                          NULL, sizeof (HICommand), NULL, &command);
 
-       err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
-       if (err == noErr)
-         {
-           void *buffer = xmalloc (byteCount);
-           if (buffer != NULL)
-             {
-               GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
-                                  sizeof (ScrapRef), NULL, &specificScrap);
-
-               err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
-                                         &byteCount, buffer);
-               if (err == noErr)
-                 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
-                                 kScrapFlavorMaskNone, byteCount, buffer);
-               xfree (buffer);
-             }
-         }
-       err = noErr;
-      }
-    case kEventServicePaste:
-      {
-       /*
-       // Get the current location
-        Size     byteCount;
-        ScrapRef specificScrap;
-        GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
-                         sizeof(ScrapRef), NULL, &specificScrap);
-        err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
-        if (err == noErr) {
-         void * buffer = xmalloc(byteCount);
-         if (buffer != NULL ) {
-           err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
-                                    &byteCount, buffer);
-           if (err == noErr) {
-             // Actually place in the buffer
-             BLOCK_INPUT;
-             // Get the current "selection" string here
-             UNBLOCK_INPUT;
+  if (err != noErr || command.commandID == 0)
+    return eventNotHandledErr;
+
+  /* A HICommand event is mapped to an Apple event whose event class
+     symbol is `hicommand' and event ID is its command ID.  */
+  class_key = Qhicommand;
+  mac_find_apple_event_spec (0, command.commandID,
+                            &class_key, &id_key, &binding);
+  if (!NILP (binding) && !EQ (binding, Qundefined))
+    {
+      if (INTEGERP (binding))
+       return XINT (binding);
+      else
+       {
+         AppleEvent apple_event;
+         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)
+           {
+             mac_store_apple_event (class_key, id_key, &apple_event);
+             AEDisposeDesc (&apple_event);
+             return noErr;
            }
-         }
-         xfree(buffer);
-        }
-        */
-      }
+       }
     }
-  return err;
+
+  return eventNotHandledErr;
 }
 
+static OSErr
+init_command_handler ()
+{
+  EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
+  static EventHandlerUPP handle_command_eventUPP = NULL;
+
+  if (handle_command_eventUPP == NULL)
+    handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
+  return InstallApplicationEventHandler (handle_command_eventUPP,
+                                        GetEventTypeCount (specs), specs,
+                                        NULL, NULL);
+}
 
 static pascal OSStatus
 mac_handle_window_event (next_handler, event, data)
@@ -7932,15 +9058,15 @@ mac_handle_window_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  extern Lisp_Object Qcontrol;
-
   WindowPtr wp;
-  OSStatus result;
+  OSStatus result, err;
   UInt32 attributes;
   XSizeHints *size_hints;
 
-  GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
-                    NULL, sizeof (WindowPtr), NULL, &wp);
+  err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
+                          NULL, sizeof (WindowPtr), NULL, &wp);
+  if (err != noErr)
+    return eventNotHandledErr;
 
   switch (GetEventKind (event))
     {
@@ -7950,15 +9076,18 @@ mac_handle_window_event (next_handler, event, data)
        return result;
 
       do_window_update (wp);
-      break;
+      return noErr;
 
     case kEventWindowBoundsChanging:
       result = CallNextEventHandler (next_handler, event);
       if (result != eventNotHandledErr)
        return result;
 
-      GetEventParameter (event, kEventParamAttributes, typeUInt32,
-                        NULL, sizeof (UInt32), NULL, &attributes);
+      err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
+                              NULL, sizeof (UInt32), NULL, &attributes);
+      if (err != noErr)
+       break;
+
       size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
       if ((attributes & kWindowBoundsChangeUserResize)
          && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
@@ -7967,9 +9096,12 @@ mac_handle_window_event (next_handler, event, data)
          Rect bounds;
          int width, height;
 
-         GetEventParameter (event, kEventParamCurrentBounds,
-                            typeQDRectangle,
-                            NULL, sizeof (Rect), NULL, &bounds);
+         err = GetEventParameter (event, kEventParamCurrentBounds,
+                                  typeQDRectangle, NULL, sizeof (Rect),
+                                  NULL, &bounds);
+         if (err != noErr)
+           break;
+
          width = bounds.right - bounds.left;
          height = bounds.bottom - bounds.top;
 
@@ -7996,337 +9128,177 @@ mac_handle_window_event (next_handler, event, data)
          return noErr;
        }
       break;
-    }
 
-  return eventNotHandledErr;
-}
-#endif /* USE_CARBON_EVENTS */
-
-
-OSErr
-install_window_handler (window)
-     WindowPtr window;
-{
-  OSErr err = noErr;
-#if USE_CARBON_EVENTS
-  EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowUpdate},
-                          {kEventClassWindow, kEventWindowBoundsChanging}};
-  static EventHandlerUPP handle_window_event_UPP = NULL;
-
-  if (handle_window_event_UPP == NULL)
-    handle_window_event_UPP = NewEventHandlerUPP (mac_handle_window_event);
+    case kEventWindowShown:
+    case kEventWindowHidden:
+    case kEventWindowExpanded:
+    case kEventWindowCollapsed:
+      result = CallNextEventHandler (next_handler, event);
 
-  err = InstallWindowEventHandler (window, handle_window_event_UPP,
-                                  GetEventTypeCount (specs), specs,
-                                  NULL, NULL);
-#endif
-#if TARGET_API_MAC_CARBON
-  if (err == noErr)
-    err = InstallTrackingHandler (mac_do_track_drag, window, NULL);
-  if (err == noErr)
-    err = InstallReceiveHandler (mac_do_receive_drag, window, NULL);
-#endif
-  return err;
-}
+      mac_handle_visibility_change (mac_window_to_frame (wp));
+      return noErr;
 
+      break;
+    }
 
-/* Open Application Apple Event */
-static pascal OSErr
-do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
-{
-  return noErr;
+  return eventNotHandledErr;
 }
 
-
-/* Defined in mac.c.  */
-extern int
-path_from_vol_dir_name (char *, int, short, long, char *);
-
-
-/* Called when we receive an AppleEvent with an ID of
-   "kAEOpenDocuments".  This routine gets the direct parameter,
-   extracts the FSSpecs in it, and puts their names on a list.  */
-#pragma options align=mac68k
-typedef struct SelectionRange {
-  short unused1; // 0 (not used)
-  short lineNum; // line to select (<0 to specify range)
-  long startRange; // start of selection range (if line < 0)
-  long endRange; // end of selection range (if line < 0)
-  long unused2; // 0 (not used)
-  long theDate; // modification date/time
-} SelectionRange;
-#pragma options align=reset
-
-static pascal OSErr
-do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
+static pascal OSStatus
+mac_handle_mouse_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
 {
-  OSErr err, err2;
-  AEDesc the_desc;
-  AEKeyword keyword;
-  DescType actual_type;
-  Size actual_size;
-  SelectionRange position;
-
-  err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
-  if (err != noErr)
-    goto descriptor_error_exit;
-
-  err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
-  if (err == noErr)
-    drag_and_drop_file_list = Fcons (list3 (make_number (position.lineNum + 1),
-                                           make_number (position.startRange + 1),
-                                           make_number (position.endRange + 1)),
-                                    drag_and_drop_file_list);
-
-  /* Check to see that we got all of the required parameters from the
-     event descriptor.  For an 'odoc' event this should just be the
-     file list.  */
-  err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
-                         &actual_type, (Ptr) &keyword,
-                          sizeof (keyword), &actual_size);
-  /* No error means that we found some unused parameters.
-     errAEDescNotFound means that there are no more parameters.  If we
-     get an error code other than that, flag it.  */
-  if ((err == noErr) || (err != errAEDescNotFound))
-    {
-      err = errAEEventNotHandled;
-      goto error_exit;
-    }
-  err = noErr;
-
-  /* Got all the parameters we need.  Now, go through the direct
-     object list and parse it up.  */
-  {
-    long num_files_to_open;
+  OSStatus result, err;
 
-    err = AECountItems (&the_desc, &num_files_to_open);
-    if (err == noErr)
+  switch (GetEventKind (event))
+    {
+    case kEventMouseWheelMoved:
       {
-        int i;
+       WindowPtr wp;
+       struct frame *f;
+       EventMouseWheelAxis axis;
+       SInt32 delta;
+       Point point;
+
+       result = CallNextEventHandler (next_handler, event);
+       if (result != eventNotHandledErr || read_socket_inev == NULL)
+         return result;
+
+       err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
+                                NULL, sizeof (WindowRef), NULL, &wp);
+       if (err != noErr)
+         break;
 
-        /* AE file list is one based so just use that for indexing here.  */
-        for (i = 1; i <= num_files_to_open; i++)
-         {
-#ifdef MAC_OSX
-           FSRef fref;
-           char unix_path_name[MAXPATHLEN];
+       f = mac_window_to_frame (wp);
+       if (f != mac_focus_frame (&one_mac_display_info))
+         break;
 
-           err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
-                              &actual_type, &fref, sizeof (FSRef),
-                              &actual_size);
-           if (err != noErr || actual_type != typeFSRef)
-             continue;
+       err = GetEventParameter (event, kEventParamMouseWheelAxis,
+                                typeMouseWheelAxis, NULL,
+                                sizeof (EventMouseWheelAxis), NULL, &axis);
+       if (err != noErr || axis != kEventMouseWheelAxisY)
+         break;
 
-           if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
-               == noErr)
-#else
-           FSSpec fs;
-           Str255 path_name, unix_path_name;
-
-           err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
-                             (Ptr) &fs, sizeof (fs), &actual_size);
-           if (err != noErr) continue;
-
-           if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
-                                       fs.name) &&
-               mac_to_posix_pathname (path_name, unix_path_name, 255))
-#endif
-             /* x-dnd functions expect undecoded filenames.  */
-             drag_and_drop_file_list =
-               Fcons (make_unibyte_string (unix_path_name,
-                                           strlen (unix_path_name)),
-                      drag_and_drop_file_list);
-         }
+       err = GetEventParameter (event, kEventParamMouseWheelDelta,
+                                typeSInt32, NULL, sizeof (SInt32),
+                                NULL, &delta);
+       if (err != noErr)
+         break;
+       err = GetEventParameter (event, kEventParamMouseLocation,
+                                typeQDPoint, NULL, sizeof (Point),
+                                NULL, &point);
+       if (err != noErr)
+         break;
+       read_socket_inev->kind = WHEEL_EVENT;
+       read_socket_inev->code = 0;
+       read_socket_inev->modifiers =
+         (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;
       }
-  }
-
-error_exit:
-  /* Nuke the coerced file list in any case */
-  err2 = AEDisposeDesc(&the_desc);
-
-descriptor_error_exit:
-  /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
-  return err;
-}
-
-
-#if TARGET_API_MAC_CARBON
-static pascal OSErr
-mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
-                  void *handlerRefCon, DragReference theDrag)
-{
-  static int can_accept;
-  short items;
-  short index;
-  ItemReference theItem;
-  FlavorFlags theFlags;
-  OSErr result;
-
-  if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
-    return dragNotAcceptedErr;
-
-  switch (message)
-    {
-    case kDragTrackingEnterHandler:
-      CountDragItems (theDrag, &items);
-      can_accept = 0;
-      for (index = 1; index <= items; index++)
-       {
-         GetDragItemReferenceNumber (theDrag, index, &theItem);
-         result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
-         if (result == noErr)
-           {
-             can_accept = 1;
-             break;
-           }
-       }
-      break;
-
-    case kDragTrackingEnterWindow:
-      if (can_accept)
-       {
-         RgnHandle hilite_rgn = NewRgn ();
-         Rect r;
-         struct frame *f = mac_window_to_frame (window);
-
-         mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
-         GetWindowPortBounds (window, &r);
-         OffsetRect (&r, -r.left, -r.top);
-         RectRgn (hilite_rgn, &r);
-         ShowDragHilite (theDrag, hilite_rgn, true);
-         DisposeRgn (hilite_rgn);
-         SetThemeCursor (kThemeCopyArrowCursor);
-       }
-      break;
-
-    case kDragTrackingInWindow:
-      break;
-
-    case kDragTrackingLeaveWindow:
-      if (can_accept)
-       {
-         struct frame *f = mac_window_to_frame (window);
-
-         mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
-         HideDragHilite (theDrag);
-         SetThemeCursor (kThemeArrowCursor);
-       }
       break;
 
-    case kDragTrackingLeaveHandler:
+    default:
       break;
     }
 
-  return noErr;
+  return eventNotHandledErr;
 }
 
-static pascal OSErr
-mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
-                    DragReference theDrag)
+#ifdef MAC_OSX
+OSErr
+mac_store_services_event (event)
+     EventRef event;
 {
-  short items;
-  short index;
-  FlavorFlags theFlags;
-  Point mouse;
-  OSErr result;
-  ItemReference theItem;
-  HFSFlavor data;
-  Size size = sizeof (HFSFlavor);
-
-  if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
-    return dragNotAcceptedErr;
+  OSErr err;
+  AppleEvent apple_event;
+  Lisp_Object id_key;
 
-  drag_and_drop_file_list = Qnil;
-  GetDragMouse (theDrag, &mouse, 0L);
-  CountDragItems (theDrag, &items);
-  for (index = 1; index <= items; index++)
+  switch (GetEventKind (event))
     {
-      /* Only handle file references.  */
-      GetDragItemReferenceNumber (theDrag, index, &theItem);
-      result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
-      if (result == noErr)
-       {
-#ifdef MAC_OSX
-         FSRef fref;
-         char unix_path_name[MAXPATHLEN];
-#else
-         Str255 path_name, unix_path_name;
-#endif
-         GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
-#ifdef MAC_OSX
-         /* Use Carbon routines, otherwise it converts the file name
-            to /Macintosh HD/..., which is not correct. */
-         FSpMakeFSRef (&data.fileSpec, &fref);
-         if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
-#else
-         if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
-                                     data.fileSpec.parID, data.fileSpec.name) &&
-             mac_to_posix_pathname (path_name, unix_path_name, 255))
-#endif
-           /* x-dnd functions expect undecoded filenames.  */
-            drag_and_drop_file_list =
-             Fcons (make_unibyte_string (unix_path_name,
-                                         strlen (unix_path_name)),
-                    drag_and_drop_file_list);
-       }
-    }
-  /* If there are items in the list, construct an event and post it to
-     the queue like an interrupt using kbd_buffer_store_event.  */
-  if (!NILP (drag_and_drop_file_list))
-    {
-      struct input_event event;
-      Lisp_Object frame;
-      struct frame *f = mac_window_to_frame (window);
-      SInt16 modifiers;
-
-      GlobalToLocal (&mouse);
-      GetDragModifiers (theDrag, NULL, NULL, &modifiers);
-
-      event.kind = DRAG_N_DROP_EVENT;
-      event.code = 0;
-      event.modifiers = mac_to_emacs_modifiers (modifiers);
-      event.timestamp = TickCount () * (1000 / 60);
-      XSETINT (event.x, mouse.h);
-      XSETINT (event.y, mouse.v);
-      XSETFRAME (frame, f);
-      event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
-      event.arg = Qnil;
-      /* Post to the interrupt queue */
-      kbd_buffer_store_event (&event);
-      /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
+    case kEventServicePaste:
+      id_key = Qpaste;
+      err = create_apple_event_from_event_ref (event, 0, NULL, NULL,
+                                              &apple_event);
+      break;
+
+    case kEventServicePerform:
       {
-       ProcessSerialNumber psn;
-       GetCurrentProcess (&psn);
-       SetFrontProcess (&psn);
+       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;
 
-      return noErr;
+    default:
+      abort ();
     }
-  else
-    return dragNotAcceptedErr;
-}
-#endif
 
+  if (err == noErr)
+    {
+      mac_store_apple_event (Qservices, id_key, &apple_event);
+      AEDisposeDesc (&apple_event);
+    }
 
-/* Print Document Apple Event */
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
-{
-  return errAEEventNotHandled;
+  return err;
 }
+#endif /* MAC_OSX */
+#endif /* USE_CARBON_EVENTS */
 
 
-static pascal OSErr
-do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
+OSErr
+install_window_handler (window)
+     WindowPtr window;
 {
-  /* FixMe: Do we need an unwind-protect or something here?  And what
-     do we do about unsaved files. Currently just forces quit rather
-     than doing recursive callback to get user input.  */
+  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);
+  if (err == noErr)
+    err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
+                                    GetEventTypeCount (specs_mouse),
+                                    specs_mouse, NULL, NULL);
+#endif
+  if (err == noErr)
+    err = install_drag_handler (window);
 
-  terminate_flag = true;
+  return err;
+}
 
-  /* Fkill_emacs doesn't return.  We have to return. (TI) */
-  return noErr;
+void
+remove_window_handler (window)
+     WindowPtr window;
+{
+  remove_drag_handler (window);
 }
 
 
@@ -8340,25 +9312,20 @@ profiler_exit_proc ()
 #endif
 
 /* These few functions implement Emacs as a normal Mac application
-   (almost): set up the heap and the Toolbox, handle necessary
-   system events plus a few simple menu events.  They also set up
-   Emacs's access to functions defined in the rest of this file.
-   Emacs uses function hooks to perform all its terminal I/O.  A
-   complete list of these functions appear in termhooks.h.  For what
-   they do, read the comments there and see also w32term.c and
-   xterm.c.  What's noticeably missing here is the event loop, which
-   is normally present in most Mac application.  After performing the
-   necessary Mac initializations, main passes off control to
-   emacs_main (corresponding to main in emacs.c).  Emacs_main calls
-   mac_read_socket (defined further below) to read input.  This is
-   where WaitNextEvent is called to process Mac events.  This is also
-   where check_alarm in sysdep.c is called to simulate alarm signals.
-   This makes the cursor jump back to its correct position after
-   briefly jumping to that of the matching parenthesis, print useful
-   hints and prompts in the minibuffer after the user stops typing for
-   a wait, etc.  */
+   (almost): set up the heap and the Toolbox, handle necessary system
+   events plus a few simple menu events.  They also set up Emacs's
+   access to functions defined in the rest of this file.  Emacs uses
+   function hooks to perform all its terminal I/O.  A complete list of
+   these functions appear in termhooks.h.  For what they do, read the
+   comments there and see also w32term.c and xterm.c.  What's
+   noticeably missing here is the event loop, which is normally
+   present in most Mac application.  After performing the necessary
+   Mac initializations, main passes off control to emacs_main
+   (corresponding to main in emacs.c).  Emacs_main calls XTread_socket
+   (defined further below) to read input.  This is where
+   WaitNextEvent/ReceiveNextEvent is called to process Mac events.  */
 
-#if !TARGET_API_MAC_CARBON
+#ifdef MAC_OS8
 #undef main
 int
 main (void)
@@ -8386,9 +9353,11 @@ main (void)
 
   init_environ ();
 
+  init_coercion_handler ();
+
   initialize_applescript ();
 
-  init_required_apple_events ();
+  init_apple_event_handler ();
 
   {
     char **argv;
@@ -8416,19 +9385,23 @@ main (void)
 #endif
 
 /* Table for translating Mac keycode to X keysym values.  Contributed
-   by Sudhir Shenoy.  */
+   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*/ 0, 0x1b /*escape*/, 0, 0,
+  /*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, 0x7f /*kp-clear*/,
+  /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
   /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
   /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
 
@@ -8440,14 +9413,15 @@ static unsigned char keycode_to_xkeysym_table[] = {
   /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
   /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
   /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
-  /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
+  /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
 
-  /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
-  /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
-  /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
+  /*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)
 {
@@ -8455,6 +9429,124 @@ keycode_to_xkeysym (int keyCode, int *xKeySym)
   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
 static RgnHandle mouse_region = NULL;
 
@@ -8472,27 +9564,62 @@ mac_wait_next_event (er, sleep_time, dequeue)
     mouse_region = NewRgn ();
 
   event_mask = everyEvent;
-  if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
+  if (!mac_ready_for_apple_events)
     event_mask -= highLevelEventMask;
 
   current_tick = TickCount ();
   target_tick = current_tick + sleep_time;
 
-  if (er_buf.what == nullEvent)
-    while (!WaitNextEvent (event_mask, &er_buf,
-                          target_tick - current_tick, mouse_region))
-      {
-       current_tick = TickCount ();
-       if (target_tick <= current_tick)
-         return false;
-      }
+  if (er_buf.what == nullEvent)
+    while (!WaitNextEvent (event_mask, &er_buf,
+                          target_tick - current_tick, mouse_region))
+      {
+       current_tick = TickCount ();
+       if (target_tick <= current_tick)
+         return false;
+      }
+
+  *er = er_buf;
+  if (dequeue)
+    er_buf.what = nullEvent;
+  return true;
+}
+#endif /* not USE_CARBON_EVENTS */
+
+#if TARGET_API_MAC_CARBON
+OSStatus
+mac_post_mouse_moved_event ()
+{
+  EventRef event = NULL;
+  OSStatus err;
+
+  err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
+                    kEventAttributeNone, &event);
+  if (err == noErr)
+    {
+      Point mouse_pos;
+
+      GetMouse (&mouse_pos);
+      LocalToGlobal (&mouse_pos);
+      err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
+                              sizeof (Point), &mouse_pos);
+    }
+  if (err == noErr)
+    {
+      UInt32 modifiers = GetCurrentKeyModifiers ();
+
+      err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
+                              sizeof (UInt32), &modifiers);
+    }
+  if (err == noErr)
+    err = PostEventToQueue (GetCurrentEventQueue (), event,
+                           kEventPriorityStandard);
+  if (event)
+    ReleaseEvent (event);
 
-  *er = er_buf;
-  if (dequeue)
-    er_buf.what = nullEvent;
-  return true;
+  return err;
 }
-#endif /* not USE_CARBON_EVENTS */
+#endif
 
 /* Emacs calls this whenever it wants to read an input event from the
    user. */
@@ -8522,24 +9649,16 @@ XTread_socket (sd, expected, hold_quit)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  /* Don't poll for events to process (specifically updateEvt) if
-     window update currently already in progress.  A call to redisplay
-     (in do_window_update) can be preempted by another call to
-     redisplay, causing blank regions to be left on the screen and the
-     cursor to be left at strange places.  */
-  if (handling_window_update)
-    {
-      UNBLOCK_INPUT;
-      return 0;
-    }
-
-  if (terminate_flag)
-    Fkill_emacs (make_number (1));
+  ++handling_signal;
 
 #if USE_CARBON_EVENTS
   toolbox_dispatcher = GetEventDispatcherTarget ();
 
-  while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
+  while (
+#if USE_CG_DRAWING
+        mac_prepare_for_quickdraw (NULL),
+#endif
+        !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
                            kEventRemoveFromQueue, &eventRef))
 #else /* !USE_CARBON_EVENTS */
   while (mac_wait_next_event (&er, 0, true))
@@ -8547,6 +9666,7 @@ XTread_socket (sd, expected, hold_quit)
     {
       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
@@ -8556,65 +9676,28 @@ XTread_socket (sd, expected, hold_quit)
       inev.kind = NO_EVENT;
       inev.arg = Qnil;
 
+#if USE_CARBON_EVENTS
+      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))
-       switch (GetEventClass (eventRef))
-         {
-         case kEventClassWindow:
-           if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
-             {
-               WindowPtr window_ptr;
-               GetEventParameter(eventRef, kEventParamDirectObject,
-                                 typeWindowRef, NULL, sizeof(WindowPtr),
-                                 NULL, &window_ptr);
-               f = mac_window_to_frame (window_ptr);
-               if (f && !f->async_iconified)
-                 x_real_positions (f, &f->left_pos, &f->top_pos);
-               SendEventToEventTarget (eventRef, toolbox_dispatcher);
-             }
-           break;
-         case kEventClassMouse:
-           if (GetEventKind (eventRef) == kEventMouseWheelMoved)
-             {
-               SInt32 delta;
-               Point point;
-               WindowPtr window_ptr = front_emacs_window ();
-
-               if (!IsValidWindowPtr (window_ptr))
-                 {
-                   SysBeep(1);
-                   break;
-                 }
-
-               GetEventParameter(eventRef, kEventParamMouseWheelDelta,
-                                 typeSInt32, NULL, sizeof (SInt32),
-                                 NULL, &delta);
-               GetEventParameter(eventRef, kEventParamMouseLocation,
-                                 typeQDPoint, NULL, sizeof (Point),
-                                 NULL, &point);
-               inev.kind = WHEEL_EVENT;
-               inev.code = 0;
-               inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
-                                 | ((delta < 0) ? down_modifier
-                                    : up_modifier));
-               SetPortWindowPort (window_ptr);
-               GlobalToLocal (&point);
-               XSETINT (inev.x, point.h);
-               XSETINT (inev.y, point.v);
-               XSETFRAME (inev.frame_or_window,
-                          mac_window_to_frame (window_ptr));
-               inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
-             }
-           else
-             SendEventToEventTarget (eventRef, toolbox_dispatcher);
-
-           break;
-
-         default:
-           /* Send the event to the appropriate receiver.  */
-           SendEventToEventTarget (eventRef, toolbox_dispatcher);
-         }
+       {
+         /* 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 */
       switch (er.what)
@@ -8623,7 +9706,7 @@ XTread_socket (sd, expected, hold_quit)
        case mouseUp:
          {
            WindowPtr window_ptr;
-           SInt16 part_code;
+           ControlPartCode part_code;
            int tool_bar_p = 0;
 
 #if USE_CARBON_EVENTS
@@ -8633,6 +9716,7 @@ XTread_socket (sd, expected, hold_quit)
                != eventNotHandledErr)
              break;
 #endif
+           last_mouse_glyph_frame = 0;
 
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
@@ -8650,26 +9734,30 @@ XTread_socket (sd, expected, hold_quit)
                  }
              }
 
-           if (er.what != mouseDown && part_code != inContent)
+           if (er.what != mouseDown &&
+               (part_code != inContent || dpyinfo->grabbed == 0))
              break;
 
            switch (part_code)
              {
              case inMenuBar:
-               f = mac_window_to_frame (front_emacs_window ());
+               f = mac_focus_frame (dpyinfo);
                saved_menu_event_location = er.where;
                inev.kind = MENU_BAR_ACTIVATE_EVENT;
                XSETFRAME (inev.frame_or_window, f);
                break;
 
              case inContent:
-               if (window_ptr != front_emacs_window ())
+               if (window_ptr != FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo)))
                  SelectWindow (window_ptr);
                else
                  {
-                   SInt16 control_part_code;
+                   ControlPartCode control_part_code;
                    ControlHandle ch;
                    Point mouse_loc = er.where;
+#ifdef MAC_OSX
+                   ControlKind control_kind;
+#endif
 
                    f = mac_window_to_frame (window_ptr);
                    /* convert to local coordinates of new window */
@@ -8679,6 +9767,10 @@ XTread_socket (sd, expected, hold_quit)
 #if TARGET_API_MAC_CARBON
                    ch = FindControlUnderMouse (mouse_loc, window_ptr,
                                                &control_part_code);
+#ifdef MAC_OSX
+                   if (ch)
+                     GetControlKind (ch, &control_kind);
+#endif
 #else
                    control_part_code = FindControl (mouse_loc, window_ptr,
                                                     &ch);
@@ -8693,26 +9785,43 @@ XTread_socket (sd, expected, hold_quit)
 #endif
                    XSETINT (inev.x, mouse_loc.h);
                    XSETINT (inev.y, mouse_loc.v);
-                   inev.timestamp = er.when * (1000 / 60);
-                   /* ticks to milliseconds */
 
-                   if (dpyinfo->grabbed && tracked_scroll_bar
-#if TARGET_API_MAC_CARBON
-                       || ch != 0
-#else
-                       || control_part_code != 0
-#endif
-                       )
+                   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
+#else  /* USE_TOOLKIT_SCROLL_BARS */
+#ifdef MAC_OSX
+                           && control_kind.kind == kControlKindScrollBar
+#endif /* MAC_OSX */
+#endif /* USE_TOOLKIT_SCROLL_BARS */
+                           ))
                      {
                        struct scroll_bar *bar;
 
                        if (dpyinfo->grabbed && tracked_scroll_bar)
                          {
                            bar = tracked_scroll_bar;
+#ifndef USE_TOOLKIT_SCROLL_BARS
                            control_part_code = kControlIndicatorPart;
+#endif
                          }
                        else
                          bar = (struct scroll_bar *) GetControlReference (ch);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+                       /* Make the "Ctrl-Mouse-2 splits window" work
+                          for toolkit scroll bars.  */
+                       if (er.modifiers & controlKey)
+                         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);
+                       else
+                         x_scroll_bar_handle_release (bar, &inev);
+#else  /* not USE_TOOLKIT_SCROLL_BARS */
                        x_scroll_bar_handle_click (bar, control_part_code,
                                                   &er, &inev);
                        if (er.what == mouseDown
@@ -8720,6 +9829,7 @@ XTread_socket (sd, expected, hold_quit)
                          tracked_scroll_bar = bar;
                        else
                          tracked_scroll_bar = NULL;
+#endif  /* not USE_TOOLKIT_SCROLL_BARS */
                      }
                    else
                      {
@@ -8748,12 +9858,6 @@ XTread_socket (sd, expected, hold_quit)
                      {
                        dpyinfo->grabbed |= (1 << inev.code);
                        last_mouse_frame = f;
-                       /* Ignore any mouse motion that happened
-                          before this event; any subsequent
-                          mouse-movement Emacs events should reflect
-                          only motion after the ButtonPress.  */
-                       if (f != 0)
-                         f->mouse_moved = 0;
 
                        if (!tool_bar_p)
                          last_tool_bar_item = -1;
@@ -8769,20 +9873,40 @@ XTread_socket (sd, expected, hold_quit)
                          dpyinfo->grabbed &= ~(1 << inev.code);
                      }
 
-                   switch (er.what)
-                     {
-                     case mouseDown:
-                       inev.modifiers |= down_modifier;
-                       break;
-                     case mouseUp:
-                       inev.modifiers |= up_modifier;
-                       break;
-                     }
+                   /* Ignore any mouse motion that happened before
+                      this event; any subsequent mouse-movement Emacs
+                      events should reflect only motion after the
+                      ButtonPress.  */
+                   if (f != 0)
+                     f->mouse_moved = 0;
+
+#ifdef USE_TOOLKIT_SCROLL_BARS
+                   if (inev.kind == MOUSE_CLICK_EVENT)
+#endif
+                     switch (er.what)
+                       {
+                       case mouseDown:
+                         inev.modifiers |= down_modifier;
+                         break;
+                       case mouseUp:
+                         inev.modifiers |= up_modifier;
+                         break;
+                       }
                  }
                break;
 
              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);
@@ -8854,10 +9978,69 @@ XTread_socket (sd, expected, hold_quit)
                          er.where.h + 1, er.where.v + 1);
 #endif
              previous_help_echo_string = help_echo_string;
-             help_echo_string = help_echo_object = help_echo_window = Qnil;
-             help_echo_pos = -1;
+             help_echo_string = Qnil;
+
+             if (dpyinfo->grabbed && last_mouse_frame
+                 && FRAME_LIVE_P (last_mouse_frame))
+               f = last_mouse_frame;
+             else
+               f = dpyinfo->x_focus_frame;
+
+             if (dpyinfo->mouse_face_hidden)
+               {
+                 dpyinfo->mouse_face_hidden = 0;
+                 clear_mouse_face (dpyinfo);
+               }
 
-             do_mouse_moved (er.where, &f);
+             if (f)
+               {
+                 WindowPtr wp = FRAME_MAC_WINDOW (f);
+                 Point mouse_pos = er.where;
+
+                 SetPortWindowPort (wp);
+
+                 GlobalToLocal (&mouse_pos);
+
+                 if (dpyinfo->grabbed && tracked_scroll_bar)
+#ifdef USE_TOOLKIT_SCROLL_BARS
+                   x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
+                                             mouse_pos, &inev);
+#else /* not USE_TOOLKIT_SCROLL_BARS */
+                   x_scroll_bar_note_movement (tracked_scroll_bar,
+                                               mouse_pos.v
+                                               - XINT (tracked_scroll_bar->top),
+                                               er.when * (1000 / 60));
+#endif /* not USE_TOOLKIT_SCROLL_BARS */
+                 else
+                   {
+                     /* Generate SELECT_WINDOW_EVENTs when needed.  */
+                     if (mouse_autoselect_window)
+                       {
+                         Lisp_Object window;
+
+                         window = window_from_coordinates (f,
+                                                           mouse_pos.h,
+                                                           mouse_pos.v,
+                                                           0, 0, 0, 0);
+
+                         /* Window will be selected only when it is
+                            not selected now and last mouse movement
+                            event was not in it.  Minibuffer window
+                            will be selected iff it is active.  */
+                         if (WINDOWP (window)
+                             && !EQ (window, last_window)
+                             && !EQ (window, selected_window))
+                           {
+                             inev.kind = SELECT_WINDOW_EVENT;
+                             inev.frame_or_window = window;
+                           }
+
+                         last_window=window;
+                       }
+                     if (!note_mouse_movement (f, &mouse_pos))
+                       help_echo_string = previous_help_echo_string;
+                   }
+               }
 
              /* If the contents of the global variable
                 help_echo_string has changed, generate a
@@ -8886,15 +10069,12 @@ XTread_socket (sd, expected, hold_quit)
            if (!is_emacs_window (window_ptr))
              break;
 
-           f = mac_window_to_frame (window_ptr);
-
            if ((er.modifiers & activeFlag) != 0)
              {
                /* A window has been activated */
                Point mouse_loc = er.where;
 
-               x_new_focus_frame (dpyinfo, f);
-               activate_scroll_bars (f);
+               x_detect_focus_change (dpyinfo, &er, &inev);
 
                SetPortWindowPort (window_ptr);
                GlobalToLocal (&mouse_loc);
@@ -8906,15 +10086,27 @@ XTread_socket (sd, expected, hold_quit)
            else
              {
                /* A window has been deactivated */
-               dpyinfo->grabbed = 0;
-
-               if (f == dpyinfo->x_focus_frame)
+#if USE_TOOLKIT_SCROLL_BARS
+               if (dpyinfo->grabbed && tracked_scroll_bar)
                  {
-                   x_new_focus_frame (dpyinfo, 0);
-                   deactivate_scroll_bars (f);
+                   struct input_event event;
+
+                   EVENT_INIT (event);
+                   event.kind = NO_EVENT;
+                   x_scroll_bar_handle_release (tracked_scroll_bar, &event);
+                   if (event.kind != NO_EVENT)
+                     {
+                       event.timestamp = timestamp;
+                       kbd_buffer_store_event_hold (&event, hold_quit);
+                       count++;
+                     }
                  }
+#endif
+               dpyinfo->grabbed = 0;
 
+               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
@@ -8940,211 +10132,110 @@ XTread_socket (sd, expected, hold_quit)
            int keycode = (er.message & keyCodeMask) >> 8;
            int xkeysym;
 
-#if USE_CARBON_EVENTS
+#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 ((!NILP (Vmac_pass_command_to_system)
+           if ((mac_pass_command_to_system
                 || !(er.modifiers & cmdKey))
-               && (!NILP (Vmac_pass_control_to_system)
-                   || !(er.modifiers & controlKey)))
+               && (mac_pass_control_to_system
+                   || !(er.modifiers & controlKey))
+               && (NILP (Vmac_option_modifier)
+                   || !(er.modifiers & optionKey)))
              if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
                  != eventNotHandledErr)
                break;
 #endif
 
-#if TARGET_API_MAC_CARBON
-           if (!IsValidWindowPtr (front_emacs_window ()))
+#if 0
+           if (dpyinfo->x_focus_frame == NULL)
              {
+               /* Beep if keyboard input occurs when all the frames
+                  are invisible.  */
                SysBeep (1);
                break;
              }
 #endif
 
+           {
+             static SInt16 last_key_script = -1;
+             SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
+
+             if (last_key_script != current_key_script)
+               {
+                 struct input_event event;
+
+                 EVENT_INIT (event);
+                 event.kind = LANGUAGE_CHANGE_EVENT;
+                 event.arg = Qnil;
+                 event.code = current_key_script;
+                 event.timestamp = timestamp;
+                 kbd_buffer_store_event (&event);
+                 count++;
+               }
+             last_key_script = current_key_script;
+           }
+
            ObscureCursor ();
 
-           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+           f = mac_focus_frame (dpyinfo);
+
+           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+               && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
              {
                clear_mouse_face (dpyinfo);
                dpyinfo->mouse_face_hidden = 1;
              }
 
-           if (keycode_to_xkeysym (keycode, &xkeysym))
-             {
-               inev.code = 0xff00 | xkeysym;
-               inev.kind = NON_ASCII_KEYSTROKE_EVENT;
-             }
-           else
+           /* 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))
              {
-               if (er.modifiers & (controlKey |
-                                   (NILP (Vmac_command_key_is_meta) ? optionKey
-                                    : cmdKey)))
-                 {
-                   /* 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 */
-                   int new_modifiers = er.modifiers & 0xe600;
-                   /* mask off option and command */
-                   int new_keycode = keycode | new_modifiers;
-                   Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-                   unsigned long some_state = 0;
-                   inev.code = KeyTranslate (kchr_ptr, new_keycode,
-                                             &some_state) & 0xff;
-                 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
-            {
-                /* When using the option key as an emacs modifier, convert
-                   the pressed key code back to one without the Mac option
-                   modifier applied. */
-                int new_modifiers = er.modifiers & ~optionKey;
-                int new_keycode = keycode | new_modifiers;
-                Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-                unsigned long some_state = 0;
-                inev.code = KeyTranslate (kchr_ptr, new_keycode,
-                                          &some_state) & 0xff;
-            }
-               else
-                 inev.code = er.message & charCodeMask;
+               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;
              }
-         }
-
-         /* If variable mac-convert-keyboard-input-to-latin-1 is
-            non-nil, convert non-ASCII characters typed at the Mac
-            keyboard (presumed to be in the Mac Roman encoding) to
-            iso-latin-1 encoding before they are passed to Emacs.
-            This enables the Mac keyboard to be used to enter
-            non-ASCII iso-latin-1 characters directly.  */
-         if (mac_keyboard_text_encoding != kTextEncodingMacRoman
-             && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
-           {
-             static TECObjectRef converter = NULL;
-             OSStatus the_err = noErr;
-             OSStatus convert_status = noErr;
-
-             if (converter ==  NULL)
-               {
-                 the_err = TECCreateConverter (&converter,
-                                               kTextEncodingMacRoman,
-                                               mac_keyboard_text_encoding);
-                 current_mac_keyboard_text_encoding
-                   = mac_keyboard_text_encoding;
-               }
-             else if (mac_keyboard_text_encoding
-                      != current_mac_keyboard_text_encoding)
+           else
+#endif
+             if (keycode_to_xkeysym (keycode, &xkeysym))
                {
-                 /* Free the converter for the current encoding
-                    before creating a new one.  */
-                 TECDisposeConverter (converter);
-                 the_err = TECCreateConverter (&converter,
-                                               kTextEncodingMacRoman,
-                                               mac_keyboard_text_encoding);
-                 current_mac_keyboard_text_encoding
-                   = mac_keyboard_text_encoding;
+                 inev.code = 0xff00 | xkeysym;
+                 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
                }
-
-             if (the_err == noErr)
+             else
                {
-                 unsigned char ch = inev.code;
-                 ByteCount actual_input_length, actual_output_length;
-                 unsigned char outbuf[32];
-
-                 convert_status = TECConvertText (converter, &ch, 1,
-                                                  &actual_input_length,
-                                                  outbuf, 1,
-                                                  &actual_output_length);
-                 if (convert_status == noErr
-                     && actual_input_length == 1
-                     && actual_output_length == 1)
-                   inev.code = *outbuf;
-
-                 /* Reset internal states of the converter object.
-                    If it fails, create another one. */
-                 convert_status = TECFlushText (converter, outbuf,
-                                                sizeof (outbuf),
-                                                &actual_output_length);
-                 if (convert_status != noErr)
-                   {
-                     TECDisposeConverter (converter);
-                     TECCreateConverter (&converter,
-                                         kTextEncodingMacRoman,
-                                         mac_keyboard_text_encoding);
-                   }
+                 inev.code =
+                   backtranslate_modified_keycode(er.modifiers, keycode,
+                                                  er.message & charCodeMask);
+                 inev.kind = ASCII_KEYSTROKE_EVENT;
                }
-           }
+         }
 
 #if USE_CARBON_EVENTS
          inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
          inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
-         XSETFRAME (inev.frame_or_window,
-                    mac_window_to_frame (front_emacs_window ()));
-         inev.timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
+         inev.modifiers |= (extra_keyboard_modifiers
+                            & (meta_modifier | alt_modifier
+                               | hyper_modifier | super_modifier));
+         XSETFRAME (inev.frame_or_window, f);
          break;
 
        case kHighLevelEvent:
-         drag_and_drop_file_list = Qnil;
-
-         AEProcessAppleEvent(&er);
-
-         /* Build a DRAG_N_DROP_EVENT type event as is done in
-            constuct_drag_n_drop in w32term.c.  */
-         if (!NILP (drag_and_drop_file_list))
-           {
-             struct frame *f = NULL;
-             WindowPtr wp;
-             Lisp_Object frame;
-
-             wp = front_emacs_window ();
-
-             if (!wp)
-               {
-                 struct frame *f = XFRAME (XCAR (Vframe_list));
-                 CollapseWindow (FRAME_MAC_WINDOW (f), false);
-                 wp = front_emacs_window ();
-               }
-
-             if (wp)
-               f = mac_window_to_frame (wp);
-
-             inev.kind = DRAG_N_DROP_EVENT;
-             inev.code = 0;
-             inev.timestamp = er.when * (1000 / 60);
-             /* ticks to milliseconds */
-#if USE_CARBON_EVENTS
-             inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-             inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
-#endif
-
-             XSETINT (inev.x, 0);
-             XSETINT (inev.y, 0);
-
-             XSETFRAME (frame, f);
-             inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
-
-             /* Regardless of whether Emacs was suspended or in the
-                foreground, ask it to redraw its entire screen.
-                Otherwise parts of the screen can be left in an
-                inconsistent state.  */
-             if (wp)
-#if TARGET_API_MAC_CARBON
-               {
-                 Rect r;
+         read_socket_inev = &inev;
+         AEProcessAppleEvent (&er);
+         read_socket_inev = NULL;
+         break;
 
-                 GetWindowPortBounds (wp, &r);
-                 InvalWindowRect (wp, &r);
-               }
-#else /* not TARGET_API_MAC_CARBON */
-                InvalRect (&(wp->portRect));
-#endif /* not TARGET_API_MAC_CARBON */
-           }
        default:
          break;
        }
@@ -9154,6 +10245,7 @@ XTread_socket (sd, expected, hold_quit)
 
       if (inev.kind != NO_EVENT)
        {
+         inev.timestamp = timestamp;
          kbd_buffer_store_event_hold (&inev, hold_quit);
          count++;
        }
@@ -9193,10 +10285,30 @@ XTread_socket (sd, expected, hold_quit)
       pending_autoraise_frame = 0;
     }
 
-#if !TARGET_API_MAC_CARBON
-  check_alarm ();  /* simulate the handling of a SIGALRM */
+#if !USE_CARBON_EVENTS
+  /* 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,
+     not in all cases).  */
+  {
+    Lisp_Object tail, frame;
+
+    FOR_EACH_FRAME (tail, frame)
+      {
+       struct frame *f = XFRAME (frame);
+
+       /* The tooltip has been drawn already.  Avoid the
+          SET_FRAME_GARBAGED in mac_handle_visibility_change.  */
+       if (EQ (frame, tip_frame))
+         continue;
+
+       if (FRAME_MAC_P (f))
+         mac_handle_visibility_change (f);
+      }
+  }
 #endif
 
+  --handling_signal;
   UNBLOCK_INPUT;
   return count;
 }
@@ -9249,12 +10361,12 @@ make_mac_terminal_frame (struct frame *f)
   f->output_data.mac->mouse_pixel = 0xff00ff;
   f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
 
-  f->output_data.mac->text_cursor = GetCursor (iBeamCursor);
-  f->output_data.mac->nontext_cursor = &arrow_cursor;
-  f->output_data.mac->modeline_cursor = &arrow_cursor;
-  f->output_data.mac->hand_cursor = &arrow_cursor;
-  f->output_data.mac->hourglass_cursor = GetCursor (watchCursor);
-  f->output_data.mac->horizontal_drag_cursor = &arrow_cursor;
+  f->output_data.mac->text_cursor = kThemeIBeamCursor;
+  f->output_data.mac->nontext_cursor = kThemeArrowCursor;
+  f->output_data.mac->modeline_cursor = kThemeArrowCursor;
+  f->output_data.mac->hand_cursor = kThemePointingHandCursor;
+  f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
+  f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
 
   FRAME_FONTSET (f) = -1;
   f->output_data.mac->explicit_parent = 0;
@@ -9332,8 +10444,8 @@ mac_initialize_display_info ()
   main_device_handle = LMGetMainDevice();
 
   dpyinfo->reference_count = 0;
-  dpyinfo->resx = 75.0;
-  dpyinfo->resy = 75.0;
+  dpyinfo->resx = 72.0;
+  dpyinfo->resy = 72.0;
   dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
 #ifdef MAC_OSX
   /* HasDepth returns true if it is possible to have a 32 bit display,
@@ -9372,59 +10484,18 @@ mac_initialize_display_info ()
   dpyinfo->mouse_face_hidden = 0;
 }
 
-/* Create an xrdb-style database of resources to supercede registry settings.
-   The database is just a concatenation of C strings, finished by an additional
-   \0.  The string are submitted to some basic normalization, so
-
-     [ *]option[ *]:[ *]value...
-
-   becomes
-
-     option:value...
 
-   but any whitespace following value is not removed.  */
-
-static char *
+static XrmDatabase
 mac_make_rdb (xrm_option)
      char *xrm_option;
 {
-  char *buffer = xmalloc (strlen (xrm_option) + 2);
-  char *current = buffer;
-  char ch;
-  int in_option = 1;
-  int before_value = 0;
-
-  do {
-    ch = *xrm_option++;
-
-    if (ch == '\n')
-      {
-        *current++ = '\0';
-        in_option = 1;
-        before_value = 0;
-      }
-    else if (ch != ' ')
-      {
-        *current++ = ch;
-        if (in_option && (ch == ':'))
-          {
-            in_option = 0;
-            before_value = 1;
-          }
-        else if (before_value)
-          {
-            before_value = 0;
-          }
-      }
-    else if (!(in_option || before_value))
-      {
-        *current++ = ch;
-      }
-  } while (ch);
+  XrmDatabase database;
 
-  *current = '\0';
+  database = xrm_get_preference_database (NULL);
+  if (xrm_option)
+    xrm_merge_string_database (database, xrm_option);
 
-  return buffer;
+  return database;
 }
 
 struct mac_display_info *
@@ -9450,14 +10521,15 @@ mac_term_init (display_name, xrm_option, resource_name)
 
   dpyinfo = &one_mac_display_info;
 
-  dpyinfo->xrdb = xrm_option ? mac_make_rdb (xrm_option) : NULL;
+  dpyinfo->xrdb = mac_make_rdb (xrm_option);
 
   /* Put this display on the chain.  */
   dpyinfo->next = x_display_list;
   x_display_list = dpyinfo;
 
   /* Put it on x_display_name_list.  */
-  x_display_name_list = Fcons (Fcons (display_name, Qnil),
+  x_display_name_list = Fcons (Fcons (display_name,
+                                     Fcons (Qnil, dpyinfo->xrdb)),
                                x_display_name_list);
   dpyinfo->name_list_element = XCAR (x_display_name_list);
 
@@ -9535,7 +10607,6 @@ mac_check_bundle()
   extern int inhibit_window_system;
   extern int noninteractive;
   CFBundleRef appsBundle;
-  pid_t child;
 
   /* No need to test if already -nw*/
   if (inhibit_window_system || noninteractive)
@@ -9573,8 +10644,8 @@ MakeMeTheFrontProcess ()
 /***** Code to handle C-g testing  *****/
 
 /* Contains the Mac modifier formed from quit_char */
-static mac_quit_char_modifiers = 0;
-static mac_quit_char_keycode;
+int mac_quit_char_modifiers = 0;
+int mac_quit_char_keycode;
 extern int quit_char;
 
 static void
@@ -9585,10 +10656,9 @@ mac_determine_quit_char_modifiers()
 
   /* Map modifiers */
   mac_quit_char_modifiers = 0;
-  if (qc_modifiers & ctrl_modifier)  mac_quit_char_modifiers |= macCtrlKey;
-  if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
-  if (qc_modifiers & meta_modifier)  mac_quit_char_modifiers |= macMetaKey;
-  if (qc_modifiers & alt_modifier)   mac_quit_char_modifiers |= macAltKey;
+  if (qc_modifiers & ctrl_modifier)  mac_quit_char_modifiers |= controlKey;
+  if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
+  if (qc_modifiers & alt_modifier)   mac_quit_char_modifiers |= optionKey;
 }
 
 static void
@@ -9601,77 +10671,40 @@ init_quit_char_handler ()
 
   mac_determine_quit_char_modifiers();
 }
+#endif /* MAC_OSX */
 
-static Boolean
-quit_char_comp (EventRef inEvent, void *inCompData)
-{
-  if (GetEventClass(inEvent) != kEventClassKeyboard)
-    return false;
-  if (GetEventKind(inEvent) != kEventRawKeyDown)
-    return false;
-  {
-    UInt32 keyCode;
-    UInt32 keyModifiers;
-    GetEventParameter(inEvent, kEventParamKeyCode,
-                     typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
-    if (keyCode != mac_quit_char_keycode)
-      return false;
-    GetEventParameter(inEvent, kEventParamKeyModifiers,
-                     typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
-    if (keyModifiers != mac_quit_char_modifiers)
-      return false;
-  }
-  return true;
-}
-
-void
-mac_check_for_quit_char ()
+static void
+init_menu_bar ()
 {
-  EventRef event;
-  static EMACS_TIME last_check_time = { 0, 0 };
-  static EMACS_TIME one_second = { 1, 0 };
-  EMACS_TIME now, t;
-
-  /* If windows are not initialized, return immediately (keep it bouncin').  */
-  if (!mac_quit_char_modifiers)
-    return;
-
-  /* Don't check if last check is less than a second ago.  */
-  EMACS_GET_TIME (now);
-  EMACS_SUB_TIME (t, now, last_check_time);
-  if (EMACS_TIME_LT (t, one_second))
-    return;
-  last_check_time = now;
-
-  /* Redetermine modifiers because they are based on lisp variables */
-  mac_determine_quit_char_modifiers ();
+#ifdef MAC_OSX
+  OSErr err;
+  MenuRef menu;
+  MenuItemIndex menu_index;
 
-  /* Fill the queue with events */
-  BLOCK_INPUT;
-  ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
-  event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
-                                   NULL);
-  UNBLOCK_INPUT;
-  if (event)
+  err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
+                                    &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);
+  if (err == noErr)
     {
-      struct input_event e;
-
-      /* Use an input_event to emulate what the interrupt handler does. */
-      EVENT_INIT (e);
-      e.kind = ASCII_KEYSTROKE_EVENT;
-      e.code = quit_char;
-      e.arg = Qnil;
-      e.modifiers = NULL;
-      e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
-      XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
-      /* Remove event from queue to prevent looping. */
-      RemoveEventFromQueue (GetMainEventQueue (), event);
-      ReleaseEvent (event);
-      kbd_buffer_store_event (&e);
+      SetMenuItemCommandKey (menu, menu_index, false, 0);
+      InsertMenuItemTextWithCFString (menu, NULL,
+                                     0, kMenuItemAttrSeparator, 0);
+      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);
+#endif
+#endif
 }
 
-#endif /* MAC_OSX */
 
 /* Set up use of X before we make the first connection.  */
 
@@ -9695,11 +10728,16 @@ static struct redisplay_interface x_redisplay_interface =
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
   x_draw_fringe_bitmap,
+#if USE_CG_DRAWING
+  mac_define_fringe_bitmap,
+  mac_destroy_fringe_bitmap,
+#else
   0, /* define_fringe_bitmap */
   0, /* destroy_fringe_bitmap */
+#endif
   mac_per_char_metric,
   mac_encode_char,
-  NULL, /* mac_compute_glyph_string_overhangs */
+  mac_compute_glyph_string_overhangs,
   x_draw_glyph_string,
   mac_define_frame_cursor,
   mac_clear_frame_area,
@@ -9741,65 +10779,42 @@ mac_initialize ()
                                   off the bottom */
   baud_rate = 19200;
 
-  x_noop_count = 0;
   last_tool_bar_item = -1;
   any_help_event_p = 0;
 
   /* Try to use interrupt input; if we can't, then start polling.  */
   Fset_input_mode (Qt, Qnil, Qt, Qnil);
 
-#ifdef USE_X_TOOLKIT
-  XtToolkitInitialize ();
-  Xt_app_con = XtCreateApplicationContext ();
-  XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
-
-  /* Install an asynchronous timer that processes Xt timeout events
-     every 0.1s.  This is necessary because some widget sets use
-     timeouts internally, for example the LessTif menu bar, or the
-     Xaw3d scroll bar.  When Xt timouts aren't processed, these
-     widgets don't behave normally.  */
-  {
-    EMACS_TIME interval;
-    EMACS_SET_SECS_USECS (interval, 0, 100000);
-    start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
-  }
-#endif
-
-#if USE_TOOLKIT_SCROLL_BARS
-  xaw3d_arrow_scroll = False;
-  xaw3d_pick_top = True;
-#endif
-
-#if 0
-  /* Note that there is no real way portable across R3/R4 to get the
-     original error handler.  */
-  XSetErrorHandler (x_error_handler);
-  XSetIOErrorHandler (x_io_error_quitter);
-
-  /* Disable Window Change signals;  they are handled by X events.  */
-#ifdef SIGWINCH
-  signal (SIGWINCH, SIG_DFL);
-#endif /* ! defined (SIGWINCH) */
-
-  signal (SIGPIPE, x_connection_signal);
-#endif
-
   BLOCK_INPUT;
 
 #if TARGET_API_MAC_CARBON
-  init_required_apple_events ();
 
 #if USE_CARBON_EVENTS
+#ifdef MAC_OSX
   init_service_handler ();
 
   init_quit_char_handler ();
-#endif
+#endif /* MAC_OSX */
+
+  init_command_handler ();
+
+  init_menu_bar ();
+#endif /* USE_CARBON_EVENTS */
 
-  DisableMenuCommand (NULL, kHICommandQuit);
+#ifdef MAC_OSX
+  init_coercion_handler ();
+
+  init_apple_event_handler ();
 
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
+#endif
+
+#if USE_CG_DRAWING
+  mac_init_fringe ();
+#endif
+
   UNBLOCK_INPUT;
 }
 
@@ -9812,13 +10827,28 @@ syms_of_macterm ()
   x_error_message_string = Qnil;
 #endif
 
+  Qcontrol = intern ("control");       staticpro (&Qcontrol);
+  Qmeta    = intern ("meta");          staticpro (&Qmeta);
+  Qalt     = intern ("alt");           staticpro (&Qalt);
+  Qhyper   = intern ("hyper");         staticpro (&Qhyper);
+  Qsuper   = intern ("super");         staticpro (&Qsuper);
   Qmodifier_value = intern ("modifier-value");
-  Qalt = intern ("alt");
-  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
-  Qhyper = intern ("hyper");
-  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
-  Qsuper = intern ("super");
-  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+  staticpro (&Qmodifier_value);
+
+  Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
+  Fput (Qmeta,    Qmodifier_value, make_number (meta_modifier));
+  Fput (Qalt,     Qmodifier_value, make_number (alt_modifier));
+  Fput (Qhyper,   Qmodifier_value, make_number (hyper_modifier));
+  Fput (Qsuper,   Qmodifier_value, make_number (super_modifier));
+
+#if USE_CARBON_EVENTS
+  Qhicommand   = intern ("hicommand");    staticpro (&Qhicommand);
+#ifdef MAC_OSX
+  Qservices    = intern ("services");    staticpro (&Qservices);
+  Qpaste       = intern ("paste");       staticpro (&Qpaste);
+  Qperform     = intern ("perform");     staticpro (&Qperform);
+#endif
+#endif
 
 #ifdef MAC_OSX
   Fprovide (intern ("mac-carbon"), Qnil);
@@ -9833,116 +10863,121 @@ syms_of_macterm ()
   staticpro (&last_mouse_scroll_bar);
   last_mouse_scroll_bar = Qnil;
 
-  staticpro (&Qvendor_specific_keysyms);
-  Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
-
-  staticpro (&last_mouse_press_frame);
-  last_mouse_press_frame = Qnil;
-
-  Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
-  staticpro (&Qmac_ready_for_drag_n_drop);
-
-  Qbig5 = intern ("big5");
-  staticpro (&Qbig5);
-
-  Qcn_gb = intern ("cn-gb");
-  staticpro (&Qcn_gb);
+  staticpro (&fm_font_family_alist);
+  fm_font_family_alist = Qnil;
 
-  Qsjis = intern ("sjis");
-  staticpro (&Qsjis);
-
-  Qeuc_kr = intern ("euc-kr");
-  staticpro (&Qeuc_kr);
-
-  DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
-    doc: /* *Non-nil means autoselect window with mouse pointer.  */);
-  x_autoselect_window_p = 0;
-
-  DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
-              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
-  Vx_toolkit_scroll_bars = Qt;
+#if USE_ATSUI
+  staticpro (&atsu_font_id_hash);
+  atsu_font_id_hash = Qnil;
+#endif
 
+  /* We don't yet support this, but defining this here avoids whining
+     from cus-start.el and other places, like "M-x set-variable".  */
   DEFVAR_BOOL ("x-use-underline-position-properties",
-               &x_use_underline_position_properties,
+              &x_use_underline_position_properties,
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
 nil means ignore them.  If you encounter fonts with bogus
 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
-to 4.1, set this to nil.  */);
+to 4.1, set this to nil.
+
+NOTE: Not supported on Mac yet.  */);
   x_use_underline_position_properties = 0;
 
+  DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
+              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  Vx_toolkit_scroll_bars = Qt;
+#else
+  Vx_toolkit_scroll_bars = Qnil;
+#endif
+
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 
-  DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
-    doc: /* Non-nil means that the command key is used as the Emacs meta key.
-Otherwise the option key is used.  */);
-  Vmac_command_key_is_meta = Qt;
+/* Variables to configure modifier key assignment.  */
+
+  DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
+    doc: /* *Modifier key assumed when the Mac control key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  The default is `control'.  */);
+  Vmac_control_modifier = Qcontrol;
 
   DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
-    doc: /* Modifier to use for the Mac alt/option key.  The value can
-be alt, hyper, or super for the respective modifier.  If the value is
-nil then the key will act as the normal Mac option modifier.  */);
+    doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  If the value is nil then the key will act as the
+normal Mac control modifier, and the option key can be used to compose
+characters depending on the chosen Mac keyboard setting.  */);
   Vmac_option_modifier = Qnil;
 
-  DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
-    doc: /* Non-nil means that the control and meta keys are reversed.  This is
-           useful for non-standard keyboard layouts.  */);
-  Vmac_reverse_ctrl_meta = Qnil;
+  DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
+    doc: /* *Modifier key assumed when the Mac command key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  The default is `meta'.  */);
+  Vmac_command_modifier = Qmeta;
+
+  DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
+    doc: /* *Modifier key assumed when the Mac function key is pressed.
+The value can be `control', `meta', `alt', `hyper', or `super' for the
+respective modifier.  Note that remapping the function key may lead to
+unexpected results for some keys on non-US/GB keyboards.  */);
+  Vmac_function_modifier = Qnil;
 
   DEFVAR_LISP ("mac-emulate-three-button-mouse",
               &Vmac_emulate_three_button_mouse,
-    doc: /* t means that when the option-key is held down while pressing the
-    mouse button, the click will register as mouse-2 and while the
-    command-key is held down, the click will register as mouse-3.
-    'reverse means that the the option-key will register for mouse-3
-    and the command-key will register for mouse-2.  nil means that
-    not emulation should be done and the modifiers should be placed
-    on the mouse-1 event. */);
+    doc: /* *Specify a way of three button mouse emulation.
+The value can be nil, t, or the symbol `reverse'.
+nil means that no emulation should be done and the modifiers should be
+placed on the mouse-1 event.
+t means that when the option-key is held down while pressing the mouse
+button, the click will register as mouse-2 and while the command-key
+is held down, the click will register as mouse-3.
+The symbol `reverse' means that the option-key will register for
+mouse-3 and the command-key will register for mouse-2.  */);
   Vmac_emulate_three_button_mouse = Qnil;
 
 #if USE_CARBON_EVENTS
-  DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
-   doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
-the right click will be mouse-3.
-Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
-  Vmac_wheel_button_is_mouse_2 = Qt;
-
-  DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
-   doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it.  */);
-  Vmac_pass_command_to_system = Qt;
-
-  DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
-   doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it.  */);
-  Vmac_pass_control_to_system = Qt;
-
-  DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
-   doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
-Toolbox for processing before Emacs sees it.  */);
-  Vmac_pass_control_to_system = Qt;
-#endif
-
-  DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
-   doc: /* If non-nil, allow anti-aliasing.
+  DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
+   doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
+Otherwise, the right click will be treated as mouse-2 and the wheel
+button will be mouse-3.  */);
+  mac_wheel_button_is_mouse_2 = 1;
+
+  DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
+   doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox.  */);
+  mac_pass_command_to_system = 1;
+
+  DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
+   doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox.  */);
+  mac_pass_control_to_system = 1;
+
+#endif
+
+  DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
+   doc: /* *If non-nil, allow anti-aliasing.
 The text will be rendered using Core Graphics text rendering which
 may anti-alias the text.  */);
-  Vmac_use_core_graphics = Qnil;
-
-  DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
-    doc: /* One of the Text Encoding Base constant values defined in the
-Basic Text Constants section of Inside Macintosh - Text Encoding
-Conversion Manager.  Its value determines the encoding characters
-typed at the Mac keyboard (presumed to be in the MacRoman encoding)
-will convert into.  E.g., if it is set to kTextEncodingMacRoman (0),
-its default value, no conversion takes place.  If it is set to
-kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
-characters typed on Mac keyboard are first converted into the
-ISO Latin-1 or ISO Latin-2 encoding, respectively before being
-passed to Emacs.  Together with Emacs's set-keyboard-coding-system
-command, this enables the Mac keyboard to be used to enter non-ASCII
-characters directly.  */);
-  mac_keyboard_text_encoding = kTextEncodingMacRoman;
+#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.
+Each entry should be of the form:
+
+   (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
+
+where CHARSET-NAME is a string used in font names to identify the
+charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
+CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING.  */);
+  Vmac_charset_info_alist =
+    Fcons (list3 (build_string ("mac-roman"),
+                 make_number (smRoman), Qnil), Qnil);
 }
 
 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b