]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
(image_cache_refcount, dpyinfo_refcount) [GLYPH_DEBUG]: New variables.
[gnu-emacs] / src / macterm.c
index ebebb129bb8304c997f5974179463190ed41f14f..362da7f77c7caa07fd5b6a0e75e723c68441d8c7 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 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,12 +59,10 @@ 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>
@@ -71,7 +70,8 @@ Boston, MA 02111-1307, USA.  */
 #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"
@@ -82,9 +82,10 @@ Boston, MA 02111-1307, USA.  */
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
+#include "keyboard.h"
 #include "intervals.h"
-#include "composite.h"
-#include "coding.h"
+#include "atimer.h"
+#include "keymap.h"
 
 /* Set of macros that handle mapping of Mac modifier keys to emacs.  */
 #define macCtrlKey     (NILP (Vmac_reverse_ctrl_meta) ? controlKey :   \
@@ -94,7 +95,6 @@ Boston, MA 02111-1307, USA.  */
                        (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
                        : controlKey)
 #define macAltKey      (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
-
 \f
 
 /* Non-nil means Emacs uses toolkit scroll bars.  */
@@ -110,18 +110,8 @@ 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.  */
-
-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.  */
-
+/* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
+static Lisp_Object last_window;
 
 /* This is a chain of structures for all the X displays currently in
    use.  */
@@ -129,9 +119,12 @@ int x_use_underline_position_properties;
 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 +138,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 +165,6 @@ 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;
 
 /* The scroll bar in which the last X motion event occurred.
 
@@ -212,48 +198,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
-
 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));
@@ -270,14 +234,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,20 +255,23 @@ 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);
+static int is_emacs_window P_ ((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 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);
+
+#define GC_FORE_COLOR(gc)      (&(gc)->fore_color)
+#define GC_BACK_COLOR(gc)      (&(gc)->back_color)
+#define GC_FONT(gc)            ((gc)->xgcv.font)
+#define MAC_WINDOW_NORMAL_GC(w)        (((mac_output *) GetWRefCon (w))->normal_gc)
+
 
 /* X display function emulation */
 
@@ -315,47 +284,6 @@ XFreePixmap (display, pixmap)
 }
 
 
-/* Set foreground color for subsequent QuickDraw commands.  Assume
-   graphic port has already been set.  */
-
-static void
-mac_set_forecolor (unsigned long color)
-{
-  RGBColor fg_color;
-
-  fg_color.red = RED16_FROM_ULONG (color);
-  fg_color.green = GREEN16_FROM_ULONG (color);
-  fg_color.blue = BLUE16_FROM_ULONG (color);
-
-  RGBForeColor (&fg_color);
-}
-
-
-/* Set background color for subsequent QuickDraw commands.  Assume
-   graphic port has already been set.  */
-
-static void
-mac_set_backcolor (unsigned long color)
-{
-  RGBColor bg_color;
-
-  bg_color.red = RED16_FROM_ULONG (color);
-  bg_color.green = GREEN16_FROM_ULONG (color);
-  bg_color.blue = BLUE16_FROM_ULONG (color);
-
-  RGBBackColor (&bg_color);
-}
-
-/* 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_set_forecolor (gc->foreground);
-  mac_set_backcolor (gc->background);
-}
-
 /* Mac version of XDrawLine.  */
 
 static void
@@ -367,7 +295,7 @@ XDrawLine (display, w, gc, x1, y1, x2, y2)
 {
   SetPortWindowPort (w);
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
 
   MoveTo (x1, y1);
   LineTo (x2, y2);
@@ -386,7 +314,7 @@ mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
   GetGWorld (&old_port, &old_gdh);
   SetGWorld (p, NULL);
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
 
   LockPixels (GetGWorldPixMap (p));
   MoveTo (x1, y1);
@@ -396,29 +324,38 @@ 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;
+static void
+mac_erase_rectangle (w, gc, x, y, width, height)
      WindowPtr w;
+     GC gc;
      int x, y;
      unsigned int width, height;
-     int exposures;
 {
-  struct mac_output *mwp = (mac_output *) GetWRefCon (w);
   Rect r;
-  XGCValues xgc;
-
-  xgc.foreground = mwp->x_compatible.foreground_pixel;
-  xgc.background = mwp->x_compatible.background_pixel;
 
   SetPortWindowPort (w);
 
-  mac_set_colors (&xgc);
+  RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
   EraseRect (&r);
+
+  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
+}
+
+
+/* Mac version of XClearArea.  */
+
+void
+XClearArea (display, w, x, y, width, height, exposures)
+     Display *display;
+     WindowPtr w;
+     int x, y;
+     unsigned int width, height;
+     int exposures;
+{
+  mac_erase_rectangle (w, MAC_WINDOW_NORMAL_GC (w), x, y, width, height);
 }
 
 /* Mac version of XClearWindow.  */
@@ -428,15 +365,9 @@ XClearWindow (display, w)
      Display *display;
      WindowPtr w;
 {
-  struct mac_output *mwp = (mac_output *) GetWRefCon (w);
-  XGCValues xgc;
-
-  xgc.foreground = mwp->x_compatible.foreground_pixel;
-  xgc.background = mwp->x_compatible.background_pixel;
-
   SetPortWindowPort (w);
 
-  mac_set_colors (&xgc);
+  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
 
 #if TARGET_API_MAC_CARBON
   {
@@ -471,7 +402,8 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
 
   SetPortWindowPort (w);
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
+  RGBBackColor (GC_BACK_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
 #if TARGET_API_MAC_CARBON
@@ -483,6 +415,8 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
   CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
            overlay_p ? srcOr : srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
+
+  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
 }
 
 
@@ -588,12 +522,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 +540,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),
@@ -634,7 +574,7 @@ XFillRectangle (display, w, gc, x, y, width, height)
 
   SetPortWindowPort (w);
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
   PaintRect (&r); /* using foreground color of gc */
@@ -656,7 +596,7 @@ mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
 
   GetGWorld (&old_port, &old_gdh);
   SetGWorld (p, NULL);
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width, y + height);
 
   LockPixels (GetGWorldPixMap (p));
@@ -682,7 +622,7 @@ mac_draw_rectangle (display, w, gc, x, y, width, height)
 
   SetPortWindowPort (w);
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width + 1, y + height + 1);
 
   FrameRect (&r); /* using foreground color of gc */
@@ -706,7 +646,7 @@ mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
 
   GetGWorld (&old_port, &old_gdh);
   SetGWorld (p, NULL);
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
   SetRect (&r, x, y, x + width + 1, y + height + 1);
 
   LockPixels (GetGWorldPixMap (p));
@@ -728,8 +668,7 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
      char *buf;
      int nchars, mode, bytes_per_char;
 {
-  SetPortWindowPort (w);
-#ifdef MAC_OS_X_VERSION_10_2
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
   UInt32 textFlags, savedFlags;
   if (!NILP(Vmac_use_core_graphics)) {
     textFlags = kQDUseCGTextRendering;
@@ -737,16 +676,23 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
   }
 #endif
 
-  mac_set_colors (gc);
+  SetPortWindowPort (w);
+
+  RGBForeColor (GC_FORE_COLOR (gc));
+  if (mode != srcOr)
+    RGBBackColor (GC_BACK_COLOR (gc));
 
-  TextFont (gc->font->mac_fontnum);
-  TextSize (gc->font->mac_fontsize);
-  TextFace (gc->font->mac_fontface);
+  TextFont (GC_FONT (gc)->mac_fontnum);
+  TextSize (GC_FONT (gc)->mac_fontsize);
+  TextFace (GC_FONT (gc)->mac_fontface);
   TextMode (mode);
 
   MoveTo (x, y);
   DrawText (buf, 0, nchars * bytes_per_char);
-#ifdef MAC_OS_X_VERSION_10_2
+
+  if (mode != srcOr)
+    RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
   if (!NILP(Vmac_use_core_graphics))
     SwapQDTextFlags(savedFlags);
 #endif
@@ -850,6 +796,8 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
            &src_r, &dest_r, srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (src));
+
+  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest)));
 }
 
 
@@ -888,26 +836,10 @@ mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (mask));
   UnlockPixels (GetGWorldPixMap (src));
-}
-
-
-#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 (MAC_WINDOW_NORMAL_GC (dest)));
 }
-#endif
+
 
 /* Mac replacement for XCopyArea: used only for scrolling.  */
 
@@ -932,31 +864,17 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
   Rect src_r, dest_r;
 
   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);
   CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
 
-  mac_set_colors (gc);
-#endif
+  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
 #endif /* not TARGET_API_MAC_CARBON */
 }
 
@@ -1046,28 +964,37 @@ mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
 /* Mac replacement for XChangeGC.  */
 
 static void
-XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
-                XGCValues *xgcv)
+XChangeGC (display, gc, mask, xgcv)
+     Display *display;
+     GC gc;
+     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);
+  if (gc)
+    {
+      bzero (gc, sizeof (*gc));
+      XChangeGC (display, gc, mask, xgcv);
+    }
 
   return gc;
 }
@@ -1087,10 +1014,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 +1037,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 +1055,25 @@ 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;
 }
 
 
@@ -1161,28 +1120,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)
@@ -1322,12 +1259,17 @@ mac_draw_vertical_window_border (w, x, y0, y1)
      int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct face *face;
+
+  face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+  if (face)
+    XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
+                   face->foreground);
 
   XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
             f->output_data.mac->normal_gc, x, y0, x, y1);
 }
 
-
 /* End update of window W (which is equal to updated_window).
 
    Draw vertical borders between horizontally adjacent windows, and
@@ -1339,7 +1281,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 +1314,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 +1329,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 +1399,18 @@ 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);
-
       UNBLOCK_INPUT;
     }
 }
@@ -1504,7 +1430,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;
@@ -1528,9 +1453,6 @@ x_draw_fringe_bitmap (w, row, p)
 
   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 +1464,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 (window, face->gc, p->bx, p->by, p->nx, p->ny);
 
 #if 0  /* MAC_TODO: stipple */
       if (!face->stipple)
@@ -1555,21 +1475,24 @@ x_draw_fringe_bitmap (w, row, p)
   if (p->which)
     {
       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;
-
-      mac_draw_bitmap (display, window, &gcv, p->x, p->y,
+      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));
+      mac_draw_bitmap (display, window, face->gc, p->x, p->y,
                       p->wd, p->h, bits, p->overlay_p);
+      XSetForeground (display, face->gc, gcv.foreground);
     }
 
   mac_reset_clipping (display, window);
 }
 
 \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 +1511,7 @@ XTreset_terminal_modes ()
 {
 }
 
+
 \f
 /***********************************************************************
                           Display Iterator
@@ -1716,10 +1640,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 +1699,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 +1708,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 *));
@@ -1991,20 +1919,37 @@ 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)
     {
-      XCharStruct cs;
-      int direction, font_ascent, font_descent;
-      XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
-                     &font_ascent, &font_descent, &cs);
-      s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
-      s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
+      Rect r;
+      MacFontStruct *font = s->font;
+
+      TextFont (font->mac_fontnum);
+      TextSize (font->mac_fontsize);
+      TextFace (font->mac_fontface);
+
+      if (s->two_byte_p)
+       QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
+      else
+       {
+         int i;
+         char *buf = xmalloc (s->nchars);
+
+         if (buf == NULL)
+           SetRect (&r, 0, 0, 0, 0);
+         else
+           {
+             for (i = 0; i < s->nchars; ++i)
+               buf[i] = s->char2b[i].byte2;
+             QDTextBounds (s->nchars, buf, &r);
+             xfree (buf);
+           }
+       }
+
+      s->right_overhang = r.right > s->width ? r.right - s->width : 0;
+      s->left_overhang = r.left < 0 ? -r.left : 0;
     }
-#endif
 }
 
 
@@ -2015,10 +1960,7 @@ 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->window, s->gc, x, y, w, h);
 }
 
 
@@ -2606,27 +2548,29 @@ x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
 {
   XGCValues xgcv;
 
-  xgcv.foreground = s->face->box_color;
+  XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+  XSetForeground (s->display, s->gc, s->face->box_color);
   mac_set_clip_rectangle (s->display, s->window, clip_rect);
 
   /* Top.  */
-  XFillRectangle (s->display, s->window, &xgcv,
+  XFillRectangle (s->display, s->window, s->gc,
                  left_x, top_y, right_x - left_x + 1, width);
 
   /* Left.  */
   if (left_p)
-    XFillRectangle (s->display, s->window, &xgcv,
+    XFillRectangle (s->display, s->window, s->gc,
                    left_x, top_y, width, bottom_y - top_y + 1);
 
   /* Bottom.  */
-  XFillRectangle (s->display, s->window, &xgcv,
+  XFillRectangle (s->display, s->window, s->gc,
                  left_x, bottom_y - width + 1, right_x - left_x + 1, width);
 
   /* Right.  */
   if (right_p)
-    XFillRectangle (s->display, s->window, &xgcv,
+    XFillRectangle (s->display, s->window, s->gc,
                    right_x - width + 1, top_y, width, bottom_y - top_y + 1);
 
+  XSetForeground (s->display, s->gc, xgcv.foreground);
   mac_reset_clipping (s->display, s->window);
 }
 
@@ -2642,15 +2586,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
@@ -3051,13 +2989,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_erase_rectangle (s->window, gc, x, y, w, h);
 
          mac_reset_clipping (s->display, s->window);
        }
@@ -3078,10 +3010,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_p
+      && s->next->hl != DRAW_CURSOR)
     {
       xassert (s->next->img == NULL);
       x_set_glyph_string_gc (s->next);
@@ -3257,11 +3191,9 @@ x_clear_frame ()
   BLOCK_INPUT;
   XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_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;
@@ -3373,7 +3305,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.
@@ -3468,6 +3399,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 +3414,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 +3464,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
@@ -3729,43 +3738,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.
@@ -3822,18 +3794,11 @@ note_mouse_movement (frame, pos)
     }
 }
 
-/* This is used for debugging, to turn off note_mouse_highlight.  */
-
-int disable_mouse_highlight;
-
-
 \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 *));
 
 
@@ -3954,25 +3919,19 @@ remember_mouse_glyph (f1, gx, gy)
 }
 
 
-static WindowPtr
-front_emacs_window ()
+static struct frame *
+mac_focus_frame (dpyinfo)
+     struct mac_display_info *dpyinfo;
 {
-#if TARGET_API_MAC_CARBON
-  WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
-
-  while (wp && !is_emacs_window (wp))
-    wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
-#else
-  WindowPtr wp = FrontWindow ();
-
-  while (wp && (wp == tip_window || !is_emacs_window (wp)))
-    wp = GetNextWindow (wp);
-#endif
-
-  return wp;
+  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 ();
 }
 
-#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
 
 /* Return the current position of the mouse.
    *fp should be a frame which indicates which display to ask about.
@@ -4005,13 +3964,10 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 {
   Point mouse_pos;
   int ignore1, ignore2;
-  WindowPtr wp = front_emacs_window ();
-  struct frame *f;
+  struct frame *f = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
+  WindowPtr wp = FRAME_MAC_WINDOW (f);
   Lisp_Object frame, tail;
 
-  if (is_emacs_window(wp))
-    f = mac_window_to_frame (wp);
-
   BLOCK_INPUT;
 
   if (! NILP (last_mouse_scroll_bar) && insist == 0)
@@ -4043,30 +3999,307 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 }
 
 \f
-/***********************************************************************
-                              Tool-bars
- ***********************************************************************/
+/************************************************************************
+                        Toolkit scroll bars
+ ************************************************************************/
+
+#ifdef USE_TOOLKIT_SCROLL_BARS
+
+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 OSErr 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 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;
+{
+  EventRef event = NULL;
+  OSErr err;
+
+  err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
+                    kEventAttributeNone, &event);
+  if (err == noErr)
+    {
+      Point mouse_pos;
+
+      GetMouse (&mouse_pos);
+      LocalToGlobal (&mouse_pos);
+      err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
+                              sizeof (Point), &mouse_pos);
+    }
+  if (err == noErr)
+    {
+      UInt32 modifiers = GetCurrentKeyModifiers ();
+
+      err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
+                              sizeof (UInt32), &modifiers);
+    }
+  if (err == noErr)
+    err = PostEventToQueue (GetCurrentEventQueue (), event,
+                           kEventPriorityStandard);
+  if (err == noErr)
+    scroll_bar_timer_event_posted_p = 1;
+
+  if (event)
+    ReleaseEvent (event);
+}
+
+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 OSStatus
+set_scroll_bar_timer (delay)
+     EventTimerInterval delay;
+{
+  if (scroll_bar_timer == NULL)
+    install_scroll_bar_timer ();
+
+  scroll_bar_timer_event_posted_p = 0;
+
+  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 -1;
+}
+
+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;
+}
+
+static OSErr
+get_control_part_bounds (ch, part_code, rect)
+     ControlHandle ch;
+     ControlPartCode part_code;
+     Rect *rect;
+{
+  RgnHandle region = NewRgn ();
+  OSStatus err;
+
+  err = GetControlRegion (ch, part_code, region);
+  if (err == noErr)
+    GetRegionBounds (region, rect);
+  DisposeRgn (region);
 
-/* Handle mouse button event on the tool-bar of frame F, at
-   frame-relative coordinates X/Y.  EVENT_TYPE is either ButtionPress
-   or ButtonRelase.  */
+  return err;
+}
 
 static void
-mac_handle_tool_bar_click (f, button_event)
-     struct frame *f;
-     EventRecord *button_event;
+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);
+
+  if (part < 0)
+    return;
+
+  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
+x_scroll_bar_handle_release (bar, bufp)
+     struct scroll_bar *bar;
+     struct input_event *bufp;
+{
+  if (last_scroll_bar_part != scroll_bar_handle
+      || !GC_NILP (bar->dragging))
+    construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
+
+  HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
+  set_scroll_bar_timer (kEventDurationForever);
+
+  last_scroll_bar_part = -1;
+  bar->dragging = Qnil;
+  tracked_scroll_bar = NULL;
+}
+
+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)
+    {
+      int top, top_range;
+      Rect r;
+
+      get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
+                              kControlIndicatorPart, &r);
+
+      if (GC_NILP (bar->dragging))
+       XSETINT (bar->dragging, mouse_pos.v - r.top);
+
+      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;
+
+      if (top < 0)
+       top = 0;
+      if (top > top_range)
+       top = top_range;
+
+      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;
+
+      if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
+       unhilite_p = 1;
+      else
+       {
+         part = control_part_code_to_scroll_bar_part (part_code);
+
+         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);
+       }
+    }
+}
+
+/* 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
+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 (button_event->what == mouseDown)
-    handle_tool_bar_click (f, x, y, 1, 0);
+  if (whole == 0 || XINT (bar->track_height) == 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;
+
+  SetControl32BitMinimum (ch, 0);
+  SetControl32BitMaximum (ch, maximum);
+  SetControl32BitValue (ch, value);
+  SetControlViewSize (ch, viewsize);
+
+  UNBLOCK_INPUT;
 }
 
+#endif /* USE_TOOLKIT_SCROLL_BARS */
+
+
 \f
 /************************************************************************
                         Scroll bars, general
@@ -4096,14 +4329,13 @@ x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
   r.bottom = disp_top + disp_height;
 
 #if TARGET_API_MAC_CARBON
-  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
-                  kControlScrollBarProc, 0L);
+  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
+                  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 +4345,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 +4375,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 +4436,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.  */
@@ -4219,10 +4458,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 +4477,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,9 +4492,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
   /* Compute the left edge of the scroll bar.  */
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + 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;
@@ -4298,20 +4535,15 @@ 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);
+      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.  */
          XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                     left, top, area_width, height, 0);
+                     left, top, width, height, 0);
 
 #if 0
           if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
@@ -4323,18 +4555,52 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
           MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
           SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                       disp_height);
-          ShowControl (ch);
+         if (sb_width < disp_height)
+           ShowControl (ch);
 
           /* 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;
     }
 
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  if (NILP (bar->track_top))
+    {
+      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);
+
+      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 +4616,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 +4659,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 +4668,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 +4727,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 +4736,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 +4796,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 +4831,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 +4845,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 +4894,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
@@ -4722,29 +4965,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.  */
@@ -4855,11 +5079,7 @@ mac_define_frame_cursor (f, cursor)
      struct frame *f;
      Cursor cursor;
 {
-#if TARGET_API_MAC_CARBON
   SetThemeCursor (cursor);
-#else
-  SetCursor (*cursor);
-#endif
 }
 
 
@@ -5091,7 +5311,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 +5352,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 +5505,11 @@ x_set_window_size (f, change_gravity, cols, rows)
   x_wm_set_size_hint (f, (long) 0, 0);
 
   SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
+#if TARGET_API_MAC_CARBON
+  if (f->output_data.mac->hourglass_control)
+    MoveControl (f->output_data.mac->hourglass_control,
+                pixelwidth - HOURGLASS_WIDTH, 0);
+#endif
 
   /* Now, strictly speaking, we can't be sure that this is accurate,
      but the window manager will get around to dealing with the size
@@ -5358,7 +5584,6 @@ x_set_mouse_pixel_position (f, pix_x, pix_y)
   UNBLOCK_INPUT;
 #endif
 }
-
 \f
 /* focus shifting, raising and lowering.  */
 
@@ -5385,6 +5610,7 @@ x_unfocus_frame (f)
 }
 
 /* Raise frame F.  */
+
 void
 x_raise_frame (f)
      struct frame *f;
@@ -5398,6 +5624,7 @@ x_raise_frame (f)
 }
 
 /* Lower frame F.  */
+
 void
 x_lower_frame (f)
      struct frame *f;
@@ -5423,6 +5650,53 @@ 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.
@@ -5447,29 +5721,32 @@ 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 (!(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;
+
+      SelectWindow (FRAME_MAC_WINDOW (f));
+      CollapseWindow (FRAME_MAC_WINDOW (f), false);
       ShowWindow (FRAME_MAC_WINDOW (f));
     }
 
@@ -5528,25 +5805,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 +5838,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 +5883,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
@@ -5782,139 +6084,406 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 
 \f
 /***********************************************************************
-                               Fonts
+                         XLFD Pattern Match
  ***********************************************************************/
 
-/* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
+/* 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;
 
-struct font_info *
-x_get_font_info (f, font_idx)
-     FRAME_PTR f;
-     int font_idx;
+  /* 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
 {
-  return (FRAME_MAC_FONT_TABLE (f) + font_idx);
+  /* 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);
+    }
 }
 
-/* the global font name table */
-char **font_name_table = NULL;
-int font_name_table_size = 0;
-int font_name_count = 0;
+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;
 
-#if 0
-/* compare two strings ignoring case */
-static int
-stricmp (const char *s, const char *t)
+  pat = xmalloc (sizeof (struct xlfdpat));
+  if (pat == NULL)
+    goto error;
+
+  pat->buf = xmalloc (strlen (pattern) + 1);
+  if (pat->buf == NULL)
+    goto error;
+
+  /* Normalize the pattern string and store it to `pat->buf'.  */
+  nblocks = 0;
+  anychar_head = NULL;
+  q = pat->buf;
+  last_char = '\0';
+  for (p = pattern; *p; p++)
+    {
+      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);
+  if (pat->blocks == NULL)
+    goto error;
+
+  /* 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;
+
+ error:
+  xlfdpat_destroy (pat);
+  return NULL;
+}
+
+static INLINE int
+xlfdpat_exact_p (pat)
+     struct xlfdpat *pat;
 {
-  for ( ; tolower (*s) == tolower (*t); s++, t++)
-    if (*s == '\0')
-      return 0;
-  return tolower (*s) - tolower (*t);
+  return (pat)->blocks == NULL;
 }
 
-/* compare two strings ignoring case and handling wildcard */
-static int
-wildstrieq (char *s1, char *s2)
+/* 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;
 {
-  if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
-    return true;
+  int start, infinity;
+  unsigned char *p, *s;
+
+  xassert (blk->len > 0);
+  xassert (start_max + blk->len <= strlen (string));
+  xassert (blk->pattern[blk->len - 1] != '?');
+
+  /* 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 stricmp (s1, s2) == 0;
+  return NULL;
 }
 
-/* Assume parameter 1 is fully qualified, no wildcards. */
+#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
-mac_font_pattern_match (fontname, pattern)
-    char * fontname;
-    char * pattern;
+xlfdpat_match (pat, string)
+     struct xlfdpat *pat;
+     unsigned char *string;
 {
-  char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
-  char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
-  char *ptr;
+  int str_len, nblocks, i, start_max;
+  struct xlfdpat_block *blk;
+  unsigned char *s;
 
-  /* Copy fontname so we can modify it during comparison.  */
-  strcpy (font_name_copy, fontname);
+  xassert (pat->nblocks > 0);
 
-  ptr = regex;
-  *ptr++ = '^';
+  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;
 
-  /* Turn pattern into a regexp and do a regexp match.  */
-  for (; *pattern; pattern++)
+  /* 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)
     {
-      if (*pattern == '?')
-        *ptr++ = '.';
-      else if (*pattern == '*')
-        {
-          *ptr++ = '.';
-          *ptr++ = '*';
-        }
-      else
-        *ptr++ = *pattern;
+      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;
     }
-  *ptr = '$';
-  *(ptr + 1) = '\0';
 
-  return (fast_c_string_match_ignore_case (build_string (regex),
-                                           font_name_copy) >= 0);
+  return 1;
 }
 
-/* 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)
+\f
+/***********************************************************************
+                               Fonts
+ ***********************************************************************/
+
+/* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
+
+struct font_info *
+x_get_font_info (f, font_idx)
+     FRAME_PTR f;
+     int font_idx;
+{
+  return (FRAME_MAC_FONT_TABLE (f) + font_idx);
+}
+
+/* the global font name table */
+static char **font_name_table = NULL;
+static int font_name_table_size = 0;
+static int font_name_count = 0;
+
+/* Alist linking character set strings to Mac text encoding and Emacs
+   coding system. */
+static Lisp_Object Vmac_charset_info_alist;
+
+static Lisp_Object
+create_text_encoding_info_alist ()
 {
-  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];
+  Lisp_Object result = Qnil, rest;
+
+  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;
 
-  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 (!(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;
 
-  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);
+      existing_info = assq_no_quit (text_encoding, result);
+      if (NILP (existing_info))
+       result = Fcons (list3 (text_encoding, coding_system, charset),
+                       result);
+      else
+       if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
+         XSETCDR (XCDR (existing_info),
+                  Fcons (charset, XCDR (XCDR (existing_info))));
+    }
 
-  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)
-    {
-    case smTradChinese:
-      coding_system = Qbig5;
-      break;
-    case smSimpChinese:
-      coding_system = Qcn_gb;
-      break;
-    case smJapanese:
-      coding_system = Qsjis;
+  for (p = name; *p; p++)
+    if (!isascii (*p) || iscntrl (*p))
       break;
-    case smKorean:
-      coding_system = Qeuc_kr;
-      break;
-    default:
-      return;
-    }
+
+  if (*p == '\0'
+      || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
+    return;
 
   setup_coding_system (coding_system, &coding);
   coding.src_multibyte = 0;
@@ -5930,73 +6499,36 @@ decode_mac_font_name (name, size, scriptcode)
 
 
 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 ? 75 : 0, size ? 75 : 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;
 }
 
@@ -6009,44 +6541,55 @@ mac_to_x_fontname (name, size, style, scriptcode)
    "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;
+x_font_name_to_mac_font_name (xf, mf, mf_decoded, style, cs)
+     char *xf, *mf, *mf_decoded;
+     Style *style;
+     char *cs;
+{
+  Str31 foundry;
+  Str255 family;
+  char weight[20], slant[2], *p;
+  Lisp_Object charset_info, coding_system = Qnil;
   struct coding_system coding;
 
   strcpy (mf, "");
 
-  if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
+  if (sscanf (xf, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
               foundry, family, weight, slant, cs) != 5 &&
-      sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
+      sscanf (xf, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
               foundry, family, weight, slant, cs) != 5)
     return;
 
-  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);
+  *style = normal;
+  if (strcmp (weight, "bold") == 0)
+    *style |= bold;
+  if (*slant == 'i')
+    *style |= italic;
+
+  charset_info = Fassoc (build_string (cs), Vmac_charset_info_alist);
+  if (!NILP (charset_info))
+    {
+      strcpy (mf_decoded, family);
+      coding_system = Fcar (Fcdr (Fcdr (charset_info)));
+    }
   else
-    sprintf (mf, "%s-%s-%s", foundry, family, cs);
+    sprintf (mf_decoded, "%s-%s-%s", foundry, family, cs);
+
+  for (p = mf_decoded; *p; p++)
+    if (!isascii (*p) || iscntrl (*p))
+      break;
 
-  if (!NILP (coding_system))
+  if (*p == '\0'
+      || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
+    strcpy (mf, mf_decoded);
+  else
     {
       setup_coding_system (coding_system, &coding);
       coding.src_multibyte = 1;
-      coding.dst_multibyte = 1;
+      coding.dst_multibyte = 0;
       coding.mode |= CODING_MODE_LAST_BLOCK;
-      encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
+      encode_coding (&coding, mf_decoded, mf,
+                    strlen (mf_decoded), sizeof (Str255) - 1);
       mf[coding.produced] = '\0';
     }
 }
@@ -6057,13 +6600,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 *));
@@ -6081,181 +6624,180 @@ 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;
+
+  /* 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;
+    }
+
+  text_encoding_info_alist = create_text_encoding_info_alist ();
 
-  if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
+  GCPRO1 (text_encoding_info_alist);
+
+  while (FMGetNextFontFamily (&ffi, &ff) == noErr)
     {
-      FMFontFamilyIterator ffi;
-      FMFontFamilyInstanceIterator ffii;
-      FMFontFamily ff;
+      Str255 name;
+      FMFont font;
+      FMFontStyle style;
+      FMFontSize size;
+      TextEncoding encoding;
+      TextEncodingBase sc;
+      Lisp_Object text_encoding_info;
 
-      /* 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;
-       }
+      if (FMGetFontFamilyName (ff, name) != noErr)
+       break;
+      p2cstr (name);
+      if (*name == '.')
+       continue;
 
-      while (FMGetNextFontFamily (&ffi, &ff) == noErr)
-       {
-         Str255 name;
-         FMFont font;
-         FMFontStyle style;
-         FMFontSize size;
-         TextEncoding encoding;
-         TextEncodingBase sc;
-
-         if (FMGetFontFamilyName (ff, name) != noErr)
-           break;
-         p2cstr (name);
-         if (*name == '.')
-           continue;
+      if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
+       break;
+      sc = GetTextEncodingBase (encoding);
+      text_encoding_info = assq_no_quit (make_number (sc),
+                                        text_encoding_info_alist);
+      if (!NILP (text_encoding_info))
+       decode_mac_font_name (name, sizeof (name),
+                             XCAR (XCDR (text_encoding_info)));
+      else
+       text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
+                                          text_encoding_info_alist);
 
-         if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
-           break;
-         sc = GetTextEncodingBase (encoding);
-         decode_mac_font_name (name, sizeof (name), sc);
+      /* Point the instance iterator at the current font family.  */
+      if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
+       break;
 
-         /* Point the instance iterator at the current font family.  */
-         if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
-           break;
+      while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
+            == noErr)
+       {
+         Lisp_Object rest = XCDR (XCDR (text_encoding_info));
 
-         while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
-                == noErr)
+         for (; !NILP (rest); rest = XCDR (rest))
            {
-             /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
-                contained in Apple Japanese (SJIS) font.  */
-           again:
+             char *cs = SDATA (XCAR (rest));
+
              if (size == 0)
                {
                  add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               style, sc));
+                                                               style, cs));
                  add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               italic, sc));
+                                                               italic, cs));
                  add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               bold, sc));
+                                                               bold, cs));
                  add_font_name_table_entry (mac_to_x_fontname (name, size,
                                                                italic | bold,
-                                                               sc));
+                                                               cs));
                }
              else
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             style, sc));
-             if (sc == smJapanese)
                {
-                 sc = -smJapanese;
-                 goto again;
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               style, cs));
                }
-             else if (sc == -smJapanese)
-               sc = smJapanese;
            }
        }
-
-      /* Dispose of the iterators.  */
-      FMDisposeFontFamilyIterator (&ffi);
-      FMDisposeFontFamilyInstanceIterator (&ffii);
     }
-  else
+
+  UNGCPRO;
+
+  /* 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;
+  struct gcpro gcpro1;
+
+  GetPort (&port);  /* save the current font number used */
+  old_fontnum = port->txFont;
+
+  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 */
     {
-#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
+      font_handle = GetIndResource ('FOND', i);
+      if (!font_handle)
+       continue;
 
-      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)
+       continue;
 
-         GetResInfo (font_handle, &id, &type, name);
-         GetFNum (name, &fontnum);
-         p2cstr (name);
-         if (fontnum == 0)
-           continue;
+      TextFont (fontnum);
+      scriptcode = FontToScript (fontnum);
+      text_encoding_info = assq_no_quit (make_number (scriptcode),
+                                        text_encoding_info_alist);
+      if (!NILP (text_encoding_info))
+       decode_mac_font_name (name, sizeof (name),
+                             XCAR (XCDR (text_encoding_info)));
+      else
+       text_encoding_info = assq_no_quit (make_number (smRoman),
+                                          text_encoding_info_alist);
+      do
+       {
+         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++)
+                 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
+
+                 for (; !NILP (rest); rest = XCDR (rest))
                    {
-                     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);
-                       }
+                     char *cs = SDATA (XCAR (rest));
+
+                     add_font_name_table_entry (mac_to_x_fontname (name,
+                                                                   assc_entry->fontSize,
+                                                                   assc_entry->fontStyle,
+                                                                   cs));
                    }
                }
-
-             HUnlock (font_handle);
-             font_handle_2 = GetNextFOND (font_handle);
-             ReleaseResource (font_handle);
-             font_handle = font_handle_2;
            }
-         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 */
 }
 
 
@@ -6288,41 +6830,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 +6861,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 +6879,128 @@ 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);
+         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);
+         if (scaled == NULL)
+           continue;
          memcpy (scaled, font_name_table[i], former_len);
          sprintf (scaled + former_len,
                   "-%d-%d-75-75-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);
+             font_list = Fcons (build_string (scaled), font_list);
+             xfree (scaled);
              if (exact || maxnames > 0 && ++n_fonts >= maxnames)
-               break;
+                 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 +7051,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;
 {
@@ -6627,7 +7119,7 @@ is_fully_specified_xlfd (char *p)
 }
 
 
-const int kDefaultFontSize = 9;
+const int kDefaultFontSize = 12;
 
 
 /* XLoadQueryFont creates and returns an internal representation for a
@@ -6639,17 +7131,26 @@ const int kDefaultFontSize = 9;
 static MacFontStruct *
 XLoadQueryFont (Display *dpy, char *fontname)
 {
-  int i, size, is_two_byte_font, char_width;
+  int i, size, point_size, avgwidth, is_two_byte_font, char_width;
   char *name;
   GrafPtr port;
   SInt16 old_fontnum, old_fontsize;
   Style old_fontface;
-  Str32 mfontname;
+  Str255 mfontname, mfontname_decoded;
+  Str31 charset;
   SInt16 fontnum;
-  Style fontface = normal;
+  Style fontface;
+#if TARGET_API_MAC_CARBON
+  TextEncoding encoding;
+  int scriptcode;
+#else
+  short scriptcode;
+#endif
   MacFontStruct *font;
   FontInfo the_fontinfo;
-  char s_weight[7], c_slant;
+#ifdef MAC_OSX
+  UInt32 old_flags, new_flags;
+#endif
 
   if (is_fully_specified_xlfd (fontname))
     name = fontname;
@@ -6674,46 +7175,50 @@ XLoadQueryFont (Display *dpy, char *fontname)
   old_fontface = port->txFace;
 #endif
 
-  if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
+  if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size, &point_size, &avgwidth) != 3)
+    size = 0;
+  else
+    {
+      if (size == 0)
+       if (point_size > 0)
+         size = point_size / 10;
+       else if (avgwidth > 0)
+         size = avgwidth / 10;
+    }
+  if (size == 0)
     size = kDefaultFontSize;
 
-  if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
-    if (strcmp (s_weight, "bold") == 0)
-      fontface |= bold;
-
-  if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
-    if (c_slant == 'i')
-      fontface |= italic;
-
-  x_font_name_to_mac_font_name (name, mfontname);
+  x_font_name_to_mac_font_name (name, mfontname, mfontname_decoded,
+                               &fontface, charset);
   c2pstr (mfontname);
+#if TARGET_API_MAC_CARBON
+  fontnum = FMGetFontFamilyFromName (mfontname);
+  if (fontnum == kInvalidFontFamily
+      || FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
+    return NULL;
+  scriptcode = GetTextEncodingBase (encoding);
+#else
   GetFNum (mfontname, &fontnum);
   if (fontnum == 0)
     return NULL;
+  scriptcode = FontToScript (fontnum);
+#endif
 
   font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
 
-  font->fontname = (char *) xmalloc (strlen (name) + 1);
-  bcopy (name, font->fontname, strlen (name) + 1);
-
   font->mac_fontnum = fontnum;
   font->mac_fontsize = size;
   font->mac_fontface = fontface;
-  font->mac_scriptcode = FontToScript (fontnum);
+  font->mac_scriptcode = scriptcode;
 
   /* 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];
+  if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
+    font->mac_scriptcode = smRoman;
 
-    if (sscanf (name,
-               "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
-               cs) == 1
-       && 0 == strcmp (cs, "jisx0201.1976-0"))
-      font->mac_scriptcode = smRoman;
-  }
+  font->full_name = mac_to_x_fontname (mfontname_decoded, size, fontface, charset);
 
   is_two_byte_font = font->mac_scriptcode == smJapanese ||
                      font->mac_scriptcode == smTradChinese ||
@@ -6762,30 +7267,40 @@ XLoadQueryFont (Display *dpy, char *fontname)
        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;
+  if (is_two_byte_font)
+    {
+      font->per_char = NULL;
 
-  font->min_bounds = font->max_bounds;
+      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;
 
-  if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
-    font->per_char = NULL;
+      font->min_bounds = font->max_bounds;
+    }
   else
     {
       font->per_char = (XCharStruct *)
        xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
       {
-        int c, min_width, max_width;
+       int c, min_width, max_width;
+       Rect char_bounds, min_bounds, max_bounds;
+       char ch;
 
        min_width = max_width = char_width;
+       SetRect (&min_bounds, -32767, -32767, 32767, 32767);
+       SetRect (&max_bounds, 0, 0, 0, 0);
         for (c = 0x20; c <= 0xff; c++)
           {
-           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;
+           ch = c;
+           char_width = CharWidth (ch);
+           QDTextBounds (1, &ch, &char_bounds);
+           STORE_XCHARSTRUCT (font->per_char[c - 0x20],
+                              char_width, char_bounds);
            /* Some Japanese fonts (in SJIS encoding) return 0 as the
               character width of 0x7f.  */
            if (char_width > 0)
@@ -6793,9 +7308,25 @@ XLoadQueryFont (Display *dpy, char *fontname)
                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;
+           if (!EmptyRect (&char_bounds))
+             {
+               SetRect (&min_bounds,
+                        max (min_bounds.left, char_bounds.left),
+                        max (min_bounds.top, char_bounds.top),
+                        min (min_bounds.right, char_bounds.right),
+                        min (min_bounds.bottom, char_bounds.bottom));
+               UnionRect (&max_bounds, &char_bounds, &max_bounds);
+             }
+         }
+       STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
+       STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
+       if (min_width == max_width
+           && max_bounds.left >= 0 && max_bounds.right <= max_width)
+         {
+           /* Fixed width and no overhangs.  */
+           xfree (font->per_char);
+           font->per_char = NULL;
+         }
       }
     }
 
@@ -6812,7 +7343,7 @@ mac_unload_font (dpyinfo, font)
      struct mac_display_info *dpyinfo;
      XFontStruct *font;
 {
-  xfree (font->fontname);
+  xfree (font->full_name);
   if (font->per_char)
     xfree (font->per_char);
   xfree (font);
@@ -6852,6 +7383,8 @@ 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.  */
   {
@@ -6861,13 +7394,7 @@ x_load_font (f, fontname, size)
     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 +7427,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 +7459,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 +7526,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 +7590,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 +7605,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,33 +7623,12 @@ 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;
 
@@ -7153,24 +7659,17 @@ Lisp_Object Vmac_pass_command_to_system;
 Lisp_Object Vmac_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;
+/* 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;
 
 /* 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;
-
 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
@@ -7184,12 +7683,16 @@ static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
 /* Drag and Drop */
 static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
+static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL;
+static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
 #endif
 
+static Lisp_Object Qapplication, Qabout;
 #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 Qpreferences, Qservices, Qpaste, Qperform;
+#endif
 /* Window Event Handler */
 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
                                                EventRef, void *);
@@ -7198,7 +7701,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();
@@ -7290,45 +7792,81 @@ 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)
 {
   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;
+
+           eventRec->what = keyDown;
+           GetEventParameter (eventRef, kEventParamKeyMacCharCodes, typeChar,
+                              NULL, sizeof (char), NULL, &char_codes);
+           GetEventParameter (eventRef, kEventParamKeyCode, typeUInt32,
+                              NULL, sizeof (UInt32), NULL, &key_code);
+           eventRec->message = char_codes | ((key_code & 0xff) << 8);
+           result = 1;
+         }
+         break;
+
+       default:
+         break;
        }
+      break;
+
+    default:
+      break;
+    }
+
+  if (result)
+    {
+      /* 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));
     }
+
   return result;
 }
 
@@ -7346,11 +7884,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 +7909,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));
 
@@ -7409,40 +7947,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 +7996,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 +8030,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)
           {
@@ -7663,13 +8119,14 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   Point top_left;
   int w_title_height, 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;
 
     standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-    standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
+    standard_size.v = dpyinfo->height;
 
     if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
       zoom_in_or_out = inZoomIn;
@@ -7725,7 +8182,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 */
@@ -7827,104 +8284,155 @@ init_required_apple_events ()
     abort ();
 }
 
-#if USE_CARBON_EVENTS
-
 void
-init_service_handler ()
+mac_store_application_menu_event (event)
+#if USE_CARBON_EVENTS
+     EventRef event;
+#else
+     UInt32 event;
+#endif
 {
-  EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
-                          {kEventClassService, kEventServiceCopy},
-                          {kEventClassService, kEventServicePaste}};
-  InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
-                                 3, specs, NULL, NULL);
-}
+  struct input_event buf;
+  Lisp_Object frame, entry;
 
-/*
-   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;
+  EVENT_INIT (buf);
+
+  XSETFRAME (frame, mac_focus_frame (&one_mac_display_info));
+  buf.kind = MENU_BAR_EVENT;
+  buf.frame_or_window = frame;
+  buf.arg = frame;
+  kbd_buffer_store_event (&buf);
 
-       GetCurrentScrap (&currentScrap);
+  buf.arg = Qapplication;
+  kbd_buffer_store_event (&buf);
+
+#if USE_CARBON_EVENTS
+  switch (GetEventClass (event))
+    {
+#ifdef MAC_OSX
+    case kEventClassService:
+      buf.arg = Qservices;
+      kbd_buffer_store_event (&buf);
+      switch (GetEventKind (event))
+       {
+       case kEventServicePaste:
+         entry = Qpaste;
+         break;
 
-       err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
-       if (err == noErr)
+       case kEventServicePerform:
          {
-           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);
-             }
+           OSErr err;
+           CFStringRef message;
+
+           err = GetEventParameter (event, kEventParamServiceMessageName,
+                                    typeCFStringRef, NULL,
+                                    sizeof (CFStringRef), NULL, &message);
+           buf.arg = Qperform;
+           kbd_buffer_store_event (&buf);
+           if (err == noErr && message)
+             entry = intern (SDATA (cfstring_to_lisp (message)));
+           else
+             entry = Qnil;
          }
-       err = noErr;
-      }
-    case kEventServicePaste:
+         break;
+
+       default:
+         abort ();
+       }
+      break;
+#endif /* MAC_OSX */
+    case kEventClassCommand:
       {
-       /*
-       // 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;
-           }
+       HICommand command;
+
+       GetEventParameter(event, kEventParamDirectObject, typeHICommand,
+                         NULL, sizeof (HICommand), NULL, &command);
+       switch (command.commandID)
+         {
+         case kHICommandAbout:
+           entry = Qabout;
+           break;
+#ifdef MAC_OSX
+         case kHICommandPreferences:
+           entry = Qpreferences;
+           break;
+#endif /* MAC_OSX */
+         case kHICommandQuit:
+           entry = Qquit;
+           break;
+         default:
+           abort ();
          }
-         xfree(buffer);
-        }
-        */
       }
+      break;
+
+    default:
+      abort ();
     }
-  return err;
+#else  /* USE_CARBON_EVENTS */
+  switch (event)
+    {
+    case kHICommandAbout:
+      entry = Qabout;
+      break;
+    case kHICommandQuit:
+      entry = Qquit;
+      break;
+    default:
+      abort ();
+    }
+#endif
+
+  buf.arg = entry;
+  kbd_buffer_store_event (&buf);
+}
+
+#if USE_CARBON_EVENTS
+static pascal OSStatus
+mac_handle_command_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  HICommand command;
+  OSErr result;
+
+  GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL,
+                   sizeof (HICommand), NULL, &command);
+
+  switch (command.commandID)
+    {
+    case kHICommandAbout:
+#ifdef MAC_OSX
+    case kHICommandPreferences:
+#endif /* MAC_OSX */
+      result = CallNextEventHandler (next_handler, event);
+      if (result != eventNotHandledErr)
+       return result;
+
+      mac_store_application_menu_event (event);
+      return noErr;
+
+    default:
+      break;
+    }
+
+  return eventNotHandledErr;
 }
 
+static OSErr
+init_command_handler ()
+{
+  OSErr err = noErr;
+  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,8 +8440,6 @@ mac_handle_window_event (next_handler, event, data)
      EventRef event;
      void *data;
 {
-  extern Lisp_Object Qcontrol;
-
   WindowPtr wp;
   OSStatus result;
   UInt32 attributes;
@@ -7950,7 +8456,7 @@ mac_handle_window_event (next_handler, event, data)
        return result;
 
       do_window_update (wp);
-      break;
+      return noErr;
 
     case kEventWindowBoundsChanging:
       result = CallNextEventHandler (next_handler, event);
@@ -7989,12 +8495,83 @@ mac_handle_window_event (next_handler, event, data)
                       / (float) size_hints->height_inc + .5)
              * size_hints->height_inc;
 
-         bounds.right = bounds.left + width;
-         bounds.bottom = bounds.top + height;
-         SetEventParameter (event, kEventParamCurrentBounds,
-                            typeQDRectangle, sizeof (Rect), &bounds);
-         return noErr;
-       }
+         bounds.right = bounds.left + width;
+         bounds.bottom = bounds.top + height;
+         SetEventParameter (event, kEventParamCurrentBounds,
+                            typeQDRectangle, sizeof (Rect), &bounds);
+         return noErr;
+       }
+      break;
+
+    case kEventWindowShown:
+    case kEventWindowHidden:
+    case kEventWindowExpanded:
+    case kEventWindowCollapsed:
+      result = CallNextEventHandler (next_handler, event);
+
+      mac_handle_visibility_change (mac_window_to_frame (wp));
+      return noErr;
+
+      break;
+    }
+
+  return eventNotHandledErr;
+}
+
+static pascal OSStatus
+mac_handle_mouse_event (next_handler, event, data)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  OSStatus result;
+
+  switch (GetEventKind (event))
+    {
+    case kEventMouseWheelMoved:
+      {
+       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;
+
+       GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
+                          NULL, sizeof (WindowRef), NULL, &wp);
+       f = mac_window_to_frame (wp);
+       if (f != mac_focus_frame (&one_mac_display_info))
+         break;
+
+       GetEventParameter (event, kEventParamMouseWheelAxis,
+                          typeMouseWheelAxis, NULL,
+                          sizeof (EventMouseWheelAxis), NULL, &axis);
+       if (axis != kEventMouseWheelAxisY)
+         break;
+
+       GetEventParameter (event, kEventParamMouseWheelDelta, typeSInt32,
+                          NULL, sizeof (SInt32), NULL, &delta);
+       GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
+                          NULL, sizeof (Point), NULL, &point);
+       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;
+      }
+      break;
+
+    default:
       break;
     }
 
@@ -8009,26 +8586,54 @@ install_window_handler (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);
-
-  err = InstallWindowEventHandler (window, handle_window_event_UPP,
-                                  GetEventTypeCount (specs), specs,
-                                  NULL, NULL);
+  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 TARGET_API_MAC_CARBON
+  if (mac_do_track_dragUPP == NULL)
+    mac_do_track_dragUPP = NewDragTrackingHandlerUPP (mac_do_track_drag);
+  if (mac_do_receive_dragUPP == NULL)
+    mac_do_receive_dragUPP = NewDragReceiveHandlerUPP (mac_do_receive_drag);
+
   if (err == noErr)
-    err = InstallTrackingHandler (mac_do_track_drag, window, NULL);
+    err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL);
   if (err == noErr)
-    err = InstallReceiveHandler (mac_do_receive_drag, window, NULL);
+    err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
 #endif
   return err;
 }
 
+void
+remove_window_handler (window)
+     WindowPtr window;
+{
+#if TARGET_API_MAC_CARBON
+  if (mac_do_track_dragUPP)
+    RemoveTrackingHandler (mac_do_track_dragUPP, window);
+  if (mac_do_receive_dragUPP)
+    RemoveReceiveHandler (mac_do_receive_dragUPP, window);
+#endif
+}
 
 /* Open Application Apple Event */
 static pascal OSErr
@@ -8038,11 +8643,6 @@ do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
 }
 
 
-/* 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.  */
@@ -8066,6 +8666,9 @@ do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
   DescType actual_type;
   Size actual_size;
   SelectionRange position;
+  Lisp_Object file_list = Qnil;
+
+  xassert (read_socket_inev);
 
   err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
   if (err != noErr)
@@ -8073,10 +8676,10 @@ do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
 
   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);
+    file_list = Fcons (list3 (make_number (position.lineNum + 1),
+                             make_number (position.startRange + 1),
+                             make_number (position.endRange + 1)),
+                      file_list);
 
   /* Check to see that we got all of the required parameters from the
      event descriptor.  For an 'odoc' event this should just be the
@@ -8107,9 +8710,9 @@ do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
         /* AE file list is one based so just use that for indexing here.  */
         for (i = 1; i <= num_files_to_open; i++)
          {
+           char unix_path_name[MAXPATHLEN];
 #ifdef MAC_OSX
            FSRef fref;
-           char unix_path_name[MAXPATHLEN];
 
            err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
                               &actual_type, &fref, sizeof (FSRef),
@@ -8121,22 +8724,57 @@ do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
                == 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))
+           if (fsspec_to_posix_pathname (&fs, unix_path_name,
+                                         sizeof (unix_path_name) - 1) == noErr)
 #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);
+             file_list = Fcons (make_unibyte_string (unix_path_name,
+                                                     strlen (unix_path_name)),
+                                file_list);
+         }
+      }
+
+    /* Build a DRAG_N_DROP_EVENT type event as is done in
+       constuct_drag_n_drop in w32term.c.  */
+    if (!NILP (file_list))
+      {
+       struct frame *f = mac_focus_frame (&one_mac_display_info);
+       WindowPtr wp;
+       Lisp_Object frame;
+
+       read_socket_inev->kind = DRAG_N_DROP_EVENT;
+       read_socket_inev->code = 0;
+       read_socket_inev->modifiers = 0;
+
+       XSETINT (read_socket_inev->x, 0);
+       XSETINT (read_socket_inev->y, 0);
+
+       XSETFRAME (frame, f);
+       read_socket_inev->frame_or_window = Fcons (frame, file_list);
+
+#if 0
+       /* Regardless of whether Emacs was suspended or in the
+          foreground, ask it to redraw its entire screen.  Otherwise
+          parts of the screen can be left in an inconsistent
+          state.  */
+       wp = FRAME_MAC_WINDOW (f);
+       if (wp)
+#if TARGET_API_MAC_CARBON
+         {
+           Rect r;
+
+           GetWindowPortBounds (wp, &r);
+           InvalWindowRect (wp, &r);
          }
+#else /* not TARGET_API_MAC_CARBON */
+       InvalRect (&(wp->portRect));
+#endif /* not TARGET_API_MAC_CARBON */
+#endif
       }
   }
 
@@ -8189,7 +8827,6 @@ mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
          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);
@@ -8207,7 +8844,6 @@ mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
        {
          struct frame *f = mac_window_to_frame (window);
 
-         mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
          HideDragHilite (theDrag);
          SetThemeCursor (kThemeArrowCursor);
        }
@@ -8232,11 +8868,12 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
   ItemReference theItem;
   HFSFlavor data;
   Size size = sizeof (HFSFlavor);
+  Lisp_Object file_list;
 
   if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
     return dragNotAcceptedErr;
 
-  drag_and_drop_file_list = Qnil;
+  file_list = Qnil;
   GetDragMouse (theDrag, &mouse, 0L);
   CountDragItems (theDrag, &items);
   for (index = 1; index <= items; index++)
@@ -8248,10 +8885,9 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
        {
 #ifdef MAC_OSX
          FSRef fref;
-         char unix_path_name[MAXPATHLEN];
-#else
-         Str255 path_name, unix_path_name;
 #endif
+         char unix_path_name[MAXPATHLEN];
+
          GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
 #ifdef MAC_OSX
          /* Use Carbon routines, otherwise it converts the file name
@@ -8259,20 +8895,18 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
          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))
+         if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name,
+                                       sizeof (unix_path_name) - 1) == noErr)
 #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);
+            file_list = Fcons (make_unibyte_string (unix_path_name,
+                                                   strlen (unix_path_name)),
+                              file_list);
        }
     }
   /* If there are items in the list, construct an event and post it to
      the queue like an interrupt using kbd_buffer_store_event.  */
-  if (!NILP (drag_and_drop_file_list))
+  if (!NILP (file_list))
     {
       struct input_event event;
       Lisp_Object frame;
@@ -8289,7 +8923,7 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
       XSETINT (event.x, mouse.h);
       XSETINT (event.y, mouse.v);
       XSETFRAME (frame, f);
-      event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
+      event.frame_or_window = Fcons (frame, file_list);
       event.arg = Qnil;
       /* Post to the interrupt queue */
       kbd_buffer_store_event (&event);
@@ -8319,14 +8953,30 @@ do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
 static pascal OSErr
 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
 {
-  /* 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.  */
+#if USE_CARBON_EVENTS
+  OSErr err;
+  EventRef event = NULL;
+  static const HICommand quit_command = {kEventAttributeNone, kHICommandQuit};
+
+  err = CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 0,
+                    kEventAttributeUserEvent, &event);
+  if (err == noErr)
+    err = SetEventParameter (event, kEventParamDirectObject, typeHICommand,
+                            sizeof (HICommand), &quit_command);
+  if (err == noErr)
+    mac_store_application_menu_event (event);
+  if (event)
+    ReleaseEvent (event);
 
-  terminate_flag = true;
+  if (err == noErr)
+    return noErr;
+  else
+    return errAEEventNotHandled;
+#else
+  mac_store_application_menu_event (kHICommandQuit);
 
-  /* Fkill_emacs doesn't return.  We have to return. (TI) */
   return noErr;
+#endif
 }
 
 
@@ -8340,25 +8990,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)
@@ -8416,19 +9061,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,11 +9089,11 @@ 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
 };
 
@@ -8522,20 +9171,6 @@ 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));
-
 #if USE_CARBON_EVENTS
   toolbox_dispatcher = GetEventDispatcherTarget ();
 
@@ -8547,6 +9182,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 +9192,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 +9222,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
@@ -8656,20 +9255,23 @@ XTread_socket (sd, expected, hold_quit)
            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 +9281,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,15 +9299,18 @@ 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
+#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;
@@ -8709,10 +9318,24 @@ XTread_socket (sd, expected, hold_quit)
                        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 +9343,7 @@ XTread_socket (sd, expected, hold_quit)
                          tracked_scroll_bar = bar;
                        else
                          tracked_scroll_bar = NULL;
+#endif  /* not USE_TOOLKIT_SCROLL_BARS */
                      }
                    else
                      {
@@ -8769,15 +9393,18 @@ 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;
-                     }
+#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;
 
@@ -8857,7 +9484,66 @@ XTread_socket (sd, expected, hold_quit)
              help_echo_string = help_echo_object = help_echo_window = Qnil;
              help_echo_pos = -1;
 
-             do_mouse_moved (er.where, &f);
+             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);
+               }
+
+             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;
+                       }
+                     note_mouse_movement (f, &mouse_pos);
+                   }
+               }
 
              /* If the contents of the global variable
                 help_echo_string has changed, generate a
@@ -8886,15 +9572,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 +9589,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,7 +9635,7 @@ 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
@@ -8949,20 +9644,44 @@ XTread_socket (sd, expected, hold_quit)
            if ((!NILP (Vmac_pass_command_to_system)
                 || !(er.modifiers & cmdKey))
                && (!NILP (Vmac_pass_control_to_system)
-                   || !(er.modifiers & controlKey)))
+                   || !(er.modifiers & controlKey))
+               && (!NILP (Vmac_command_key_is_meta)
+                   && NILP (Vmac_option_modifier)
+                   || !(er.modifiers & optionKey)))
              if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
                  != eventNotHandledErr)
                break;
 #endif
 
-#if 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))
@@ -8996,155 +9715,43 @@ XTread_socket (sd, expected, hold_quit)
                    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 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.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)
-               {
-                 /* 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;
-               }
-
-             if (the_err == noErr)
-               {
-                 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);
-                   }
-               }
-           }
-
 #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, mac_focus_frame (dpyinfo));
          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 +9761,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,8 +9801,27 @@ 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
 
   UNBLOCK_INPUT;
@@ -9249,12 +9876,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;
@@ -9372,59 +9999,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++;
+  XrmDatabase database;
 
-    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);
+  database = xrm_get_preference_database (NULL);
+  if (xrm_option)
+    xrm_merge_string_database (database, xrm_option);
 
-  *current = '\0';
-
-  return buffer;
+  return database;
 }
 
 struct mac_display_info *
@@ -9450,14 +10036,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);
 
@@ -9573,8 +10160,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
@@ -9663,15 +10250,47 @@ mac_check_for_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 ()));
+      XSETFRAME (e.frame_or_window, mac_focus_frame (&one_mac_display_info));
       /* Remove event from queue to prevent looping. */
       RemoveEventFromQueue (GetMainEventQueue (), event);
       ReleaseEvent (event);
       kbd_buffer_store_event (&e);
     }
 }
+#endif /* MAC_OSX */
+
+static void
+init_menu_bar ()
+{
+#ifdef MAC_OSX
+  OSErr err;
+  MenuRef menu;
+  MenuItemIndex menu_index;
+
+  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)
+    {
+      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.  */
 
@@ -9699,7 +10318,7 @@ static struct redisplay_interface x_redisplay_interface =
   0, /* destroy_fringe_bitmap */
   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,64 +10360,33 @@ 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 ();
 
-  DisableMenuCommand (NULL, kHICommandQuit);
+  init_menu_bar ();
+#endif /* USE_CARBON_EVENTS */
 
+#ifdef MAC_OSX
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
+#endif
 #endif
   UNBLOCK_INPUT;
 }
@@ -9820,6 +10408,16 @@ syms_of_macterm ()
   Qsuper = intern ("super");
   Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
 
+  Qapplication = intern ("application");  staticpro (&Qapplication);
+  Qabout       = intern ("about");       staticpro (&Qabout);
+
+#if USE_CARBON_EVENTS && defined (MAC_OSX)
+  Qpreferences = intern ("preferences");  staticpro (&Qpreferences);
+  Qservices    = intern ("services");    staticpro (&Qservices);
+  Qpaste       = intern ("paste");       staticpro (&Qpaste);
+  Qperform     = intern ("perform");     staticpro (&Qperform);
+#endif
+
 #ifdef MAC_OSX
   Fprovide (intern ("mac-carbon"), Qnil);
 #endif
@@ -9833,42 +10431,16 @@ 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);
-
-  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.  */);
+#ifdef USE_TOOLKIT_SCROLL_BARS
   Vx_toolkit_scroll_bars = Qt;
-
-  DEFVAR_BOOL ("x-use-underline-position-properties",
-               &x_use_underline_position_properties,
-     doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
-nil means ignore them.  If you encounter fonts with bogus
-UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
-to 4.1, set this to nil.  */);
-  x_use_underline_position_properties = 0;
+#else
+  Vx_toolkit_scroll_bars = Qnil;
+#endif
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
@@ -9886,18 +10458,18 @@ nil then the key will act as the normal Mac option modifier.  */);
 
   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.  */);
+useful for non-standard keyboard layouts.  */);
   Vmac_reverse_ctrl_meta = 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. */);
+mouse button, the click will register as mouse-2 and while the
+command-key is held down, the click will register as mouse-3.
+'reverse means that the option-key will register for mouse-3
+and the command-key will register for mouse-2.  nil means that
+no emulation should be done and the modifiers should be placed
+on the mouse-1 event. */);
   Vmac_emulate_three_button_mouse = Qnil;
 
 #if USE_CARBON_EVENTS
@@ -9917,10 +10489,6 @@ Toolbox for processing before Emacs sees it.  */);
 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,
@@ -9929,20 +10497,21 @@ 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;
+  /* Register an entry for `mac-roman' so that it can be used when
+     creating the terminal frame on Mac OS 9 before loading
+     term/mac-win.elc.  */
+  DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
+               doc: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
+Each entry should be of the form:
+
+   (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
+
+where CHARSET-NAME is a string used in font names to identify the
+charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
+is a coding system corresponding to TEXT-ENCODING.  */);
+  Vmac_charset_info_alist =
+    Fcons (list3 (build_string ("mac-roman"),
+                 make_number (smRoman), Qnil), Qnil);
 }
 
 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b