]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
(image_cache_refcount, dpyinfo_refcount) [GLYPH_DEBUG]: New variables.
[gnu-emacs] / src / macterm.c
index fdb61249629fa5877693b3869a313c565a9ce9e2..362da7f77c7caa07fd5b6a0e75e723c68441d8c7 100644 (file)
@@ -1,5 +1,6 @@
 /* Implementation of GUI terminal on the Mac OS.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004 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>
@@ -50,27 +51,27 @@ Boston, MA 02111-1307, USA.  */
 #include <TextUtils.h>
 #include <LowMem.h>
 #include <Controls.h>
+#include <Windows.h>
 #if defined (__MRC__) || (__MSL__ >= 0x6000)
 #include <ControlDefinitions.h>
 #endif
-#include <Gestalt.h>
 
 #if __profile__
 #include <profiler.h>
 #endif
-#endif /* not MAC_OSX */
+#endif /* not TARGET_API_MAC_CARBON */
 
 #include "systty.h"
 #include "systime.h"
-#include "atimer.h"
-#include "keymap.h"
 
 #include <ctype.h>
 #include <errno.h>
 #include <setjmp.h>
 #include <sys/stat.h>
+#include <sys/param.h>
 
-#include "keyboard.h"
+#include "charset.h"
+#include "coding.h"
 #include "frame.h"
 #include "dispextern.h"
 #include "fontset.h"
@@ -81,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 :   \
@@ -93,30 +95,23 @@ 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.  */
 
 Lisp_Object Vx_toolkit_scroll_bars;
 
+/* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text.  */
+Lisp_Object Vmac_use_core_graphics;
+
+
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    start.  */
 
 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.  */
@@ -124,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;
 
@@ -140,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)
@@ -173,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.
 
@@ -196,14 +187,6 @@ static Lisp_Object last_mouse_scroll_bar;
 
 static Time last_mouse_movement_time;
 
-enum mouse_tracking_type {
-  mouse_tracking_none,
-  mouse_tracking_mouse_movement,
-  mouse_tracking_scroll_bar
-};
-
-enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
-
 struct scroll_bar *tracked_scroll_bar = NULL;
 
 /* Incremented by XTread_socket whenever it really tries to read
@@ -215,44 +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;
 
-static Lisp_Object Qvendor_specific_keysyms;
+/* The keysyms to use for the various modifiers.  */
 
-#if 0
-extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
-#endif
+static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
 
 extern int inhibit_window_system;
 
-#if __MRC__
+#if __MRC__ && !TARGET_API_MAC_CARBON
 QDGlobals qd;  /* QuickDraw global information structure.  */
 #endif
 
+#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
 
-struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
 struct mac_display_info *mac_display_info_for_display (Display *);
 static void x_update_window_end P_ ((struct window *, int, int));
-static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
 static int x_io_error_quitter P_ ((Display *));
 int x_catch_errors P_ ((Display *));
 void x_uncatch_errors P_ ((Display *, int));
@@ -269,39 +234,44 @@ 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 *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
 
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
+static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
 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 P_ ((WindowPtr));
 
-static int is_emacs_window (WindowPtr);
-
-int x_bitmap_icon (struct frame *, Lisp_Object);
-void x_make_frame_visible (struct frame *);
-
-extern void window_scroll (Lisp_Object, int, int, int);
+static 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 */
 
@@ -314,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
@@ -364,13 +293,9 @@ XDrawLine (display, w, gc, x1, y1, x2, y2)
      GC gc;
      int x1, y1, x2, y2;
 {
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  SetPortWindowPort (w);
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
 
   MoveTo (x1, y1);
   LineTo (x2, y2);
@@ -383,43 +308,54 @@ mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
      GC gc;
      int x1, y1, x2, y2;
 {
+  CGrafPtr old_port;
+  GDHandle old_gdh;
+
+  GetGWorld (&old_port, &old_gdh);
   SetGWorld (p, NULL);
 
-  mac_set_colors (gc);
+  RGBForeColor (GC_FORE_COLOR (gc));
 
   LockPixels (GetGWorldPixMap (p));
   MoveTo (x1, y1);
   LineTo (x2, y2);
   UnlockPixels (GetGWorldPixMap (p));
+
+  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;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  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.  */
@@ -429,19 +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;
-
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  SetPortWindowPort (w);
 
-  mac_set_colors (&xgc);
+  RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
 
 #if TARGET_API_MAC_CARBON
   {
@@ -474,13 +400,10 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
   bitmap.baseAddr = (char *)bits;
   SetRect (&(bitmap.bounds), 0, 0, width, height);
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  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
@@ -492,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)));
 }
 
 
@@ -503,11 +428,7 @@ mac_set_clip_rectangle (display, w, r)
      WindowPtr w;
      Rect *r;
 {
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  SetPortWindowPort (w);
 
   ClipRect (r);
 }
@@ -522,34 +443,13 @@ mac_reset_clipping (display, w)
 {
   Rect r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  SetPortWindowPort (w);
 
   SetRect (&r, -32767, -32767, 32767, 32767);
   ClipRect (&r);
 }
 
 
-/* XBM bits seem to be backward within bytes compared with how
-   Mac does things.  */
-static unsigned char
-reflect_byte (orig)
-     unsigned char orig;
-{
-  int i;
-  unsigned char reflected = 0x00;
-  for (i = 0; i < 8; i++)
-    {
-      if (orig & (0x01 << i))
-       reflected |= 0x80 >> i;
-    }
-  return reflected;
-}
-
-
 /* Mac replacement for XCreateBitmapFromBitmapData.  */
 
 static void
@@ -558,6 +458,11 @@ mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
      char *bits;
      int w, h;
 {
+  static unsigned char swap_nibble[16]
+    = { 0x0, 0x8, 0x4, 0xc,    /* 0000 1000 0100 1100 */
+       0x2, 0xa, 0x6, 0xe,    /* 0010 1010 0110 1110 */
+       0x1, 0x9, 0x5, 0xd,    /* 0001 1001 0101 1101 */
+       0x3, 0xb, 0x7, 0xf };  /* 0011 1011 0111 1111 */
   int i, j, w1;
   char *p;
 
@@ -569,7 +474,12 @@ mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
     {
       p = bitmap->baseAddr + i * bitmap->rowBytes;
       for (j = 0; j < w1; j++)
-        *p++ = reflect_byte (*bits++);
+       {
+         /* Bitswap XBM bytes to match how Mac does things.  */
+         unsigned char c = *bits++;
+         *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
+                                | (swap_nibble[(c>>4) & 0xf]));;
+       }
     }
 
   SetRect (&(bitmap->bounds), 0, 0, w, h);
@@ -589,17 +499,13 @@ XCreatePixmap (display, w, width, height, depth)
      Display *display;         /* not used */
      WindowPtr w;
      unsigned int width, height;
-     unsigned int depth;       /* not used */
+     unsigned int depth;
 {
   Pixmap pixmap;
   Rect r;
   QDErr err;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  SetPortWindowPort (w);
 
   SetRect (&r, 0, 0, width, height);
   err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
@@ -616,19 +522,28 @@ 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)
     return NULL;
 
+  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),
@@ -638,6 +553,7 @@ XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
            &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (pixmap));
+  SetGWorld (old_port, old_gdh);
   mac_free_bitmap (&bitmap);
 
   return pixmap;
@@ -656,19 +572,16 @@ XFillRectangle (display, w, gc, x, y, width, height)
 {
   Rect r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  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 */
 }
 
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
 static void
 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
      Display *display;
@@ -677,16 +590,22 @@ mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
+  CGrafPtr old_port;
+  GDHandle old_gdh;
   Rect r;
 
+  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));
   PaintRect (&r); /* using foreground color of gc */
   UnlockPixels (GetGWorldPixMap (p));
+
+  SetGWorld (old_port, old_gdh);
 }
+#endif
 
 
 /* Mac replacement for XDrawRectangle: dest is a window.  */
@@ -701,19 +620,16 @@ mac_draw_rectangle (display, w, gc, x, y, width, height)
 {
   Rect r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  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 */
 }
 
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
 /* Mac replacement for XDrawRectangle: dest is a Pixmap.  */
 
 static void
@@ -724,16 +640,22 @@ mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
+  CGrafPtr old_port;
+  GDHandle old_gdh;
   Rect r;
 
+  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));
   FrameRect (&r); /* using foreground color of gc */
   UnlockPixels (GetGWorldPixMap (p));
+
+  SetGWorld (old_port, old_gdh);
 }
+#endif
 
 
 static void
@@ -746,21 +668,34 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
      char *buf;
      int nchars, mode, bytes_per_char;
 {
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+  UInt32 textFlags, savedFlags;
+  if (!NILP(Vmac_use_core_graphics)) {
+    textFlags = kQDUseCGTextRendering;
+    savedFlags = SwapQDTextFlags(textFlags);
+  }
 #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);
+
+  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
 }
 
 
@@ -841,11 +776,7 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
 {
   Rect src_r, dest_r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (dest));
-#else
-  SetPort (dest);
-#endif
+  SetPortWindowPort (dest);
 
   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);
@@ -865,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)));
 }
 
 
@@ -881,11 +814,7 @@ mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
 {
   Rect src_r, dest_r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (dest));
-#else
-  SetPort (dest);
-#endif
+  SetPortWindowPort (dest);
 
   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);
@@ -907,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.  */
 
@@ -940,57 +853,33 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
      int dest_x, dest_y;
 {
 #if TARGET_API_MAC_CARBON
-  Rect gw_r, src_r, dest_r;
+  Rect src_r;
+  RgnHandle dummy = NewRgn (); /* For avoiding update events.  */
 
   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);
-
-  SetPort (GetWindowPort (w));
-
-  ForeColor (blackColor);
-  BackColor (whiteColor);
-
-  LockPortBits (GetWindowPort (w));
-  {
-    const BitMap *bitmap = GetPortBitMapForCopyBits (GetWindowPort (w));
-    CopyBits (bitmap, bitmap, &src_r, &dest_r, srcCopy, 0);
-  }
-  UnlockPortBits (GetWindowPort (w));
-
-  mac_set_colors (gc);
+  ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
+                   kScrollWindowNoOptions, dummy);
+  DisposeRgn (dummy);
 #else /* not TARGET_API_MAC_CARBON */
   Rect src_r, dest_r;
 
   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 */
 }
 
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
 /* Mac replacement for XCopyArea: dest must be Pixmap.  */
 
 static void
@@ -1003,8 +892,11 @@ mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
      unsigned int width, height;
      int dest_x, dest_y;
 {
+  CGrafPtr old_port;
+  GDHandle old_gdh;
   Rect src_r, dest_r;
 
+  GetGWorld (&old_port, &old_gdh);
   SetGWorld (dest, NULL);
   ForeColor (blackColor);
   BackColor (whiteColor);
@@ -1023,6 +915,8 @@ mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
 #endif /* not TARGET_API_MAC_CARBON */
   UnlockPixels (GetGWorldPixMap (dest));
   UnlockPixels (GetGWorldPixMap (src));
+
+  SetGWorld (old_port, old_gdh);
 }
 
 
@@ -1036,8 +930,11 @@ mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
      unsigned int width, height;
      int dest_x, dest_y;
 {
+  CGrafPtr old_port;
+  GDHandle old_gdh;
   Rect src_r, dest_r;
 
+  GetGWorld (&old_port, &old_gdh);
   SetGWorld (dest, NULL);
   ForeColor (blackColor);
   BackColor (whiteColor);
@@ -1058,34 +955,46 @@ mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
   UnlockPixels (GetGWorldPixMap (dest));
   UnlockPixels (GetGWorldPixMap (mask));
   UnlockPixels (GetGWorldPixMap (src));
+
+  SetGWorld (old_port, old_gdh);
 }
+#endif
 
 
 /* Mac replacement for XChangeGC.  */
 
 static void
-XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
-                XGCValues *xgcv)
+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;
 }
@@ -1105,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;
 }
 
 
@@ -1120,7 +1037,31 @@ 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);
+    }
+}
+
+
+/* Mac replacement for XSetBackground.  */
+
+void
+XSetBackground (display, gc, color)
+     Display *display;
+     GC gc;
+     unsigned long 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);
+    }
 }
 
 
@@ -1132,18 +1073,52 @@ XSetFont (display, gc, font)
      GC gc;
      XFontStruct *font;
 {
-  gc->font = font;
+  gc->xgcv.font = font;
 }
 
 
-static void
-XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
-                     int *direction,int *font_ascent,
-                     int *font_descent, XCharStruct *cs)
+/* Mac replacement for XSetWindowBackground.  */
+
+void
+XSetWindowBackground (display, w, color)
+     Display *display;
+     WindowPtr w;
+     unsigned long color;
 {
-  /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
-}
+#if !TARGET_API_MAC_CARBON
+  AuxWinHandle aw_handle;
+  CTabHandle ctab_handle;
+  ColorSpecPtr ct_table;
+  short ct_size;
+#endif
+  RGBColor bg_color;
+
+  bg_color.red = RED16_FROM_ULONG (color);
+  bg_color.green = GREEN16_FROM_ULONG (color);
+  bg_color.blue = BLUE16_FROM_ULONG (color);
 
+#if TARGET_API_MAC_CARBON
+  SetWindowContentColor (w, &bg_color);
+#else
+  if (GetAuxWin (w, &aw_handle))
+    {
+      ctab_handle = (*aw_handle)->awCTable;
+      HandToHand ((Handle *) &ctab_handle);
+      ct_table = (*ctab_handle)->ctTable;
+      ct_size = (*ctab_handle)->ctSize;
+      while (ct_size > -1)
+       {
+         if (ct_table->value == 0)
+           {
+             ct_table->rgb = bg_color;
+             CTabChanged (ctab_handle);
+             SetWinColor (w, (WCTabHandle) ctab_handle);
+           }
+         ct_size--;
+       }
+    }
+#endif
+}
 
 /* x_sync is a no-op on Mac.  */
 void
@@ -1153,42 +1128,34 @@ x_sync (f)
 }
 
 
-/* Remove calls to XFlush by defining XFlush to an empty replacement.
-   Calls to XFlush should be unnecessary because the X output buffer
-   is flushed automatically as needed by calls to XPending,
-   XNextEvent, or XWindowEvent according to the XFlush man page.
-   XTread_socket calls XPending.  Removing XFlush improves
-   performance.  */
-
-#if TARGET_API_MAC_CARBON
-#define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
-#else
-#define XFlush(DISPLAY)        (void) 0
-#endif
-
 /* Flush display of frame F, or of all frames if F is null.  */
 
-void
+static void
 x_flush (f)
      struct frame *f;
 {
 #if TARGET_API_MAC_CARBON
   BLOCK_INPUT;
-  if (f == NULL)
-    {
-      Lisp_Object rest, frame;
-      FOR_EACH_FRAME (rest, frame)
-       x_flush (XFRAME (frame));
-    }
-  else if (FRAME_X_P (f))
-    XFlush (FRAME_MAC_DISPLAY (f));
+  if (f)
+    QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
+  else
+    QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
   UNBLOCK_INPUT;
-#endif /* TARGET_API_MAC_CARBON */
+#endif
 }
 
 
-\f
-/* Return the struct mac_display_info corresponding to DPY.  There's
+/* Remove calls to XFlush by defining XFlush to an empty replacement.
+   Calls to XFlush should be unnecessary because the X output buffer
+   is flushed automatically as needed by calls to XPending,
+   XNextEvent, or XWindowEvent according to the XFlush man page.
+   XTread_socket calls XPending.  Removing XFlush improves
+   performance.  */
+
+#define XFlush(DISPLAY)        (void) 0
+
+\f
+/* Return the struct mac_display_info corresponding to DPY.  There's
    only one.  */
 
 struct mac_display_info *
@@ -1213,7 +1180,17 @@ static void
 x_update_begin (f)
      struct frame *f;
 {
-  /* Nothing to do.  */
+#if TARGET_API_MAC_CARBON
+  /* During update of a frame, availability of input events is
+     periodically checked with ReceiveNextEvent if
+     redisplay-dont-pause is nil.  That normally flushes window buffer
+     changes for every check, and thus screen update looks waving even
+     if no input is available.  So we disable screen updates during
+     update of a frame.  */
+  BLOCK_INPUT;
+  DisableScreenUpdates ();
+  UNBLOCK_INPUT;
+#endif
 }
 
 
@@ -1260,7 +1237,7 @@ x_update_window_begin (w)
        {
          int i;
 
-          for (i = 0; i < w->desired_matrix->nrows; ++i)
+         for (i = 0; i < w->desired_matrix->nrows; ++i)
            if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
              break;
 
@@ -1282,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
@@ -1298,8 +1280,8 @@ mac_draw_vertical_window_border (w, x, y0, y1)
    make sure that the mouse-highlight is properly redrawn.
 
    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. */
+   support.  Such windows don't have a cursor, so don't display it
+   here.  */
 
 static void
 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
@@ -1317,9 +1299,8 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
-      x_draw_vertical_border (w);
-
-      draw_window_fringes (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
 
       UNBLOCK_INPUT;
     }
@@ -1333,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;
 }
 
@@ -1352,21 +1325,13 @@ static void
 x_update_end (f)
      struct frame *f;
 {
-  /* 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.  */
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
-#else
-  SetPort (FRAME_MAC_WINDOW (f));
-#endif
-
-  mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
-
   /* Mouse highlight may be displayed again.  */
   FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
 
   BLOCK_INPUT;
+#if TARGET_API_MAC_CARBON
+  EnableScreenUpdates ();
+#endif
   XFlush (FRAME_MAC_DISPLAY (f));
   UNBLOCK_INPUT;
 }
@@ -1380,7 +1345,7 @@ static void
 XTframe_up_to_date (f)
      struct frame *f;
 {
-  if (FRAME_X_P (f))
+  if (FRAME_MAC_P (f))
     {
       struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
 
@@ -1434,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;
     }
 }
@@ -1466,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;
@@ -1481,18 +1444,15 @@ x_draw_fringe_bitmap (w, row, p)
       int oldVH = row->visible_height;
       row->visible_height = p->h;
       row->y -= rowY - p->y;
-      x_clip_to_row (w, row, gc);
+      x_clip_to_row (w, row, -1, gc);
       row->y = oldY;
       row->visible_height = oldVH;
     }
   else
-    x_clip_to_row (w, row, gc);
+    x_clip_to_row (w, row, -1, gc);
 
   if (p->bx >= 0 && !p->overlay_p)
     {
-      XGCValues gcv;
-      gcv.foreground = face->background;
-
 #if 0  /* MAC_TODO: stipple */
       /* In case the same realized face is used for fringes and
         for something displayed in the text (e.g. face `region' on
@@ -1504,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)
@@ -1517,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
@@ -1550,6 +1511,7 @@ XTreset_terminal_modes ()
 {
 }
 
+
 \f
 /***********************************************************************
                           Display Iterator
@@ -1678,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
        {
@@ -1735,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 *,
@@ -1743,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 *));
@@ -1953,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
 }
 
 
@@ -1977,13 +1960,18 @@ 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);
 }
 
 
+/* We prefer not to use XDrawImageString (srcCopy text transfer mode)
+   on Mac OS X because:
+   - Screen is double-buffered.  (In srcCopy mode, a text is drawn
+     into an offscreen graphics world first.  So performance gain
+     cannot be expected.)
+   - It lowers rendering quality.
+   - Some fonts leave garbage on cursor movement.  */
+
 /* Draw the background of glyph_string S.  If S->background_filled_p
    is non-zero don't draw it.  FORCE_P non-zero means draw the
    background even if it wouldn't be drawn normally.  This is used
@@ -2015,10 +2003,12 @@ x_draw_glyph_string_background (s, force_p)
        }
       else
 #endif
+#ifdef MAC_OS8
         if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
               || force_p)
+#endif
        {
          x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
                                     s->background_width,
@@ -2071,6 +2061,7 @@ x_draw_glyph_string_foreground (s)
        for (i = 0; i < s->nchars; ++i)
          char1b[i] = s->char2b[i].byte2;
 
+#ifdef MAC_OS8
       /* Draw text with XDrawString if background has already been
         filled.  Otherwise, use XDrawImageString.  (Note that
         XDrawImageString is usually faster than XDrawString.)  Always
@@ -2078,6 +2069,7 @@ x_draw_glyph_string_foreground (s)
         no chance that characters under a box cursor are invisible.  */
       if (s->for_overlaps_p
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
+#endif
        {
          /* Draw characters with 16-bit or 8-bit functions.  */
          if (s->two_byte_p)
@@ -2087,6 +2079,7 @@ x_draw_glyph_string_foreground (s)
            XDrawString (s->display, s->window, s->gc, x,
                         s->ybase - boff, char1b, s->nchars);
        }
+#ifdef MAC_OS8
       else
        {
          if (s->two_byte_p)
@@ -2096,6 +2089,7 @@ x_draw_glyph_string_foreground (s)
            XDrawImageString (s->display, s->window, s->gc, x,
                              s->ybase - boff, char1b, s->nchars);
        }
+#endif
     }
 }
 
@@ -2554,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);
 }
 
@@ -2590,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
@@ -2662,38 +2652,17 @@ x_draw_image_foreground (s)
 
   if (s->img->pixmap)
     {
+      x_set_glyph_string_clipping (s);
+
       if (s->img->mask)
-       {
-         Rect nr;
-         XRectangle clip_rect, image_rect, r;
-
-         get_glyph_string_clip_rect (s, &nr);
-         CONVERT_TO_XRECT (clip_rect, nr);
-         image_rect.x = x;
-         image_rect.y = y;
-         image_rect.width = s->slice.width;
-         image_rect.height = s->slice.height;
-         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-           mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
-                                    s->window, s->gc,
-                                    s->slice.x + r.x - x, s->slice.y + r.y - y,
-                                    r.width, r.height, r.x, r.y);
-       }
+       mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
+                                s->window, s->gc, s->slice.x, s->slice.y,
+                                s->slice.width, s->slice.height, x, y);
       else
        {
-         Rect nr;
-         XRectangle clip_rect, image_rect, r;
-
-         get_glyph_string_clip_rect (s, &nr);
-         CONVERT_TO_XRECT (clip_rect, nr);
-         image_rect.x = x;
-         image_rect.y = y;
-         image_rect.width = s->slice.width;
-         image_rect.height = s->slice.height;
-         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-           mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
-                          s->slice.x + r.x - x, s->slice.y + r.y - y,
-                          r.width, r.height, r.x, r.y);
+         mac_copy_area (s->display, s->img->pixmap,
+                        s->window, s->gc, s->slice.x, s->slice.y,
+                        s->slice.width, s->slice.height, x, y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2772,6 +2741,7 @@ x_draw_image_relief (s)
 }
 
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
 /* Draw the foreground of image glyph string S to PIXMAP.  */
 
 static void
@@ -2832,6 +2802,7 @@ x_draw_image_foreground_1 (s, pixmap)
     mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
                                  s->slice.width - 1, s->slice.height - 1);
 }
+#endif
 
 
 /* Draw part of the background of glyph string S.  X, Y, W, and H
@@ -2903,6 +2874,7 @@ x_draw_image_glyph_string (s)
       if (s->slice.y == 0)
        y += box_line_vwidth;
 
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
       if (s->img->mask)
        {
          /* Create a pixmap as large as the glyph string.  Fill it
@@ -2939,12 +2911,14 @@ x_draw_image_glyph_string (s)
            }
        }
       else
+#endif
        x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
 
       s->background_filled_p = 1;
     }
 
   /* Draw the foreground.  */
+#if 0 /* TODO: figure out if we need to do this on Mac.  */
   if (pixmap != 0)
     {
       x_draw_image_foreground_1 (s, pixmap);
@@ -2955,6 +2929,7 @@ x_draw_image_glyph_string (s)
       XFreePixmap (s->display, pixmap);
     }
   else
+#endif
     x_draw_image_foreground (s);
 
   /* If we must draw a relief around the image, do it.  */
@@ -3014,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);
        }
@@ -3041,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);
@@ -3220,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;
@@ -3336,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.
@@ -3431,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);
 }
 
@@ -3438,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);
 }
 
@@ -3480,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
@@ -3692,45 +3738,6 @@ x_get_keysym_name (keysym)
 }
 
 
-\f
-/* 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;
-
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
-#else
-  SetPort (FRAME_MAC_WINDOW (f));
-#endif
-
-  GlobalToLocal (&mouseLoc);
-  XSETINT (result->x, mouseLoc.h);
-  XSETINT (result->y, mouseLoc.v);
-
-  XSETFRAME (result->frame_or_window, f);
-
-  result->arg = Qnil;
-  return Qnil;
-}
-
 \f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
@@ -3748,6 +3755,7 @@ note_mouse_movement (frame, pos)
      FRAME_PTR frame;
      Point *pos;
 {
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
 #if TARGET_API_MAC_CARBON
   Rect r;
 #endif
@@ -3762,9 +3770,17 @@ note_mouse_movement (frame, pos)
   if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
 #endif
     {
-      frame->mouse_moved = 1;
-      last_mouse_scroll_bar = Qnil;
-      note_mouse_highlight (frame, -1, -1);
+      if (frame == dpyinfo->mouse_face_mouse_frame)
+       /* This case corresponds to LeaveNotify in X11.  */
+       {
+         /* If we move outside the frame, then we're certainly no
+            longer on any text in the frame.  */
+         clear_mouse_face (dpyinfo);
+         dpyinfo->mouse_face_mouse_frame = 0;
+         if (!dpyinfo->grabbed)
+           rif->define_frame_cursor (frame,
+                                     frame->output_data.mac->nontext_cursor);
+       }
     }
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
   else if (pos->h < last_mouse_glyph.left
@@ -3778,20 +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 void x_check_fullscreen P_ ((struct frame *));
-static void x_check_fullscreen_move P_ ((struct frame *));
 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
 
 
@@ -3912,6 +3919,20 @@ remember_mouse_glyph (f1, gx, gy)
 }
 
 
+static struct frame *
+mac_focus_frame (dpyinfo)
+     struct mac_display_info *dpyinfo;
+{
+  if (dpyinfo->x_focus_frame)
+    return dpyinfo->x_focus_frame;
+  else
+    /* Mac version may get events, such as a menu bar click, even when
+       all the frames are invisible.  In this case, we regard the
+       event came to the selected frame.  */
+    return SELECTED_FRAME ();
+}
+
+
 /* Return the current position of the mouse.
    *fp should be a frame which indicates which display to ask about.
 
@@ -3943,13 +3964,10 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 {
   Point mouse_pos;
   int ignore1, ignore2;
-  WindowPtr wp = FrontWindow ();
-  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_output *) GetWRefCon (wp))->mFP;
-
   BLOCK_INPUT;
 
   if (! NILP (last_mouse_scroll_bar) && insist == 0)
@@ -3962,11 +3980,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 
       last_mouse_scroll_bar = Qnil;
 
-#if TARGET_API_MAC_CARBON
-      SetPort (GetWindowPort (wp));
-#else
-      SetPort (wp);
-#endif
+      SetPortWindowPort (wp);
 
       GetMouse (&mouse_pos);
 
@@ -3985,119 +3999,401 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 }
 
 \f
-/***********************************************************************
-                              Tool-bars
- ***********************************************************************/
+/************************************************************************
+                        Toolkit scroll bars
+ ************************************************************************/
 
-/* Handle mouse button event on the tool-bar of frame F, at
-   frame-relative coordinates X/Y.  EVENT_TYPE is either ButtionPress
-   or ButtonRelase.  */
+#ifdef USE_TOOLKIT_SCROLL_BARS
 
-static void
-mac_handle_tool_bar_click (f, button_event)
-     struct frame *f;
-     EventRecord *button_event;
-{
-  int x = button_event->where.h;
-  int y = button_event->where.v;
+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));
 
-  if (button_event->what == mouseDown)
-    handle_tool_bar_click (f, x, y, 1, 0);
-  else
-    handle_tool_bar_click (f, x, y, 0,
-                          x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
-                                                    button_event->modifiers));
-}
+/* Last scroll bar part sent in x_scroll_bar_handle_*.  */
 
-\f
-/************************************************************************
-                        Scroll bars, general
- ************************************************************************/
+static int last_scroll_bar_part;
 
-/* Create a scroll bar and return the scroll bar vector for it.  W is
-   the Emacs window on which to create the scroll bar. TOP, LEFT,
-   WIDTH and HEIGHT are the pixel coordinates and dimensions of the
-   scroll bar. */
+static EventLoopTimerRef scroll_bar_timer;
 
-static struct scroll_bar *
-x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
-     struct window *w;
-     int top, left, width, height, disp_top, disp_height;
+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;
 {
-  struct frame *f = XFRAME (w->frame);
-  struct scroll_bar *bar
-    = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
-  Rect r;
-  ControlHandle ch;
+  EventRef event = NULL;
+  OSErr err;
 
-  BLOCK_INPUT;
+  err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
+                    kEventAttributeNone, &event);
+  if (err == noErr)
+    {
+      Point mouse_pos;
 
-  r.left = left;
-  r.top = disp_top;
-  r.right = left + width;
-  r.bottom = disp_top + disp_height;
+      GetMouse (&mouse_pos);
+      LocalToGlobal (&mouse_pos);
+      err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
+                              sizeof (Point), &mouse_pos);
+    }
+  if (err == noErr)
+    {
+      UInt32 modifiers = GetCurrentKeyModifiers ();
 
-#ifdef TARGET_API_MAC_CARBON
-  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
-                  kControlScrollBarProc, 0L);
-#else
-  ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
-                  0L);
-#endif
-  SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
-  SetControlReference (ch, (long) bar);
+      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;
 
-  XSETWINDOW (bar->window, w);
-  XSETINT (bar->top, top);
-  XSETINT (bar->left, left);
-  XSETINT (bar->width, width);
-  XSETINT (bar->height, height);
-  XSETINT (bar->start, 0);
-  XSETINT (bar->end, 0);
-  bar->dragging = Qnil;
+  if (event)
+    ReleaseEvent (event);
+}
 
-  /* Add bar to its frame's list of scroll bars.  */
-  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);
+static OSStatus
+install_scroll_bar_timer ()
+{
+  static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
 
-  UNBLOCK_INPUT;
-  return bar;
+  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 ();
 
-/* Draw BAR's handle in the proper position.
+  scroll_bar_timer_event_posted_p = 0;
 
-   If the handle is already drawn from START to END, don't bother
-   redrawing it, unless REBUILD is non-zero; in that case, always
-   redraw it.  (REBUILD is handy for drawing the handle after expose
-   events.)
+  return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
+}
 
-   Normally, we want to constrain the start and end of the handle to
-   fit inside its rectangle, but if the user is dragging the scroll
-   bar handle, we want to let them drag it down all the way, so that
-   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.  */
+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
-x_scroll_bar_set_handle (bar, start, end, rebuild)
+construct_scroll_bar_click (bar, part, bufp)
      struct scroll_bar *bar;
-     int start, end;
-     int rebuild;
+     int part;
+     struct input_event *bufp;
 {
-  int dragging = ! NILP (bar->dragging);
-  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-  int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
-  int length = end - start;
-
-  /* If the display is already accurate, do nothing.  */
-  if (! rebuild
-      && start == XINT (bar->start)
-      && end == XINT (bar->end))
-    return;
+  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);
+
+  return err;
+}
+
+static void
+x_scroll_bar_handle_press (bar, part_code, bufp)
+     struct scroll_bar *bar;
+     ControlPartCode part_code;
+     struct input_event *bufp;
+{
+  int part = control_part_code_to_scroll_bar_part (part_code);
+
+  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;
+{
+  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+
+  int value, viewsize, maximum;
+
+  if (whole == 0 || XINT (bar->track_height) == 0)
+    value = 0, viewsize = 1, maximum = 0;
+  else
+    {
+      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
+ ************************************************************************/
+
+/* Create a scroll bar and return the scroll bar vector for it.  W is
+   the Emacs window on which to create the scroll bar. TOP, LEFT,
+   WIDTH and HEIGHT are the pixel coordinates and dimensions of the
+   scroll bar. */
+
+static struct scroll_bar *
+x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
+     struct window *w;
+     int top, left, width, height, disp_top, disp_height;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct scroll_bar *bar
+    = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
+  Rect r;
+  ControlHandle ch;
+
+  BLOCK_INPUT;
+
+  r.left = left;
+  r.top = disp_top;
+  r.right = left + width;
+  r.bottom = disp_top + disp_height;
+
+#if TARGET_API_MAC_CARBON
+  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", width < disp_height,
+                  0, 0, 0, scrollBarProc, (long) bar);
+#endif
+  SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
+
+  XSETWINDOW (bar->window, w);
+  XSETINT (bar->top, top);
+  XSETINT (bar->left, left);
+  XSETINT (bar->width, width);
+  XSETINT (bar->height, 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);
+  bar->prev = Qnil;
+  XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
+  if (!NILP (bar->next))
+    XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+
+  UNBLOCK_INPUT;
+  return bar;
+}
+
+
+/* Draw BAR's handle in the proper position.
+
+   If the handle is already drawn from START to END, don't bother
+   redrawing it, unless REBUILD is non-zero; in that case, always
+   redraw it.  (REBUILD is handy for drawing the handle after expose
+   events.)
+
+   Normally, we want to constrain the start and end of the handle to
+   fit inside its rectangle, but if the user is dragging the scroll
+   bar handle, we want to let them drag it down all the way, so that
+   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;
+     int start, end;
+     int rebuild;
+{
+  int dragging = ! NILP (bar->dragging);
+  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+  FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+  int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+  int length = end - start;
+
+  /* If the display is already accurate, do nothing.  */
+  if (! rebuild
+      && start == XINT (bar->start)
+      && end == XINT (bar->end))
+    return;
 
   BLOCK_INPUT;
 
@@ -4140,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.  */
@@ -4161,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;
@@ -4178,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.  */
@@ -4197,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;
@@ -4240,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))
@@ -4265,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))
@@ -4292,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 */
 }
 
 
@@ -4334,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))
@@ -4342,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
@@ -4404,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));
-#ifdef 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));
-#ifdef TARGET_API_MAC_CARBON
-      DeactivateControl (ch);
-#else
-      SetControlMaximum (ch, XINT (-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.
 
@@ -4457,10 +4736,12 @@ 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;
 {
+  int win_y, top_range;
+
   if (! GC_WINDOWP (bar->window))
     abort ();
 
@@ -4484,7 +4765,7 @@ x_scroll_bar_handle_click (bar, part_code, er, bufp)
     case kControlPageDownPart:
       bufp->part = scroll_bar_below_handle;
       break;
-#ifdef TARGET_API_MAC_CARBON
+#if TARGET_API_MAC_CARBON
     default:
 #else
     case kControlIndicatorPart:
@@ -4495,8 +4776,27 @@ x_scroll_bar_handle_click (bar, part_code, er, bufp)
       bufp->part = scroll_bar_handle;
       break;
     }
+
+  win_y = XINT (bufp->y) - XINT (bar->top);
+  top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
+
+  win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
+
+  win_y -= 24;
+
+  if (! NILP (bar->dragging))
+    win_y -= XINT (bar->dragging);
+
+  if (win_y < 0)
+    win_y = 0;
+  if (win_y > top_range)
+    win_y = top_range;
+
+  XSETINT (bufp->x, win_y);
+  XSETINT (bufp->y, top_range);
 }
 
+#ifndef USE_TOOLKIT_SCROLL_BARS
 
 /* Handle some mouse motion while someone is dragging the scroll bar.
 
@@ -4531,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)
@@ -4544,16 +4845,17 @@ 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 = FrontWindow ();
-  Point mouse_pos;
-  struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
-  int win_y, top_range;
-
+  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
 #if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (wp));
+  WindowPtr wp = GetControlOwner (ch);
 #else
-  SetPort (wp);
+  WindowPtr wp = (*ch)->contrlOwner;
 #endif
+  Point mouse_pos;
+  struct frame *f = mac_window_to_frame (wp);
+  int win_y, top_range;
+
+  SetPortWindowPort (wp);
 
   GetMouse (&mouse_pos);
 
@@ -4592,8 +4894,23 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
 
   *time = last_mouse_movement_time;
 }
-\f
-/***********************************************************************
+
+
+/* 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
  ***********************************************************************/
 
@@ -4605,18 +4922,19 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
    mode lines must be clipped to the whole window.  */
 
 static void
-x_clip_to_row (w, row, gc)
+x_clip_to_row (w, row, area, gc)
      struct window *w;
      struct glyph_row *row;
+     int area;
      GC gc;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Rect clip_rect;
-  int window_y, window_width;
+  int window_x, window_y, window_width;
 
-  window_box (w, -1, 0, &window_y, &window_width, 0);
+  window_box (w, area, &window_x, &window_y, &window_width, 0);
 
-  clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
+  clip_rect.left = window_x;
   clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
   clip_rect.top = max (clip_rect.top, window_y);
   clip_rect.right = clip_rect.left + window_width;
@@ -4647,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.  */
@@ -4682,7 +4981,7 @@ x_draw_hollow_cursor (w, row)
   gc = dpyinfo->scratch_cursor_gc;
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
-  x_clip_to_row (w, row, gc);
+  x_clip_to_row (w, row, TEXT_AREA, gc);
   mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
   mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
 }
@@ -4753,7 +5052,7 @@ x_draw_bar_cursor (w, row, width, kind)
       width = min (cursor_glyph->pixel_width, width);
 
       w->phys_cursor_width = width;
-      x_clip_to_row (w, row, gc);
+      x_clip_to_row (w, row, TEXT_AREA, gc);
 
       if (kind == BAR_CURSOR)
        XFillRectangle (dpy, window, gc,
@@ -4780,7 +5079,7 @@ mac_define_frame_cursor (f, cursor)
      struct frame *f;
      Cursor cursor;
 {
-  /* MAC TODO */
+  SetThemeCursor (cursor);
 }
 
 
@@ -4945,7 +5244,8 @@ x_new_font (f, fontname)
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
 
-  FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+  FRAME_COLUMN_WIDTH (f) = fontp->average_width;
+  FRAME_SPACE_WIDTH (f) = fontp->space_width;
   FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
 
   compute_fringe_widths (f, 1);
@@ -4973,13 +5273,16 @@ x_new_font (f, fontname)
       XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
                FRAME_FONT (f));
 
+      /* Don't change the size of a tip frame; there's no point in
+        doing it because it's done in Fx_show_tip, and it leads to
+        problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
         x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
     }
 
   return build_string (fontp->full_name);
 }
-\f
+
 /* Give frame F the fontset named FONTSETNAME as its default font, and
    return the full name of that fontset.  FONTSETNAME may be a wildcard
    pattern; in that case, we choose some fontset that fits the pattern.
@@ -5008,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);
 }
@@ -5028,6 +5331,27 @@ xim_close_dpy (dpyinfo)
 
  */
 
+\f
+void
+mac_get_window_bounds (f, inner, outer)
+     struct frame *f;
+     Rect *inner, *outer;
+{
+#if TARGET_API_MAC_CARBON
+  GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
+  GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
+#else /* not TARGET_API_MAC_CARBON */
+  RgnHandle region = NewRgn ();
+
+  GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
+  *inner = (*region)->rgnBBox;
+  GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
+  *outer = (*region)->rgnBBox;
+  DisposeRgn (region);
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
 \f
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
@@ -5036,51 +5360,36 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Point pt;
+  int width_diff = 0, height_diff = 0;
   int flags = f->size_hint_flags;
+  Rect inner, outer;
 
-  pt.h = pt.v = 0;
+  /* We have nothing to do if the current position
+     is already for the top-left corner.  */
+  if (! ((flags & XNegative) || (flags & YNegative)))
+    return;
 
-  /* Find the position of the outside upper-left corner of
+  /* Find the offsets of the outside upper-left corner of
      the inner window, with respect to the outer window.  */
-  if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
-    {
-      GrafPtr savePort;
-      GetPort (&savePort);
-
-#if TARGET_API_MAC_CARBON
-      SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
-#else
-      SetPort (FRAME_MAC_WINDOW (f));
-#endif
+  mac_get_window_bounds (f, &inner, &outer);
 
-#if TARGET_API_MAC_CARBON
-      {
-        Rect r;
-
-        GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
-        SetPt(&pt, r.left,  r.top);
-      }
-#else /* not TARGET_API_MAC_CARBON */
-      SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left,  FRAME_MAC_WINDOW (f)->portRect.top);
-#endif /* not TARGET_API_MAC_CARBON */
-      LocalToGlobal (&pt);
-      SetPort (savePort);
-    }
+  width_diff = (outer.right - outer.left) - (inner.right - inner.left);
+  height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
 
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
-                  - 2 * f->border_width - pt.h
+                   - width_diff
                   - FRAME_PIXEL_WIDTH (f)
                   + f->left_pos);
-  /* NTEMACS_TODO: Subtract menubar height?  */
+
   if (flags & YNegative)
     f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
-                 - 2 * f->border_width - pt.v
+                 - height_diff
                  - FRAME_PIXEL_HEIGHT (f)
                  + f->top_pos);
+
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
@@ -5099,8 +5408,6 @@ x_set_offset (f, xoff, yoff, change_gravity)
      register int xoff, yoff;
      int change_gravity;
 {
-  int modified_top, modified_left;
-
   if (change_gravity > 0)
     {
       f->top_pos = yoff;
@@ -5117,11 +5424,55 @@ x_set_offset (f, xoff, yoff, change_gravity)
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
-  modified_left = f->left_pos;
-  modified_top = f->top_pos;
-
-  MoveWindow (f->output_data.mac->mWP, modified_left + 6,
-             modified_top + 42, false);
+#if TARGET_API_MAC_CARBON
+  MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
+  /* If the title bar is completely outside the screen, adjust the
+     position. */
+  ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
+                          kWindowConstrainMoveRegardlessOfFit
+                          | kWindowConstrainAllowPartial, NULL, NULL);
+  x_real_positions (f, &f->left_pos, &f->top_pos);
+#else
+  {
+    Rect inner, outer, screen_rect, dummy;
+    RgnHandle region = NewRgn ();
+
+    mac_get_window_bounds (f, &inner, &outer);
+    f->x_pixels_diff = inner.left - outer.left;
+    f->y_pixels_diff = inner.top - outer.top;
+    MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
+               f->top_pos + f->y_pixels_diff, false);
+
+    /* If the title bar is completely outside the screen, adjust the
+       position.  The variable `outer' holds the title bar rectangle.
+       The variable `inner' holds slightly smaller one than `outer',
+       so that the calculation of overlapping may not become too
+       strict.  */
+    GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
+    outer = (*region)->rgnBBox;
+    DisposeRgn (region);
+    inner = outer;
+    InsetRect (&inner, 8, 8);
+    screen_rect = qd.screenBits.bounds;
+    screen_rect.top += GetMBarHeight ();
+
+    if (!SectRect (&inner, &screen_rect, &dummy))
+      {
+       if (inner.right <= screen_rect.left)
+         f->left_pos = screen_rect.left;
+       else if (inner.left >= screen_rect.right)
+         f->left_pos = screen_rect.right - (outer.right - outer.left);
+
+       if (inner.bottom <= screen_rect.top)
+         f->top_pos = screen_rect.top;
+       else if (inner.top >= screen_rect.bottom)
+         f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
+
+       MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
+                   f->top_pos + f->y_pixels_diff, false);
+      }
+  }
+#endif
 
   UNBLOCK_INPUT;
 }
@@ -5154,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
@@ -5228,7 +5584,6 @@ x_set_mouse_pixel_position (f, pix_x, pix_y)
   UNBLOCK_INPUT;
 #endif
 }
-
 \f
 /* focus shifting, raising and lowering.  */
 
@@ -5255,21 +5610,31 @@ x_unfocus_frame (f)
 }
 
 /* Raise frame F.  */
+
 void
 x_raise_frame (f)
      struct frame *f;
 {
   if (f->async_visible)
-    SelectWindow (FRAME_MAC_WINDOW (f));
+    {
+      BLOCK_INPUT;
+      SelectWindow (FRAME_MAC_WINDOW (f));
+      UNBLOCK_INPUT;
+    }
 }
 
 /* Lower frame F.  */
+
 void
 x_lower_frame (f)
      struct frame *f;
 {
   if (f->async_visible)
-    SendBehind (FRAME_MAC_WINDOW (f), nil);
+    {
+      BLOCK_INPUT;
+      SendBehind (FRAME_MAC_WINDOW (f), nil);
+      UNBLOCK_INPUT;
+    }
 }
 
 static void
@@ -5285,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.
@@ -5309,16 +5721,37 @@ 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);
+#if TARGET_API_MAC_CARBON
+       if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
+         {
+           struct frame *sf = SELECTED_FRAME ();
+           if (!FRAME_MAC_P (sf))
+             RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
+                               kWindowCenterOnMainScreen);
+           else
+             RepositionWindow (FRAME_MAC_WINDOW (f),
+                               FRAME_MAC_WINDOW (sf),
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+                               kWindowCascadeStartAtParentWindowScreen
+#else
+                               kWindowCascadeOnParentWindowScreen
+#endif
+                               );
+           x_real_positions (f, &f->left_pos, &f->top_pos);
+         }
+       else
+#endif
+         x_set_offset (f, f->left_pos, f->top_pos, 0);
 
       f->output_data.mac->asked_for_visible = 1;
 
+      SelectWindow (FRAME_MAC_WINDOW (f));
+      CollapseWindow (FRAME_MAC_WINDOW (f), false);
       ShowWindow (FRAME_MAC_WINDOW (f));
     }
 
   XFlush (FRAME_MAC_DISPLAY (f));
 
-#if 0 /* MAC_TODO */
   /* Synchronize to ensure Emacs knows the frame is visible
      before we do anything else.  We do this loop with input not blocked
      so that incoming events are handled.  */
@@ -5362,9 +5795,6 @@ x_make_frame_visible (f)
        FRAME_SAMPLE_VISIBILITY (f);
       }
   }
-#else
-  UNBLOCK_INPUT;
-#endif /* MAC_TODO */
 }
 
 /* Change from mapped state to withdrawn state.  */
@@ -5375,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.  */
@@ -5402,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
@@ -5427,10 +5879,18 @@ x_free_frame_resources (f)
      struct frame *f;
 {
   struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+  WindowPtr wp = FRAME_MAC_WINDOW (f);
 
   BLOCK_INPUT;
 
-  DisposeWindow (FRAME_MAC_WINDOW (f));
+  if (wp != tip_window)
+    remove_window_handler (wp);
+
+  DisposeWindow (wp);
+  if (wp == tip_window)
+    /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
+       closed' event.  So we reset tip_window here.  */
+    tip_window = NULL;
 
   free_frame_menubar (f);
 
@@ -5439,6 +5899,9 @@ x_free_frame_resources (f)
 
   x_free_gcs (f);
 
+  if (FRAME_SIZE_HINTS (f))
+    xfree (FRAME_SIZE_HINTS (f));
+
   xfree (f->output_data.mac);
   f->output_data.mac = NULL;
 
@@ -5491,143 +5954,39 @@ x_wm_set_size_hint (f, flags, user_position)
      long flags;
      int user_position;
 {
-#if 0 /* MAC_TODO: connect this to the Appearance Manager */
-  XSizeHints size_hints;
-
-#ifdef USE_X_TOOLKIT
-  Arg al[2];
-  int ac = 0;
-  Dimension widget_width, widget_height;
-  Window window = XtWindow (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
-  Window window = FRAME_X_WINDOW (f);
-#endif /* not USE_X_TOOLKIT */
-
-  /* Setting PMaxSize caused various problems.  */
-  size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
-
-  size_hints.x = f->left_pos;
-  size_hints.y = f->top_pos;
-
-#ifdef USE_X_TOOLKIT
-  XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
-  XtSetArg (al[ac], XtNheight, &widget_height); ac++;
-  XtGetValues (f->output_data.x->widget, al, ac);
-  size_hints.height = widget_height;
-  size_hints.width = widget_width;
-#else /* not USE_X_TOOLKIT */
-  size_hints.height = FRAME_PIXEL_HEIGHT (f);
-  size_hints.width = FRAME_PIXEL_WIDTH (f);
-#endif /* not USE_X_TOOLKIT */
-
-  size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
-  size_hints.height_inc = FRAME_LINE_HEIGHT (f);
-  size_hints.max_width
-    = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
-  size_hints.max_height
-    = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
-
-  /* Calculate the base and minimum sizes.
-
-     (When we use the X toolkit, we don't do it here.
-     Instead we copy the values that the widgets are using, below.)  */
-#ifndef USE_X_TOOLKIT
-  {
-    int base_width, base_height;
-    int min_rows = 0, min_cols = 0;
+  int base_width, base_height, width_inc, height_inc;
+  int min_rows = 0, min_cols = 0;
+  XSizeHints *size_hints;
 
-    base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
-    base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
+  base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
+  base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
+  width_inc = FRAME_COLUMN_WIDTH (f);
+  height_inc = FRAME_LINE_HEIGHT (f);
 
-    check_frame_size (f, &min_rows, &min_cols);
+  check_frame_size (f, &min_rows, &min_cols);
 
-    /* The window manager uses the base width hints to calculate the
-       current number of rows and columns in the frame while
-       resizing; min_width and min_height aren't useful for this
-       purpose, since they might not give the dimensions for a
-       zero-row, zero-column frame.
-
-       We use the base_width and base_height members if we have
-       them; otherwise, we set the min_width and min_height members
-       to the size for a zero x zero frame.  */
-
-#ifdef HAVE_X11R4
-    size_hints.flags |= PBaseSize;
-    size_hints.base_width = base_width;
-    size_hints.base_height = base_height;
-    size_hints.min_width  = base_width + min_cols * size_hints.width_inc;
-    size_hints.min_height = base_height + min_rows * size_hints.height_inc;
-#else
-    size_hints.min_width = base_width;
-    size_hints.min_height = base_height;
-#endif
-  }
-
-  /* If we don't need the old flags, we don't need the old hint at all.  */
-  if (flags)
+  size_hints = FRAME_SIZE_HINTS (f);
+  if (size_hints == NULL)
     {
-      size_hints.flags |= flags;
-      goto no_read;
+      size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
+      bzero (size_hints, sizeof (XSizeHints));
     }
-#endif /* not USE_X_TOOLKIT */
-
-  {
-    XSizeHints hints;          /* Sometimes I hate X Windows... */
-    long supplied_return;
-    int value;
-
-#ifdef HAVE_X11R4
-    value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
-                              &supplied_return);
-#else
-    value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
-#endif
-
-#ifdef USE_X_TOOLKIT
-    size_hints.base_height = hints.base_height;
-    size_hints.base_width = hints.base_width;
-    size_hints.min_height = hints.min_height;
-    size_hints.min_width = hints.min_width;
-#endif
-
-    if (flags)
-      size_hints.flags |= flags;
-    else
-      {
-       if (value == 0)
-         hints.flags = 0;
-       if (hints.flags & PSize)
-         size_hints.flags |= PSize;
-       if (hints.flags & PPosition)
-         size_hints.flags |= PPosition;
-       if (hints.flags & USPosition)
-         size_hints.flags |= USPosition;
-       if (hints.flags & USSize)
-         size_hints.flags |= USSize;
-      }
-  }
-
-#ifndef USE_X_TOOLKIT
- no_read:
-#endif
 
-#ifdef PWinGravity
-  size_hints.win_gravity = f->win_gravity;
-  size_hints.flags |= PWinGravity;
+  size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
+  size_hints->width_inc  = width_inc;
+  size_hints->height_inc = height_inc;
+  size_hints->min_width  = base_width + min_cols * width_inc;
+  size_hints->min_height = base_height + min_rows * height_inc;
+  size_hints->base_width  = base_width;
+  size_hints->base_height = base_height;
 
-  if (user_position)
+  if (flags)
+    size_hints->flags = flags;
+  else if (user_position)
     {
-      size_hints.flags &= ~ PPosition;
-      size_hints.flags |= USPosition;
+      size_hints->flags &= ~ PPosition;
+      size_hints->flags |= USPosition;
     }
-#endif /* PWinGravity */
-
-#ifdef HAVE_X11R4
-  XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
-#else
-  XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
-#endif
-#endif /* MAC_TODO */
 }
 
 #if 0 /* MAC_TODO: hide application instead of iconify? */
@@ -5725,196 +6084,453 @@ 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.  */
-
-struct font_info *
-x_get_font_info (f, font_idx)
-     FRAME_PTR f;
-     int font_idx;
+/* An XLFD pattern is divided into blocks delimited by '*'.  This
+   structure holds information for each block.  */
+struct xlfdpat_block
 {
-  return (FRAME_MAC_FONT_TABLE (f) + font_idx);
-}
+  /* Length of the pattern string in this block.  Non-zero except for
+     the first and the last blocks.  */
+  int len;
 
-/* the global font name table */
-char **font_name_table = NULL;
-int font_name_table_size = 0;
-int font_name_count = 0;
+  /* 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;
 
-#if 0
-/* compare two strings ignoring case */
-static int
-stricmp (const char *s, const char *t)
-{
-  for ( ; tolower (*s) == tolower (*t); s++, t++)
-    if (*s == '\0')
-      return 0;
-  return tolower (*s) - tolower (*t);
-}
+  /* Last character of the pattern string.  Must not be '?'.  */
+  unsigned char last_char;
 
-/* compare two strings ignoring case and handling wildcard */
-static int
-wildstrieq (char *s1, char *s2)
-{
-  if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
-    return true;
+  /* 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];
 
-  return stricmp (s1, s2) == 0;
-}
+  /* 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;
+};
 
-/* Assume parameter 1 is fully qualified, no wildcards. */
-static int
-mac_font_pattern_match (fontname, pattern)
-    char * fontname;
-    char * pattern;
+struct xlfdpat
 {
-  char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
-  char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
-  char *ptr;
+  /* 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;
 
-  /* Copy fontname so we can modify it during comparison.  */
-  strcpy (font_name_copy, fontname);
+  /* Number of characters except '*'s and trailing '?'s in the
+     normalized pattern string.  */
+  int nchars;
 
-  ptr = regex;
-  *ptr++ = '^';
+  /* Number of trailing '?'s in the normalized pattern string.  */
+  int trailing_anychars;
 
-  /* Turn pattern into a regexp and do a regexp match.  */
-  for (; *pattern; pattern++)
+  /* 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 (*pattern == '?')
-        *ptr++ = '.';
-      else if (*pattern == '*')
-        {
-          *ptr++ = '.';
-          *ptr++ = '*';
-        }
-      else
-        *ptr++ = *pattern;
+      if (pat->buf)
+       {
+         if (pat->blocks)
+           xfree (pat->blocks);
+         xfree (pat->buf);
+       }
+      xfree (pat);
     }
-  *ptr = '$';
-  *(ptr + 1) = '\0';
-
-  return (fast_c_string_match_ignore_case (build_string (regex),
-                                           font_name_copy) >= 0);
 }
 
-/* Two font specs are considered to match if their foundry, family,
-   weight, slant, and charset match.  */
-static int
-mac_font_match (char *mf, char *xf)
+static struct xlfdpat *
+xlfdpat_create (pattern)
+     char *pattern;
 {
-  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];
+  struct xlfdpat *pat;
+  int nblocks, i, skip;
+  unsigned char last_char, *p, *q, *anychar_head;
+  struct xlfdpat_block *blk;
 
-  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);
+  pat = xmalloc (sizeof (struct xlfdpat));
+  if (pat == NULL)
+    goto error;
 
-  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);
+  pat->buf = xmalloc (strlen (pattern) + 1);
+  if (pat->buf == NULL)
+    goto error;
 
-  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);
-}
-#endif
+  /* 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;
 
-static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
+      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);
 
-static void
-decode_mac_font_name (char *name, int size, short scriptcode)
-{
-  Lisp_Object coding_system;
-  struct coding_system coding;
-  char *buf;
+  if (anychar_head == NULL && nblocks == 1)
+    {
+      /* The pattern is exact.  */
+      pat->blocks = NULL;
+      return pat;
+    }
 
-  switch (scriptcode)
+  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++)
     {
-    case smTradChinese:
-      coding_system = Qbig5;
-      break;
-    case smSimpChinese:
-      coding_system = Qcn_gb;
-      break;
-    case smJapanese:
-      coding_system = Qsjis;
-      break;
-    case smKorean:
-      coding_system = Qeuc_kr;
-      break;
-    default:
-      return;
+      blk->pattern = p;
+      while (*p != '*')
+       p++;
+      blk->len = p - blk->pattern;
+      p++;
     }
+  blk->pattern = p;
+  blk->len = q - blk->pattern;
 
-  setup_coding_system (coding_system, &coding);
-  coding.src_multibyte = 0;
-  coding.dst_multibyte = 1;
-  coding.mode |= CODING_MODE_LAST_BLOCK;
-  coding.composing = COMPOSITION_DISABLED;
-  buf = (char *) alloca (size);
+  /* 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';
 
-  decode_coding (&coding, name, buf, strlen (name), size - 1);
-  bcopy (buf, name, coding.produced);
-  name[coding.produced] = '\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;
+{
+  return (pat)->blocks == NULL;
 }
 
+/* Return the first string in STRING + 0, ..., STRING + START_MAX such
+   that the pattern in *BLK matches with its prefix.  Return NULL
+   there is no such strings.  STRING must be lowered in advance.  */
 
 static char *
-mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
+xlfdpat_block_match_1 (blk, string, start_max)
+     struct xlfdpat_block *blk;
+     unsigned char *string;
+     int start_max;
 {
-  char foundry[32], family[32], cs[32];
-  char xf[256], *result, *p;
+  int start, infinity;
+  unsigned char *p, *s;
 
-  if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
+  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
     {
-      strcpy(foundry, "Apple");
-      strcpy(family, name);
+      /* Check the last character of the pattern. */
+      s = string + blk->len - 1;
+      do
+       {
+         start += blk->skip[*(s + start)];
+       }
+      while (start <= start_max);
 
-      switch (scriptcode)
-      {
-      case smTradChinese:
-        strcpy(cs, "big5-0");
-        break;
-      case smSimpChinese:
-        strcpy(cs, "gb2312.1980-0");
-        break;
-      case smJapanese:
-        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:
-        strcpy(cs, "ksc5601.1989-0");
-        break;
-      default:
-        strcpy(cs, "mac-roman");
-        break;
-      }
-    }
+      if (start < infinity)
+       /* Couldn't find the last character.  */
+       return NULL;
 
-  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);
+      /* No less than `infinity' means we could find the last
+        character at `s[start - infinity]'.  */
+      start -= infinity;
 
-  result = (char *) xmalloc (strlen (xf) + 1);
-  strcpy (result, xf);
-  for (p = result; *p; p++)
-    *p = tolower(*p);
-  return result;
-}
+      /* Check the remaining characters.  We prefer making no-'?'
+        cases faster because the use of '?' is really rare.  */
+      p = blk->pattern;
+      s = string + start;
+      do
+       {
+         while (*p++ == *s++)
+           ;
+       }
+      while (*(p - 1) == '?');
+
+      if (*(p - 1) == '\0')
+       /* Matched.  */
+       return string + start;
+
+      /* Didn't match.  */
+      start += blk->last_char_skip;
+    }
+  while (start <= start_max);
+
+  return NULL;
+}
+
+#define xlfdpat_block_match(b, s, m) \
+  ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
+   : xlfdpat_block_match_1 (b, s, m))
+
+/* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
+   matches with STRING.  STRING must be lowered in advance.  */
+
+static int
+xlfdpat_match (pat, string)
+     struct xlfdpat *pat;
+     unsigned char *string;
+{
+  int str_len, nblocks, i, start_max;
+  struct xlfdpat_block *blk;
+  unsigned char *s;
+
+  xassert (pat->nblocks > 0);
+
+  if (xlfdpat_exact_p (pat))
+    return strcmp (pat->buf, string) == 0;
+
+  /* The number of the characters in the string must not be smaller
+     than that in the pattern.  */
+  str_len = strlen (string);
+  if (str_len < pat->nchars + pat->trailing_anychars)
+    return 0;
+
+  /* Chop off the trailing '?'s.  */
+  str_len -= pat->trailing_anychars;
+
+  /* The last block.  When it is non-empty, it must match at the end
+     of the string.  */
+  nblocks = pat->nblocks;
+  blk = pat->blocks + (nblocks - 1);
+  if (nblocks == 1)
+    /* The last block is also the first one.  */
+    return (str_len == blk->len
+           && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
+  else if (blk->len != 0)
+    if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
+      return 0;
+
+  /* The first block.  When it is non-empty, it must match at the
+     beginning of the string.  */
+  blk = pat->blocks;
+  if (blk->len != 0)
+    {
+      s = xlfdpat_block_match (blk, string, 0);
+      if (s == NULL)
+       return 0;
+      string = s + blk->len;
+    }
+
+  /* The rest of the blocks.  */
+  start_max = str_len - pat->nchars;
+  for (i = 1, blk++; i < nblocks - 1; i++, blk++)
+    {
+      s = xlfdpat_block_match (blk, string, start_max);
+      if (s == NULL)
+       return 0;
+      start_max -= s - string;
+      string = s + blk->len;
+    }
+
+  return 1;
+}
+
+\f
+/***********************************************************************
+                               Fonts
+ ***********************************************************************/
+
+/* 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 ()
+{
+  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 (!(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;
+
+      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 result;
+}
+
+
+static void
+decode_mac_font_name (name, size, coding_system)
+     char *name;
+     int size;
+     Lisp_Object coding_system;
+{
+  struct coding_system coding;
+  char *buf, *p;
+
+  for (p = name; *p; p++)
+    if (!isascii (*p) || iscntrl (*p))
+      break;
+
+  if (*p == '\0'
+      || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
+    return;
+
+  setup_coding_system (coding_system, &coding);
+  coding.src_multibyte = 0;
+  coding.dst_multibyte = 1;
+  coding.mode |= CODING_MODE_LAST_BLOCK;
+  coding.composing = COMPOSITION_DISABLED;
+  buf = (char *) alloca (size);
+
+  decode_coding (&coding, name, buf, strlen (name), size - 1);
+  bcopy (buf, name, coding.produced);
+  name[coding.produced] = '\0';
+}
+
+
+static char *
+mac_to_x_fontname (name, size, style, charset)
+     char *name;
+     int size;
+     Style style;
+     char *charset;
+{
+  Str31 foundry, cs;
+  Str255 family;
+  char xf[256], *result;
+  unsigned char *p;
+
+  if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
+    charset = cs;
+  else
+    {
+      strcpy(foundry, "Apple");
+      strcpy(family, name);
+    }
+
+  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 = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
+  sprintf (result, "-%s-%s-%s", foundry, family, xf);
+  for (p = result; *p; p++)
+    /* On Mac OS X 10.3, tolower also converts non-ASCII characters
+       for some locales.  */
+    if (isascii (*p))
+      *p = tolower (*p);
+  return result;
+}
 
 
 /* Convert an X font spec to the corresponding mac font name, which
@@ -5925,41 +6541,55 @@ mac_to_x_fontname (char *name, int size, Style style, short 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)
-    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);
 
-  if (!NILP (coding_system))
+  for (p = mf_decoded; *p; p++)
+    if (!isascii (*p) || iscntrl (*p))
+      break;
+
+  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';
     }
 }
@@ -5970,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 *));
@@ -5994,178 +6624,193 @@ static void
 init_font_name_table ()
 {
 #if TARGET_API_MAC_CARBON
-  SInt32 sv;
-
-  if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
+  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)
     {
-      FMFontFamilyIterator ffi;
-      FMFontFamilyInstanceIterator ffii;
-      FMFontFamily ff;
+      FMDisposeFontFamilyInstanceIterator (&ffii);
+      return;
+    }
 
-      /* 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 ();
 
-      while (FMGetNextFontFamily (&ffi, &ff) == noErr)
-       {
-         Str255 name;
-         FMFont font;
-         FMFontStyle style;
-         FMFontSize size;
-         SInt16 sc;
+  GCPRO1 (text_encoding_info_alist);
 
-         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;
+      Lisp_Object text_encoding_info;
 
-         sc = FontToScript (ff);
-         decode_mac_font_name (name, sizeof (name), sc);
+      if (FMGetFontFamilyName (ff, name) != noErr)
+       break;
+      p2cstr (name);
+      if (*name == '.')
+       continue;
 
-         /* Point the instance iterator at the current font family.  */
-         if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
-           break;
+      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);
 
-         while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
-                == noErr)
+      /* 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));
+
+         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 */
+}
+
+
+void
+mac_clear_font_name_table ()
+{
+  int i;
+
+  for (i = 0; i < font_name_count; i++)
+    xfree (font_name_table[i]);
+  xfree (font_name_table);
+  font_name_table = NULL;
+  font_name_table_size = font_name_count = 0;
 }
 
 
@@ -6191,11 +6836,14 @@ mac_do_list_fonts (pattern, maxnames)
      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;
+  int exact;
+
+  if (font_name_table == NULL)  /* Initialize when first used.  */
+    init_font_name_table ();
 
   for (i = 0; i < XLFD_SCL_LAST; i++)
     scl_val[i] = -1;
@@ -6213,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)
@@ -6231,127 +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++ = '^';
-
-  /* Turn pattern into a regexp and do a regexp match.  */
-  for (; *pattern; pattern++)
-    {
-      if (*pattern == '?')
-        *ptr++ = '.';
-      else if (*pattern == '*')
-        {
-          *ptr++ = '.';
-          *ptr++ = '*';
-        }
-      else
-        *ptr++ = tolower (*pattern);
-    }
-  *ptr = '$';
-  *(ptr + 1) = '\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 = build_string (font_name_table[i]);
-      if (fast_string_match (pattern_regex, fontname) >= 0)
+      if (xlfdpat_match (pat, font_name_table[i]))
        {
-         font_list = Fcons (fontname, font_list);
-
-          n_fonts++;
-          if (maxnames > 0 && n_fonts >= maxnames)
-            break;
+         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 = build_string (scaled);
-         if (fast_string_match (pattern_regex, fontname) >= 0)
-           {
-             font_list = Fcons (fontname, font_list);
+                  ptr + sizeof ("-0-0-0-0-m-0-") - 1);
 
-             n_fonts++;
-             if (maxnames > 0 && n_fonts >= maxnames)
-               break;
+         if (xlfdpat_match (pat, scaled))
+           {
+             font_list = Fcons (build_string (scaled), font_list);
+             xfree (scaled);
+             if (exact || maxnames > 0 && ++n_fonts >= maxnames)
+                 break;
            }
+         else
+           xfree (scaled);
        }
     }
+
+  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;
 
-  if (font_name_table == NULL)  /* Initialize when first used.  */
-    init_font_name_table ();
+  xassert (size <= 0);
+
+  patterns = Fassoc (pattern, Valternate_fontname_alist);
+  if (NILP (patterns))
+    patterns = Fcons (pattern, Qnil);
 
-  if (dpyinfo)
+  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;
        }
-    }
 
-  newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
+      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 */
+      /* Now store the result in the cache.  */
+      XSETCAR (XCDR (dpyinfo->name_list_element),
+              Fcons (Fcons (key, list),
+                     XCAR (XCDR (dpyinfo->name_list_element))));
 
-  if (dpyinfo)
-    {
-      XSETCDR (dpyinfo->name_list_element,
-              Fcons (Fcons (key, newlist),
-                     XCDR (dpyinfo->name_list_element)));
+    label_cached:
+      if (NILP (list)) continue; /* Try the remaining alternatives.  */
     }
- label_cached:
 
-  return newlist;
+  return list;
 }
 
 
@@ -6391,12 +7040,8 @@ x_font_min_bounds (font, w, h)
      MacFontStruct *font;
      int *w, *h;
 {
-  /*
-   * TODO: Windows does not appear to offer min bound, only
-   * average and maximum width, and maximum height.
-   */
   *h = FONT_HEIGHT (font);
-  *w = FONT_WIDTH (font);
+  *w = font->min_bounds.width;
 }
 
 
@@ -6406,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;
 {
@@ -6474,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
@@ -6486,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;
@@ -6521,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 ||
@@ -6609,29 +7267,66 @@ 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;
+       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;
-            font->per_char[c - 0x20].width =
-             font->per_char[c - 0x20].rbearing = CharWidth (c);
-          }
+           ch = c;
+           char_width = CharWidth (ch);
+           QDTextBounds (1, &ch, &char_bounds);
+           STORE_XCHARSTRUCT (font->per_char[c - 0x20],
+                              char_width, char_bounds);
+           /* Some Japanese fonts (in SJIS encoding) return 0 as the
+              character width of 0x7f.  */
+           if (char_width > 0)
+             {
+               min_width = min (min_width, char_width);
+               max_width = max (max_width, char_width);
+             }
+           if (!EmptyRect (&char_bounds))
+             {
+               SetRect (&min_bounds,
+                        max (min_bounds.left, char_bounds.left),
+                        max (min_bounds.top, char_bounds.top),
+                        min (min_bounds.right, char_bounds.right),
+                        min (min_bounds.bottom, char_bounds.bottom));
+               UnionRect (&max_bounds, &char_bounds, &max_bounds);
+             }
+         }
+       STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
+       STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
+       if (min_width == max_width
+           && max_bounds.left >= 0 && max_bounds.right <= max_width)
+         {
+           /* Fixed width and no overhangs.  */
+           xfree (font->per_char);
+           font->per_char = NULL;
+         }
       }
     }
 
@@ -6643,6 +7338,18 @@ XLoadQueryFont (Display *dpy, char *fontname)
 }
 
 
+void
+mac_unload_font (dpyinfo, font)
+     struct mac_display_info *dpyinfo;
+     XFontStruct *font;
+{
+  xfree (font->full_name);
+  if (font->per_char)
+    xfree (font->per_char);
+  xfree (font);
+}
+
+
 /* Load font named FONTNAME of the size SIZE for frame F, and return a
    pointer to the structure font_info while allocating it dynamically.
    If SIZE is 0, load any size of font.
@@ -6676,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.  */
   {
@@ -6685,15 +7394,11 @@ 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);
+    UNBLOCK_INPUT;
     if (!font)
       return NULL;
 
@@ -6722,15 +7427,45 @@ 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);
 
-    fontp->full_name = fontp->name;
+    if (font->min_bounds.width == font->max_bounds.width)
+      {
+       /* Fixed width font.  */
+       fontp->average_width = fontp->space_width = font->min_bounds.width;
+      }
+    else
+      {
+       XChar2b char2b;
+       XCharStruct *pcm;
 
-    fontp->size = font->max_bounds.width;
-    fontp->height = FONT_HEIGHT (font);
-    {
-      /* For some font, ascent and descent in max_bounds field is
+       char2b.byte1 = 0x00, char2b.byte2 = 0x20;
+       pcm = mac_per_char_metric (font, &char2b, 0);
+       if (pcm)
+         fontp->space_width = pcm->width;
+       else
+         fontp->space_width = FONT_WIDTH (font);
+
+       if (pcm)
+         {
+           int width = pcm->width;
+           for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
+             if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
+               width += pcm->width;
+           fontp->average_width = width / 95;
+         }
+       else
+         fontp->average_width = FONT_WIDTH (font);
+      }
+
+    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);
+    {
+      /* For some font, ascent and descent in max_bounds field is
         larger than the above value.  */
       int max_height = font->max_bounds.ascent + font->max_bounds.descent;
       if (max_height > fontp->height)
@@ -6791,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;
   }
@@ -6855,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>
@@ -6870,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
@@ -6889,37 +7623,21 @@ 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;
-
-/* 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;
-
 #define EXTRA_STACK_ALLOC (256 * 1024)
 
 #define ARGV_STRING_LIST_ID 129
 #define ABOUT_ALERT_ID 128
 #define RAM_TOO_LARGE_ALERT_ID 129
 
-Boolean        terminate_flag = false;
-
 /* Contains the string "reverse", which is a constant for mouse button emu.*/
 Lisp_Object Qreverse;
 
 /* True if using command key as meta key.  */
 Lisp_Object Vmac_command_key_is_meta;
 
+/* Modifier associated with the option key, or nil for normal behavior. */
+Lisp_Object Vmac_option_modifier;
+
 /* True if the ctrl and meta keys should be reversed.  */
 Lisp_Object Vmac_reverse_ctrl_meta;
 
@@ -6941,17 +7659,15 @@ 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;
 
 /* Apple Events */
@@ -6963,19 +7679,28 @@ do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
 
+#if TARGET_API_MAC_CARBON
 /* Drag and Drop */
-static OSErr init_mac_drag_n_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 *);
 #endif
+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();
@@ -6996,6 +7721,12 @@ mac_to_emacs_modifiers (EventModifiers mods)
     result |= meta_modifier;
   if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
     result |= alt_modifier;
+  if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
+      Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
+      if (!NILP(val))
+          result |= XUINT(val);
+  }
+
   return result;
 }
 
@@ -7003,9 +7734,9 @@ static int
 mac_get_emulated_btn ( UInt32 modifiers )
 {
   int result = 0;
-  if (Vmac_emulate_three_button_mouse != Qnil) {
-    int cmdIs3 = (Vmac_emulate_three_button_mouse != Qreverse);
-    if (modifiers & controlKey)
+  if (!NILP (Vmac_emulate_three_button_mouse)) {
+    int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
+    if (modifiers & cmdKey)
       result = cmdIs3 ? 2 : 1;
     else if (modifiers & optionKey)
       result = cmdIs3 ? 1 : 2;
@@ -7022,10 +7753,10 @@ mac_event_to_emacs_modifiers (EventRef eventRef)
   UInt32 mods = 0;
   GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
                    sizeof (UInt32), NULL, &mods);
-  if (Vmac_emulate_three_button_mouse != Qnil &&
+  if (!NILP (Vmac_emulate_three_button_mouse) &&
       GetEventClass(eventRef) == kEventClassMouse)
     {
-      mods &= ~(optionKey & cmdKey);
+      mods &= ~(optionKey | cmdKey);
     }
   return mac_to_emacs_modifiers (mods);
 }
@@ -7041,7 +7772,7 @@ mac_get_mouse_btn (EventRef ref)
   switch (result)
     {
     case kEventMouseButtonPrimary:
-      if (Vmac_emulate_three_button_mouse == Qnil)
+      if (NILP (Vmac_emulate_three_button_mouse))
        return 0;
       else {
        UInt32 mods = 0;
@@ -7061,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;
 }
 
@@ -7117,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
 }
 
 
@@ -7168,37 +7937,43 @@ do_check_ram_size (void)
 static void
 do_window_update (WindowPtr win)
 {
-  struct mac_output *mwp = (mac_output *) GetWRefCon (win);
-  struct frame *f = mwp->mFP;
+  struct frame *f = mac_window_to_frame (win);
 
-  if (f)
+  BeginUpdate (win);
+
+  /* The tooltip has been drawn already.  Avoid the SET_FRAME_GARBAGED
+     below.  */
+  if (win != tip_window)
     {
       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
-        {
-          BeginUpdate (win);
-          handling_window_update = 1;
-
-         XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
-
-          expose_frame (f, 0, 0, 0, 0);
+       {
+         Rect r;
+#if TARGET_API_MAC_CARBON
+         RgnHandle region = NewRgn ();
 
-          handling_window_update = 0;
-          EndUpdate (win);
-        }
+         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
+         r = (*win->visRgn)->rgnBBox;
+         expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
+         UpdateControls (win, win->visRgn);
+#endif
+       }
     }
+
+  EndUpdate (win);
 }
 
 static int
@@ -7217,155 +7992,18 @@ is_emacs_window (WindowPtr win)
   return 0;
 }
 
-static void
-do_window_activate (WindowPtr win)
-{
-  mac_output *mwp;
-  struct frame *f;
-
-  if (is_emacs_window (win))
-    {
-      mwp = (mac_output *) GetWRefCon (win);
-      f = mwp->mFP;
-
-      if (f)
-       {
-         x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
-         activate_scroll_bars (f);
-       }
-    }
-}
-
-static void
-do_window_deactivate (WindowPtr win)
-{
-  mac_output *mwp;
-  struct frame *f;
-
-  if (is_emacs_window (win))
-    {
-      mwp = (mac_output *) GetWRefCon (win);
-      f = mwp->mFP;
-
-      if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
-       {
-         x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
-         deactivate_scroll_bars (f);
-       }
-    }
-}
-
 static void
 do_app_resume ()
 {
-  WindowPtr wp;
-  mac_output *mwp;
-  struct frame *f;
-
-  wp = FrontWindow();
-  if (is_emacs_window (wp))
-    {
-      mwp = (mac_output *) GetWRefCon (wp);
-      f = mwp->mFP;
-
-      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;
+  /* Window-activate events will do the job. */
 }
 
 static void
 do_app_suspend ()
 {
-  WindowPtr wp;
-  mac_output *mwp;
-  struct frame *f;
-
-  wp = FrontWindow();
-  if (is_emacs_window (wp))
-    {
-      mwp = (mac_output *) GetWRefCon (wp);
-      f = mwp->mFP;
-
-      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;
-}
-
-
-static void
-do_mouse_moved (Point mouse_pos)
-{
-  WindowPtr wp = FrontWindow ();
-  struct frame *f;
-
-  if (is_emacs_window (wp))
-    {
-      f = ((mac_output *) GetWRefCon (wp))->mFP;
-
-#if TARGET_API_MAC_CARBON
-      SetPort (GetWindowPort (wp));
-#else
-      SetPort (wp);
-#endif
-
-      GlobalToLocal (&mouse_pos);
-
-      note_mouse_movement (f, &mouse_pos);
-    }
-}
-
-
-static void
-do_os_event (EventRecord *erp)
-{
-  switch((erp->message >> 24) & 0x000000FF)
-    {
-    case suspendResumeMessage:
-      if((erp->message & resumeFlag) == 1)
-       do_app_resume ();
-      else
-       do_app_suspend ();
-      break;
-
-    case mouseMovedMessage:
-      do_mouse_moved (erp->where);
-      break;
-    }
+  /* Window-deactivate events will do the job. */
 }
 
-static void
-do_events (EventRecord *erp)
-{
-  switch (erp->what)
-    {
-    case updateEvt:
-      do_window_update ((WindowPtr) erp->message);
-      break;
-
-    case osEvt:
-      do_os_event (erp);
-      break;
-
-    case activateEvt:
-      if ((erp->modifiers & activeFlag) != 0)
-       do_window_activate ((WindowPtr) erp->message);
-      else
-       do_window_deactivate ((WindowPtr) erp->message);
-      break;
-    }
-}
 
 static void
 do_apple_menu (SInt16 menu_item)
@@ -7392,19 +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:
       {
-        WindowPtr wp = FrontWindow ();
-        struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
+        struct frame *f = mac_focus_frame (&one_mac_display_info);
         MenuHandle menu = GetMenuHandle (menu_id);
         if (menu)
           {
@@ -7426,21 +8063,43 @@ do_menu_choice (SInt32 menu_choice)
 static void
 do_grow_window (WindowPtr w, EventRecord *e)
 {
-  long grow_size;
   Rect limit_rect;
-  int rows, columns;
-  mac_output *mwp = (mac_output *) GetWRefCon (w);
-  struct frame *f = mwp->mFP;
+  int rows, columns, width, height;
+  struct frame *f = mac_window_to_frame (w);
+  XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
+  int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
+#if TARGET_API_MAC_CARBON
+  Rect new_rect;
+#else
+  long grow_size;
+#endif
 
-  SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
+  if (size_hints->flags & PMinSize)
+    {
+      min_width  = size_hints->min_width;
+      min_height = size_hints->min_height;
+    }
+  SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
 
+#if TARGET_API_MAC_CARBON
+  if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
+    return;
+  height = new_rect.bottom - new_rect.top;
+  width = new_rect.right - new_rect.left;
+#else
   grow_size = GrowWindow (w, e->where, &limit_rect);
-
   /* see if it really changed size */
-  if (grow_size != 0)
+  if (grow_size == 0)
+    return;
+  height = HiWord (grow_size);
+  width = LoWord (grow_size);
+#endif
+
+  if (width != FRAME_PIXEL_WIDTH (f)
+      || height != FRAME_PIXEL_HEIGHT (f))
     {
-      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, HiWord (grow_size));
-      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, LoWord (grow_size));
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
+      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
 
       x_set_window_size (f, 0, columns, rows);
     }
@@ -7458,46 +8117,44 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   GrafPtr save_port;
   Rect zoom_rect, port_rect;
   Point top_left;
-  int w_title_height, columns, rows, width, height, dummy, x, y;
-  mac_output *mwp = (mac_output *) GetWRefCon (w);
-  struct frame *f = mwp->mFP;
-
-  GetPort (&save_port);
-
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  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);
 
-  /* Clear window to avoid flicker.  */
 #if TARGET_API_MAC_CARBON
   {
-    Rect r;
-    BitMap bm;
+    Point standard_size;
 
-    GetWindowPortBounds (w, &r);
-    EraseRect (&r);
+    standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+    standard_size.v = dpyinfo->height;
 
-    if (zoom_in_or_out == inZoomOut)
+    if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
+      zoom_in_or_out = inZoomIn;
+    else
       {
-        /* calculate height of window's title bar (hard card it for now).  */
-        w_title_height = 20 + GetMBarHeight ();
-
-        /* get maximum height of window into zoom_rect.bottom -
-          zoom_rect.top */
-        GetQDGlobalsScreenBits (&bm);
-        zoom_rect = bm.bounds;
-        zoom_rect.top += w_title_height;
-        InsetRect (&zoom_rect, 8, 4);  /* not too tight */
-
-        zoom_rect.right = zoom_rect.left
-         + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-
-        SetWindowStandardState (w, &zoom_rect);
+       /* Adjust the standard size according to character boundaries.  */
+
+       columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
+       rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
+       standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
+       standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+       GetWindowBounds (w, kWindowContentRgn, &port_rect);
+       if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
+           && port_rect.left == zoom_rect.left
+           && port_rect.top == zoom_rect.top)
+         zoom_in_or_out = inZoomIn;
+       else
+         zoom_in_or_out = inZoomOut;
       }
+
+    ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
   }
 #else /* not TARGET_API_MAC_CARBON */
+  GetPort (&save_port);
+
+  SetPortWindowPort (w);
+
+  /* Clear window to avoid flicker.  */
   EraseRect (&(w->portRect));
   if (zoom_in_or_out == inZoomOut)
     {
@@ -7516,12 +8173,19 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
       zoom_rect.right = zoom_rect.left
        + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
 
+      /* Adjust the standard size according to character boundaries.  */
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
+      zoom_rect.bottom =
+       zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+
       (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
        = zoom_rect;
     }
-#endif /* not TARGET_API_MAC_CARBON */
 
-  ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
+  ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
+
+  SetPort (save_port);
+#endif /* not TARGET_API_MAC_CARBON */
 
   /* retrieve window size and update application values */
 #if TARGET_API_MAC_CARBON
@@ -7529,19 +8193,23 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
 #else
   port_rect = w->portRect;
 #endif
-  rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
-  columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
-  x_set_window_size (mwp->mFP, 0, columns, rows);
+  height = port_rect.bottom - port_rect.top;
+  width = port_rect.right - port_rect.left;
 
-  SetPort (save_port);
-}
+  if (width != FRAME_PIXEL_WIDTH (f)
+      || height != FRAME_PIXEL_HEIGHT (f))
+    {
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
+      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
 
-/* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
-static OSErr
-init_mac_drag_n_drop ()
-{
-  OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
-  return result;
+      change_frame_size (f, rows, columns, 0, 1, 0);
+      SET_FRAME_GARBAGED (f);
+      cancel_mouse_face (f);
+
+      FRAME_PIXEL_WIDTH (f) = width;
+      FRAME_PIXEL_HEIGHT (f) = height;
+    }
+  x_real_positions (f, &f->left_pos, &f->top_pos);
 }
 
 /* Intialize AppleEvent dispatcher table for the required events.  */
@@ -7616,106 +8284,358 @@ 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);
 
-       GetCurrentScrap (&currentScrap);
+  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);
 
-       err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
-       if (err == noErr)
+  buf.arg = Qapplication;
+  kbd_buffer_store_event (&buf);
+
+#if USE_CARBON_EVENTS
+  switch (GetEventClass (event))
+    {
+#ifdef MAC_OSX
+    case kEventClassService:
+      buf.arg = Qservices;
+      kbd_buffer_store_event (&buf);
+      switch (GetEventKind (event))
+       {
+       case kEventServicePaste:
+         entry = Qpaste;
+         break;
+
+       case kEventServicePerform:
          {
-           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 ();
+    }
+#else  /* USE_CARBON_EVENTS */
+  switch (event)
+    {
+    case kHICommandAbout:
+      entry = Qabout;
+      break;
+    case kHICommandQuit:
+      entry = Qquit;
+      break;
+    default:
+      abort ();
     }
-  return err;
-}
 #endif
 
-/* Open Application Apple Event */
+  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)
+     EventHandlerCallRef next_handler;
+     EventRef event;
+     void *data;
+{
+  WindowPtr wp;
+  OSStatus result;
+  UInt32 attributes;
+  XSizeHints *size_hints;
+
+  GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
+                    NULL, sizeof (WindowPtr), NULL, &wp);
+
+  switch (GetEventKind (event))
+    {
+    case kEventWindowUpdate:
+      result = CallNextEventHandler (next_handler, event);
+      if (result != eventNotHandledErr)
+       return result;
+
+      do_window_update (wp);
+      return noErr;
+
+    case kEventWindowBoundsChanging:
+      result = CallNextEventHandler (next_handler, event);
+      if (result != eventNotHandledErr)
+       return result;
+
+      GetEventParameter (event, kEventParamAttributes, typeUInt32,
+                        NULL, sizeof (UInt32), NULL, &attributes);
+      size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
+      if ((attributes & kWindowBoundsChangeUserResize)
+         && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
+             == (PResizeInc | PBaseSize | PMinSize)))
+       {
+         Rect bounds;
+         int width, height;
+
+         GetEventParameter (event, kEventParamCurrentBounds,
+                            typeQDRectangle,
+                            NULL, sizeof (Rect), NULL, &bounds);
+         width = bounds.right - bounds.left;
+         height = bounds.bottom - bounds.top;
+
+         if (width < size_hints->min_width)
+           width = size_hints->min_width;
+         else
+           width = size_hints->base_width
+             + (int) ((width - size_hints->base_width)
+                      / (float) size_hints->width_inc + .5)
+             * size_hints->width_inc;
+
+         if (height < size_hints->min_height)
+           height = size_hints->min_height;
+         else
+           height = size_hints->base_height
+             + (int) ((height - size_hints->base_height)
+                      / (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;
+       }
+      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;
+    }
+
+  return eventNotHandledErr;
+}
+#endif /* USE_CARBON_EVENTS */
+
+
+OSErr
+install_window_handler (window)
+     WindowPtr window;
+{
+  OSErr err = noErr;
+#if USE_CARBON_EVENTS
+  EventTypeSpec specs_window[] =
+    {{kEventClassWindow, kEventWindowUpdate},
+     {kEventClassWindow, kEventWindowBoundsChanging},
+     {kEventClassWindow, kEventWindowShown},
+     {kEventClassWindow, kEventWindowHidden},
+     {kEventClassWindow, kEventWindowExpanded},
+     {kEventClassWindow, kEventWindowCollapsed}};
+  EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
+  static EventHandlerUPP handle_window_eventUPP = NULL;
+  static EventHandlerUPP handle_mouse_eventUPP = NULL;
+
+  if (handle_window_eventUPP == NULL)
+    handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
+  if (handle_mouse_eventUPP == NULL)
+    handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
+  err = InstallWindowEventHandler (window, handle_window_eventUPP,
+                                  GetEventTypeCount (specs_window),
+                                  specs_window, NULL, NULL);
+  if (err == noErr)
+    err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
+                                    GetEventTypeCount (specs_mouse),
+                                    specs_mouse, NULL, NULL);
+#endif
+#if 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_dragUPP, window, NULL);
+  if (err == noErr)
+    err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
+#endif
+  return err;
+}
+
+void
+remove_window_handler (window)
+     WindowPtr window;
+{
+#if TARGET_API_MAC_CARBON
+  if (mac_do_track_dragUPP)
+    RemoveTrackingHandler (mac_do_track_dragUPP, window);
+  if (mac_do_receive_dragUPP)
+    RemoveReceiveHandler (mac_do_receive_dragUPP, window);
+#endif
+}
+
+/* Open Application Apple Event */
 static pascal OSErr
 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
 {
@@ -7723,14 +8643,20 @@ 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.  */
+#pragma options align=mac68k
+typedef struct SelectionRange {
+  short unused1; // 0 (not used)
+  short lineNum; // line to select (<0 to specify range)
+  long startRange; // start of selection range (if line < 0)
+  long endRange; // end of selection range (if line < 0)
+  long unused2; // 0 (not used)
+  long theDate; // modification date/time
+} SelectionRange;
+#pragma options align=reset
+
 static pascal OSErr
 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
 {
@@ -7739,11 +8665,22 @@ do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
   AEKeyword keyword;
   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)
     goto descriptor_error_exit;
 
+  err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
+  if (err == noErr)
+    file_list = Fcons (list3 (make_number (position.lineNum + 1),
+                             make_number (position.startRange + 1),
+                             make_number (position.endRange + 1)),
+                      file_list);
+
   /* Check to see that we got all of the required parameters from the
      event descriptor.  For an 'odoc' event this should just be the
      file list.  */
@@ -7771,32 +8708,74 @@ do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
         int i;
 
         /* AE file list is one based so just use that for indexing here.  */
-        for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
+        for (i = 1; i <= num_files_to_open; i++)
          {
-           FSSpec fs;
-           Str255 path_name, unix_path_name;
+           char unix_path_name[MAXPATHLEN];
 #ifdef MAC_OSX
            FSRef fref;
-#endif
+
+           err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
+                              &actual_type, &fref, sizeof (FSRef),
+                              &actual_size);
+           if (err != noErr || actual_type != typeFSRef)
+             continue;
+
+           if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
+               == noErr)
+#else
+           FSSpec fs;
 
            err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
                              (Ptr) &fs, sizeof (fs), &actual_size);
-           if (err != noErr) break;
+           if (err != noErr) continue;
 
-#ifdef MAC_OSX
-           err = FSpMakeFSRef (&fs, &fref);
-           if (err != noErr) break;
-
-           if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
-#else
-           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
-             drag_and_drop_file_list = Fcons (build_string (unix_path_name),
-                                              drag_and_drop_file_list);
+             /* x-dnd functions expect undecoded filenames.  */
+             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
+      }
   }
 
 error_exit:
@@ -7809,6 +8788,74 @@ descriptor_error_exit:
 }
 
 
+#if TARGET_API_MAC_CARBON
+static pascal OSErr
+mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
+                  void *handlerRefCon, DragReference theDrag)
+{
+  static int can_accept;
+  short items;
+  short index;
+  ItemReference theItem;
+  FlavorFlags theFlags;
+  OSErr result;
+
+  if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
+    return dragNotAcceptedErr;
+
+  switch (message)
+    {
+    case kDragTrackingEnterHandler:
+      CountDragItems (theDrag, &items);
+      can_accept = 0;
+      for (index = 1; index <= items; index++)
+       {
+         GetDragItemReferenceNumber (theDrag, index, &theItem);
+         result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
+         if (result == noErr)
+           {
+             can_accept = 1;
+             break;
+           }
+       }
+      break;
+
+    case kDragTrackingEnterWindow:
+      if (can_accept)
+       {
+         RgnHandle hilite_rgn = NewRgn ();
+         Rect r;
+         struct frame *f = mac_window_to_frame (window);
+
+         GetWindowPortBounds (window, &r);
+         OffsetRect (&r, -r.left, -r.top);
+         RectRgn (hilite_rgn, &r);
+         ShowDragHilite (theDrag, hilite_rgn, true);
+         DisposeRgn (hilite_rgn);
+         SetThemeCursor (kThemeCopyArrowCursor);
+       }
+      break;
+
+    case kDragTrackingInWindow:
+      break;
+
+    case kDragTrackingLeaveWindow:
+      if (can_accept)
+       {
+         struct frame *f = mac_window_to_frame (window);
+
+         HideDragHilite (theDrag);
+         SetThemeCursor (kThemeArrowCursor);
+       }
+      break;
+
+    case kDragTrackingLeaveHandler:
+      break;
+    }
+
+  return noErr;
+}
+
 static pascal OSErr
 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
                     DragReference theDrag)
@@ -7820,10 +8867,13 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
   OSErr result;
   ItemReference theItem;
   HFSFlavor data;
-  FSRef fref;
   Size size = sizeof (HFSFlavor);
+  Lisp_Object file_list;
 
-  drag_and_drop_file_list = Qnil;
+  if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
+    return dragNotAcceptedErr;
+
+  file_list = Qnil;
   GetDragMouse (theDrag, &mouse, 0L);
   CountDragItems (theDrag, &items);
   for (index = 1; index <= items; index++)
@@ -7834,11 +8884,10 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
       if (result == noErr)
        {
 #ifdef MAC_OSX
-         FSRef frref;
-#else
-         Str255 path_name;
+         FSRef fref;
 #endif
-         Str255 unix_path_name;
+         char unix_path_name[MAXPATHLEN];
+
          GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
 #ifdef MAC_OSX
          /* Use Carbon routines, otherwise it converts the file name
@@ -7846,34 +8895,35 @@ 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
-            drag_and_drop_file_list = Fcons (build_string (unix_path_name),
-                                            drag_and_drop_file_list);
+           /* x-dnd functions expect undecoded filenames.  */
+            file_list = Fcons (make_unibyte_string (unix_path_name,
+                                                   strlen (unix_path_name)),
+                              file_list);
        }
-      else
-       return;
     }
   /* 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;
-      struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
-      SetPort (GetWindowPort (window));
+      struct frame *f = mac_window_to_frame (window);
+      SInt16 modifiers;
+
       GlobalToLocal (&mouse);
+      GetDragModifiers (theDrag, NULL, NULL, &modifiers);
 
       event.kind = DRAG_N_DROP_EVENT;
       event.code = 0;
-      event.modifiers = 0;
+      event.modifiers = mac_to_emacs_modifiers (modifiers);
       event.timestamp = TickCount () * (1000 / 60);
       XSETINT (event.x, mouse.h);
       XSETINT (event.y, mouse.v);
       XSETFRAME (frame, f);
-      event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
+      event.frame_or_window = Fcons (frame, file_list);
       event.arg = Qnil;
       /* Post to the interrupt queue */
       kbd_buffer_store_event (&event);
@@ -7883,8 +8933,13 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
        GetCurrentProcess (&psn);
        SetFrontProcess (&psn);
       }
+
+      return noErr;
     }
+  else
+    return dragNotAcceptedErr;
 }
+#endif
 
 
 /* Print Document Apple Event */
@@ -7898,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};
 
-  terminate_flag = true;
+  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);
+
+  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
 }
 
 
@@ -7919,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.  */
-
-#if !TARGET_API_MAC_CARBON
+   (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.  */
+
+#ifdef MAC_OS8
 #undef main
 int
 main (void)
@@ -7995,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,
 
@@ -8019,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
 };
 
@@ -8034,29 +9104,66 @@ keycode_to_xkeysym (int keyCode, int *xKeySym)
   return *xKeySym != 0;
 }
 
+#if !USE_CARBON_EVENTS
+static RgnHandle mouse_region = NULL;
+
+Boolean
+mac_wait_next_event (er, sleep_time, dequeue)
+     EventRecord *er;
+     UInt32 sleep_time;
+     Boolean dequeue;
+{
+  static EventRecord er_buf = {nullEvent};
+  UInt32 target_tick, current_tick;
+  EventMask event_mask;
+
+  if (mouse_region == NULL)
+    mouse_region = NewRgn ();
+
+  event_mask = everyEvent;
+  if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
+    event_mask -= highLevelEventMask;
+
+  current_tick = TickCount ();
+  target_tick = current_tick + sleep_time;
+
+  if (er_buf.what == nullEvent)
+    while (!WaitNextEvent (event_mask, &er_buf,
+                          target_tick - current_tick, mouse_region))
+      {
+       current_tick = TickCount ();
+       if (target_tick <= current_tick)
+         return false;
+      }
+
+  *er = er_buf;
+  if (dequeue)
+    er_buf.what = nullEvent;
+  return true;
+}
+#endif /* not USE_CARBON_EVENTS */
+
 /* Emacs calls this whenever it wants to read an input event from the
    user. */
 int
-XTread_socket (int sd, int expected, struct input_event *hold_quit)
+XTread_socket (sd, expected, hold_quit)
+     int sd, expected;
+     struct input_event *hold_quit;
 {
   struct input_event inev;
   int count = 0;
 #if USE_CARBON_EVENTS
-  OSStatus rneResult;
   EventRef eventRef;
-  EventMouseButton mouseBtn;
+  EventTargetRef toolbox_dispatcher;
 #endif
   EventRecord er;
-  int the_modifiers;
-  EventMask event_mask;
+  struct mac_display_info *dpyinfo = &one_mac_display_info;
 
-#if 0
   if (interrupt_input_blocked)
     {
       interrupt_input_pending = 1;
       return -1;
     }
-#endif
 
   interrupt_input_pending = 0;
   BLOCK_INPUT;
@@ -8064,516 +9171,626 @@ XTread_socket (int sd, int expected, struct input_event *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));
-
-  /* It is necessary to set this (additional) argument slot of an
-     event to nil because keyboard.c protects incompletely processed
-     event from being garbage collected by placing them in the
-     kbd_buffer_gcpro vector.  */
-  EVENT_INIT (inev);
-  inev.kind = NO_EVENT;
-  inev.arg = Qnil;
+#if USE_CARBON_EVENTS
+  toolbox_dispatcher = GetEventDispatcherTarget ();
+
+  while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
+                           kEventRemoveFromQueue, &eventRef))
+#else /* !USE_CARBON_EVENTS */
+  while (mac_wait_next_event (&er, 0, true))
+#endif /* !USE_CARBON_EVENTS */
+    {
+      int do_help = 0;
+      struct frame *f;
+      unsigned long timestamp;
+
+      /* It is necessary to set this (additional) argument slot of an
+        event to nil because keyboard.c protects incompletely
+        processed event from being garbage collected by placing them
+        in the kbd_buffer_gcpro vector.  */
+      EVENT_INIT (inev);
+      inev.kind = NO_EVENT;
+      inev.arg = Qnil;
 
-  event_mask = everyEvent;
-  if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
-    event_mask -= highLevelEventMask;
+#if USE_CARBON_EVENTS
+      timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
+#else
+      timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
+#endif
 
 #if USE_CARBON_EVENTS
-  rneResult = ReceiveNextEvent (0, NULL,
-                               expected
-                               ? TicksToEventTime (app_sleep_time)
-                               : 0,
-                               kEventRemoveFromQueue, &eventRef);
-  if (!rneResult)
-    {
       /* Handle new events */
       if (!mac_convert_event_ref (eventRef, &er))
-       switch (GetEventClass (eventRef))
+       {
+         /* 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)
+       {
+       case mouseDown:
+       case mouseUp:
          {
-         case kEventClassMouse:
-           if (GetEventKind (eventRef) == kEventMouseWheelMoved)
+           WindowPtr window_ptr;
+           ControlPartCode part_code;
+           int tool_bar_p = 0;
+
+#if USE_CARBON_EVENTS
+           /* This is needed to send mouse events like aqua window
+              buttons to the correct handler.  */
+           if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+               != eventNotHandledErr)
+             break;
+#endif
+
+           if (dpyinfo->grabbed && last_mouse_frame
+               && FRAME_LIVE_P (last_mouse_frame))
+             {
+               window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
+               part_code = inContent;
+             }
+           else
              {
-               SInt32 delta;
-               Point point;
-               WindowPtr window_ptr = FrontNonFloatingWindow ();
-               struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
-               if (!IsValidWindowPtr (window_ptr))
+               part_code = FindWindow (er.where, &window_ptr);
+               if (tip_window && window_ptr == tip_window)
                  {
-                   SysBeep(1);
-                   UNBLOCK_INPUT;
-                   return 0;
+                   HideWindow (tip_window);
+                   part_code = FindWindow (er.where, &window_ptr);
                  }
-
-               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));
-               SetPort (GetWindowPort (window_ptr));
-               GlobalToLocal (&point);
-               XSETINT (inev.x, point.h);
-               XSETINT (inev.y, point.v);
-               XSETFRAME (inev.frame_or_window, mwp->mFP);
-               inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
              }
-           else
-             SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
 
-           break;
-         default:
-           /* Send the event to the appropriate receiver.  */
-           SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
-         }
-      else
-#else
-  if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
-#endif /* USE_CARBON_EVENTS */
-    switch (er.what)
-      {
-      case mouseDown:
-      case mouseUp:
-       {
-         WindowPtr window_ptr = FrontWindow ();
-         SInt16 part_code;
+           if (er.what != mouseDown && part_code != inContent)
+             break;
 
-#if USE_CARBON_EVENTS
-         /* This is needed to send mouse events like aqua window buttons
-            to the correct handler.  */
-         if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
-           break;
-         }
+           switch (part_code)
+             {
+             case inMenuBar:
+               f = mac_focus_frame (dpyinfo);
+               saved_menu_event_location = er.where;
+               inev.kind = MENU_BAR_ACTIVATE_EVENT;
+               XSETFRAME (inev.frame_or_window, f);
+               break;
 
-         if (!is_emacs_window(window_ptr))
-           break;
+             case inContent:
+               if (window_ptr != FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo)))
+                 SelectWindow (window_ptr);
+               else
+                 {
+                   ControlPartCode control_part_code;
+                   ControlHandle ch;
+                   Point mouse_loc = er.where;
+#ifdef MAC_OSX
+                   ControlKind control_kind;
 #endif
 
-          if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
-             && er.what == mouseUp)
-            {
-             struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
-             Point mouse_loc = er.where;
+                   f = mac_window_to_frame (window_ptr);
+                   /* convert to local coordinates of new window */
+                   SetPortWindowPort (window_ptr);
 
-             /* Convert to local coordinates of new window.  */
+                   GlobalToLocal (&mouse_loc);
 #if TARGET_API_MAC_CARBON
-              SetPort (GetWindowPort (window_ptr));
+                   ch = FindControlUnderMouse (mouse_loc, window_ptr,
+                                               &control_part_code);
+#ifdef MAC_OSX
+                   if (ch)
+                     GetControlKind (ch, &control_kind);
+#endif
 #else
-              SetPort (window_ptr);
+                   control_part_code = FindControl (mouse_loc, window_ptr,
+                                                    &ch);
 #endif
 
-             GlobalToLocal (&mouse_loc);
-
 #if USE_CARBON_EVENTS
-             inev.code = mac_get_mouse_btn (eventRef);
+                   inev.code = mac_get_mouse_btn (eventRef);
+                   inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
-             inev.code = mac_get_emulate_btn (er.modifiers);
+                   inev.code = mac_get_emulated_btn (er.modifiers);
+                   inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
-              inev.kind = SCROLL_BAR_CLICK_EVENT;
-              inev.frame_or_window = tracked_scroll_bar->window;
-              inev.part = scroll_bar_handle;
-#if USE_CARBON_EVENTS
-             inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-             inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+                   XSETINT (inev.x, mouse_loc.h);
+                   XSETINT (inev.y, mouse_loc.v);
+
+                   if (dpyinfo->grabbed && tracked_scroll_bar
+                       || ch != 0
+#ifndef USE_TOOLKIT_SCROLL_BARS
+                       /* control_part_code becomes kControlNoPart if
+                          a progress indicator is clicked.  */
+                       && control_part_code != kControlNoPart
+#else  /* USE_TOOLKIT_SCROLL_BARS */
+#ifdef MAC_OSX
+                       && control_kind.kind == kControlKindScrollBar
+#endif /* MAC_OSX */
+#endif /* USE_TOOLKIT_SCROLL_BARS */
+                       )
+                     {
+                       struct scroll_bar *bar;
+
+                       if (dpyinfo->grabbed && tracked_scroll_bar)
+                         {
+                           bar = tracked_scroll_bar;
+#ifndef USE_TOOLKIT_SCROLL_BARS
+                           control_part_code = kControlIndicatorPart;
 #endif
-              inev.modifiers |= up_modifier;
-             inev.timestamp = er.when * (1000 / 60);
-               /* ticks to milliseconds */
-
-              XSETINT (inev.x, tracked_scroll_bar->left + 2);
-              XSETINT (inev.y, mouse_loc.v - 24);
-              tracked_scroll_bar->dragging = Qnil;
-              mouse_tracking_in_progress = mouse_tracking_none;
-              tracked_scroll_bar = NULL;
-              break;
-            }
-
-         part_code = FindWindow (er.where, &window_ptr);
+                         }
+                       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
+                           && control_part_code == kControlIndicatorPart)
+                         tracked_scroll_bar = bar;
+                       else
+                         tracked_scroll_bar = NULL;
+#endif  /* not USE_TOOLKIT_SCROLL_BARS */
+                     }
+                   else
+                     {
+                       Lisp_Object window;
+                       int x = mouse_loc.h;
+                       int y = mouse_loc.v;
+
+                       window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
+                       if (EQ (window, f->tool_bar_window))
+                         {
+                           if (er.what == mouseDown)
+                             handle_tool_bar_click (f, x, y, 1, 0);
+                           else
+                             handle_tool_bar_click (f, x, y, 0,
+                                                    inev.modifiers);
+                           tool_bar_p = 1;
+                         }
+                       else
+                         {
+                           XSETFRAME (inev.frame_or_window, f);
+                           inev.kind = MOUSE_CLICK_EVENT;
+                         }
+                     }
+
+                   if (er.what == mouseDown)
+                     {
+                       dpyinfo->grabbed |= (1 << inev.code);
+                       last_mouse_frame = f;
+                       /* Ignore any mouse motion that happened
+                          before this event; any subsequent
+                          mouse-movement Emacs events should reflect
+                          only motion after the ButtonPress.  */
+                       if (f != 0)
+                         f->mouse_moved = 0;
+
+                       if (!tool_bar_p)
+                         last_tool_bar_item = -1;
+                     }
+                   else
+                     {
+                       if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
+                         /* If a button is released though it was not
+                            previously pressed, that would be because
+                            of multi-button emulation.  */
+                         dpyinfo->grabbed = 0;
+                       else
+                         dpyinfo->grabbed &= ~(1 << inev.code);
+                     }
+
+#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;
 
-         switch (part_code)
-           {
-           case inMenuBar:
-             if (er.what == mouseDown)
+             case inDrag:
+#if TARGET_API_MAC_CARBON
+               DragWindow (window_ptr, er.where, NULL);
+#else /* not TARGET_API_MAC_CARBON */
+               DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
+#endif /* not TARGET_API_MAC_CARBON */
+               /* Update the frame parameters.  */
                {
-                 struct frame *f = ((mac_output *)
-                                    GetWRefCon (FrontWindow ()))->mFP;
-                 saved_menu_event_location = er.where;
-                 inev.kind = MENU_BAR_ACTIVATE_EVENT;
-                 XSETFRAME (inev.frame_or_window, f);
+                 struct frame *f = mac_window_to_frame (window_ptr);
+
+                 if (f && !f->async_iconified)
+                   x_real_positions (f, &f->left_pos, &f->top_pos);
                }
-             break;
+               break;
 
-           case inContent:
-             if (window_ptr != FrontWindow ())
-               SelectWindow (window_ptr);
-             else
-               {
-                 SInt16 control_part_code;
-                 ControlHandle ch;
-                 struct mac_output *mwp = (mac_output *)
-                   GetWRefCon (window_ptr);
-                 Point mouse_loc = er.where;
-
-                 /* convert to local coordinates of new window */
-#if TARGET_API_MAC_CARBON
-                  SetPort (GetWindowPort (window_ptr));
-#else
-                  SetPort (window_ptr);
-#endif
+             case inGoAway:
+               if (TrackGoAway (window_ptr, er.where))
+                 {
+                   inev.kind = DELETE_WINDOW_EVENT;
+                   XSETFRAME (inev.frame_or_window,
+                              mac_window_to_frame (window_ptr));
+                 }
+               break;
 
-                 GlobalToLocal (&mouse_loc);
-#if TARGET_API_MAC_CARBON
-                 ch = FindControlUnderMouse (mouse_loc, window_ptr,
-                                             &control_part_code);
-#else
-                 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
-#endif
+               /* window resize handling added --ben */
+             case inGrow:
+               do_grow_window (window_ptr, &er);
+               break;
 
+               /* window zoom handling added --ben */
+             case inZoomIn:
+             case inZoomOut:
+               if (TrackBox (window_ptr, er.where, part_code))
+                 do_zoom_window (window_ptr, part_code);
+               break;
+
+             default:
+               break;
+             }
+         }
+         break;
+
+       case updateEvt:
 #if USE_CARBON_EVENTS
-                 inev.code = mac_get_mouse_btn (eventRef);
+         if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+             != eventNotHandledErr)
+           break;
 #else
-                 inev.code = mac_get_emulate_btn (er.modifiers);
+         do_window_update ((WindowPtr) er.message);
 #endif
-                 XSETINT (inev.x, mouse_loc.h);
-                 XSETINT (inev.y, mouse_loc.v);
-                 inev.timestamp = er.when * (1000 / 60);
-                   /* ticks to milliseconds */
+         break;
 
-#if TARGET_API_MAC_CARBON
-                 if (ch != 0)
-#else
-                 if (control_part_code != 0)
-#endif
-                   {
-                     struct scroll_bar *bar = (struct scroll_bar *)
-                       GetControlReference (ch);
-                     x_scroll_bar_handle_click (bar, control_part_code, &er,
-                                                &inev);
-                     if (er.what == mouseDown
-                         && control_part_code == kControlIndicatorPart)
-                       {
-                         mouse_tracking_in_progress
-                           = mouse_tracking_scroll_bar;
-                         tracked_scroll_bar = bar;
-                       }
-                     else
-                       {
-                         mouse_tracking_in_progress = mouse_tracking_none;
-                         tracked_scroll_bar = NULL;
-                       }
-                   }
-                 else
-                   {
-                     Lisp_Object window;
-
-                     XSETFRAME (inev.frame_or_window, mwp->mFP);
-                     if (er.what == mouseDown)
-                       mouse_tracking_in_progress
-                         = mouse_tracking_mouse_movement;
-                     else
-                       mouse_tracking_in_progress = mouse_tracking_none;
-                     window = window_from_coordinates (mwp->mFP, inev.x, inev.y, 0, 0, 0, 1);
-
-                     if (EQ (window, mwp->mFP->tool_bar_window))
-                       {
-                         if (er.what == mouseDown)
-                           handle_tool_bar_click (mwp->mFP, inev.x, inev.y, 1, 0);
-                         else
-                           handle_tool_bar_click (mwp->mFP, inev.x, inev.y, 0,
+       case osEvt:
 #if USE_CARBON_EVENTS
-                                                  mac_event_to_emacs_modifiers (eventRef)
-#else
-                                                  er.modifiers
+         if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+             != eventNotHandledErr)
+           break;
 #endif
-                                                  );
-                         break;
-                       }
-                     else
-                       inev.kind = MOUSE_CLICK_EVENT;
-                   }
+         switch ((er.message >> 24) & 0x000000FF)
+           {
+           case suspendResumeMessage:
+             if ((er.message & resumeFlag) == 1)
+               do_app_resume ();
+             else
+               do_app_suspend ();
+             break;
 
-#if USE_CARBON_EVENTS
-                 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-                 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+           case mouseMovedMessage:
+#if !USE_CARBON_EVENTS
+             SetRectRgn (mouse_region, er.where.h, er.where.v,
+                         er.where.h + 1, er.where.v + 1);
 #endif
+             previous_help_echo_string = help_echo_string;
+             help_echo_string = help_echo_object = help_echo_window = Qnil;
+             help_echo_pos = -1;
 
-                 switch (er.what)
-                   {
-                   case mouseDown:
-                     inev.modifiers |= down_modifier;
-                     break;
-                   case mouseUp:
-                     inev.modifiers |= up_modifier;
-                     break;
-                   }
-               }
-             break;
+             if (dpyinfo->grabbed && last_mouse_frame
+                 && FRAME_LIVE_P (last_mouse_frame))
+               f = last_mouse_frame;
+             else
+               f = dpyinfo->x_focus_frame;
 
-           case inDrag:
-#if TARGET_API_MAC_CARBON
-              if (er.what == mouseDown)
+             if (dpyinfo->mouse_face_hidden)
                {
-                 BitMap bm;
-
-                 GetQDGlobalsScreenBits (&bm);
-                 DragWindow (window_ptr, er.where, &bm.bounds);
+                 dpyinfo->mouse_face_hidden = 0;
+                 clear_mouse_face (dpyinfo);
                }
-#else /* not TARGET_API_MAC_CARBON */
-             DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
-#endif /* not TARGET_API_MAC_CARBON */
-             break;
-
-           case inGoAway:
-             if (TrackGoAway (window_ptr, er.where))
-               {
-                 inev.kind = DELETE_WINDOW_EVENT;
-                 XSETFRAME (inev.frame_or_window,
-                            ((mac_output *) GetWRefCon (window_ptr))->mFP);
-               }
-             break;
 
-           /* window resize handling added --ben */
-           case inGrow:
-              if (er.what == mouseDown)
+             if (f)
                {
-                 do_grow_window(window_ptr, &er);
-                 break;
+                 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);
+                   }
                }
 
-           /* window zoom handling added --ben */
-           case inZoomIn:
-           case inZoomOut:
-             if (TrackBox (window_ptr, er.where, part_code))
-               do_zoom_window (window_ptr, part_code);
-             break;
-
-           default:
+             /* If the contents of the global variable
+                help_echo_string has changed, generate a
+                HELP_EVENT.  */
+             if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
+               do_help = 1;
              break;
            }
-       }
-       break;
+         break;
+
+       case activateEvt:
+         {
+           WindowPtr window_ptr = (WindowPtr) er.message;
 
-      case updateEvt:
-      case osEvt:
-      case activateEvt:
 #if USE_CARBON_EVENTS
-       if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
+           if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+               != eventNotHandledErr)
+             break;
 #endif
-       do_events (&er);
-       break;
+           if (window_ptr == tip_window)
+             {
+               HideWindow (tip_window);
+               break;
+             }
 
-      case keyDown:
-      case autoKey:
-       {
-         int keycode = (er.message & keyCodeMask) >> 8;
-         int xkeysym;
+           if (!is_emacs_window (window_ptr))
+             break;
 
-#if USE_CARBON_EVENTS
-         /* When using Carbon Events, we need to pass raw keyboard events
-            to the TSM ourselves.  If TSM handles it, it will pass back
-            noErr, otherwise it will pass back "eventNotHandledErr" and
-            we can process it normally.   */
-         if ((!NILP (Vmac_pass_command_to_system)
-              || !(er.modifiers & cmdKey))
-             && (!NILP (Vmac_pass_control_to_system)
-                 || !(er.modifiers & controlKey)))
-           {
-             OSStatus err;
-             err = SendEventToEventTarget (eventRef,
-                                           GetEventDispatcherTarget ());
-             if (err != eventNotHandledErr)
-               break;
-           }
+           if ((er.modifiers & activeFlag) != 0)
+             {
+               /* A window has been activated */
+               Point mouse_loc = er.where;
+
+               x_detect_focus_change (dpyinfo, &er, &inev);
+
+               SetPortWindowPort (window_ptr);
+               GlobalToLocal (&mouse_loc);
+               /* Window-activated event counts as mouse movement,
+                  so update things that depend on mouse position.  */
+               note_mouse_movement (mac_window_to_frame (window_ptr),
+                                    &mouse_loc);
+             }
+           else
+             {
+               /* A window has been deactivated */
+#if USE_TOOLKIT_SCROLL_BARS
+               if (dpyinfo->grabbed && tracked_scroll_bar)
+                 {
+                   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;
 
-         if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
-           {
-             SysBeep (1);
-             UNBLOCK_INPUT;
-             return 0;
-           }
+               x_detect_focus_change (dpyinfo, &er, &inev);
 
-         ObscureCursor ();
+               f = mac_window_to_frame (window_ptr);
+               if (f == dpyinfo->mouse_face_mouse_frame)
+                 {
+                   /* If we move outside the frame, then we're
+                      certainly no longer on any text in the
+                      frame.  */
+                   clear_mouse_face (dpyinfo);
+                   dpyinfo->mouse_face_mouse_frame = 0;
+                 }
+
+               /* Generate a nil HELP_EVENT to cancel a help-echo.
+                  Do it only if there's something to cancel.
+                  Otherwise, the startup message is cleared when the
+                  mouse leaves the frame.  */
+               if (any_help_event_p)
+                 do_help = -1;
+             }
+         }
+         break;
+
+       case keyDown:
+       case autoKey:
+         {
+           int keycode = (er.message & keyCodeMask) >> 8;
+           int xkeysym;
+
+#if USE_CARBON_EVENTS && defined (MAC_OSX)
+           /* When using Carbon Events, we need to pass raw keyboard
+              events to the TSM ourselves.  If TSM handles it, it
+              will pass back noErr, otherwise it will pass back
+              "eventNotHandledErr" and we can process it
+              normally.  */
+           if ((!NILP (Vmac_pass_command_to_system)
+                || !(er.modifiers & cmdKey))
+               && (!NILP (Vmac_pass_control_to_system)
+                   || !(er.modifiers & controlKey))
+               && (!NILP (Vmac_command_key_is_meta)
+                   && NILP (Vmac_option_modifier)
+                   || !(er.modifiers & optionKey)))
+             if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+                 != eventNotHandledErr)
+               break;
+#endif
+
+#if 0
+           if (dpyinfo->x_focus_frame == NULL)
+             {
+               /* Beep if keyboard input occurs when all the frames
+                  are invisible.  */
+               SysBeep (1);
+               break;
+             }
+#endif
 
-         if (keycode_to_xkeysym (keycode, &xkeysym))
-           {
-             inev.code = 0xff00 | xkeysym;
-             inev.kind = NON_ASCII_KEYSTROKE_EVENT;
-           }
-         else
            {
-             if (er.modifiers & (controlKey |
-                                 (NILP (Vmac_command_key_is_meta) ? optionKey
-                                  : cmdKey)))
+             static SInt16 last_key_script = -1;
+             SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
+
+             if (last_key_script != current_key_script)
                {
-                 /* This code comes from Keyboard Resource, Appendix
-                    C of IM - Text.  This is necessary since shift is
-                    ignored in KCHR table translation when option or
-                    command is pressed.  It also does not translate
-                    correctly control-shift chars like C-% so mask off
-                    shift here also */
-                 int new_modifiers = er.modifiers & 0xe600;
-                 /* mask off option and command */
-                 int new_keycode = keycode | new_modifiers;
-                 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
-                 unsigned long some_state = 0;
-                 inev.code = KeyTranslate (kchr_ptr, new_keycode,
-                                           &some_state) & 0xff;
+                 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++;
                }
-             else
-               inev.code = er.message & charCodeMask;
-             inev.kind = ASCII_KEYSTROKE_EVENT;
+             last_key_script = current_key_script;
            }
-       }
 
-       /* 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;
+           ObscureCursor ();
 
-           if (converter ==  NULL)
+           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
              {
-               the_err = TECCreateConverter (&converter,
-                                             kTextEncodingMacRoman,
-                                             mac_keyboard_text_encoding);
-               current_mac_keyboard_text_encoding
-                 = mac_keyboard_text_encoding;
+               clear_mouse_face (dpyinfo);
+               dpyinfo->mouse_face_hidden = 1;
              }
-           else if (mac_keyboard_text_encoding
-                    != current_mac_keyboard_text_encoding)
+
+           if (keycode_to_xkeysym (keycode, &xkeysym))
              {
-               /* Free the converter for the current encoding before
-                  creating a new one.  */
-               TECDisposeConverter (converter);
-               the_err = TECCreateConverter (&converter,
-                                             kTextEncodingMacRoman,
-                                             mac_keyboard_text_encoding);
-               current_mac_keyboard_text_encoding
-                 = mac_keyboard_text_encoding;
+               inev.code = 0xff00 | xkeysym;
+               inev.kind = NON_ASCII_KEYSTROKE_EVENT;
              }
-
-           if (the_err == noErr)
+           else
              {
-               unsigned char ch = inev.code;
-               ByteCount actual_input_length, actual_output_length;
-               unsigned char outch;
-
-               convert_status = TECConvertText (converter, &ch, 1,
-                                                &actual_input_length,
-                                                &outch, 1,
-                                                &actual_output_length);
-               if (convert_status == noErr
-                   && actual_input_length == 1
-                   && actual_output_length == 1)
-                 inev.code = outch;
+               if (er.modifiers & (controlKey |
+                                   (NILP (Vmac_command_key_is_meta) ? optionKey
+                                    : cmdKey)))
+                 {
+                   /* This code comes from Keyboard Resource,
+                      Appendix C of IM - Text.  This is necessary
+                      since shift is ignored in KCHR table
+                      translation when option or command is pressed.
+                      It also does not translate correctly
+                      control-shift chars like C-% so mask off shift
+                      here also */
+                   int new_modifiers = er.modifiers & 0xe600;
+                   /* mask off option and command */
+                   int new_keycode = keycode | new_modifiers;
+                   Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+                   unsigned long some_state = 0;
+                   inev.code = KeyTranslate (kchr_ptr, new_keycode,
+                                             &some_state) & 0xff;
+                 }
+               else if (!NILP (Vmac_option_modifier)
+                        && (er.modifiers & optionKey))
+                 {
+                   /* When using the option key as an emacs modifier,
+                      convert the pressed key code back to one
+                      without the Mac option modifier applied. */
+                   int new_modifiers = er.modifiers & ~optionKey;
+                   int new_keycode = keycode | new_modifiers;
+                   Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+                   unsigned long some_state = 0;
+                   inev.code = KeyTranslate (kchr_ptr, new_keycode,
+                                             &some_state) & 0xff;
+                 }
+               else
+                 inev.code = er.message & charCodeMask;
+               inev.kind = ASCII_KEYSTROKE_EVENT;
              }
          }
 
 #if USE_CARBON_EVENTS
-       inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
+         inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
-       inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+         inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
+         inev.modifiers |= (extra_keyboard_modifiers
+                            & (meta_modifier | alt_modifier
+                               | hyper_modifier | super_modifier));
+         XSETFRAME (inev.frame_or_window, mac_focus_frame (dpyinfo));
+         break;
 
-       {
-         mac_output *mwp
-           = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
-         XSETFRAME (inev.frame_or_window, mwp->mFP);
-       }
-
-       inev.timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
-       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 = FrontNonFloatingWindow ();
-
-           if (!wp)
-             {
-               struct frame *f = XFRAME (XCAR (Vframe_list));
-               CollapseWindow (FRAME_MAC_WINDOW (f), false);
-               wp = FrontNonFloatingWindow ();
-             }
-
-            if (wp && is_emacs_window(wp))
-               f = ((mac_output *) GetWRefCon (wp))->mFP;
+       case kHighLevelEvent:
+         read_socket_inev = &inev;
+         AEProcessAppleEvent (&er);
+         read_socket_inev = NULL;
+         break;
 
-            inev.kind = DRAG_N_DROP_EVENT;
-            inev.code = 0;
-            inev.timestamp = er.when * (1000 / 60);
-             /* ticks to milliseconds */
+       default:
+         break;
+       }
 #if USE_CARBON_EVENTS
-           inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-           inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+      ReleaseEvent (eventRef);
 #endif
 
-            XSETINT (inev.x, 0);
-            XSETINT (inev.y, 0);
+      if (inev.kind != NO_EVENT)
+       {
+         inev.timestamp = timestamp;
+         kbd_buffer_store_event_hold (&inev, hold_quit);
+         count++;
+       }
 
-            XSETFRAME (frame, f);
-            inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
+      if (do_help
+         && !(hold_quit && hold_quit->kind != NO_EVENT))
+       {
+         Lisp_Object frame;
 
-            /* 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;
+         if (f)
+           XSETFRAME (frame, f);
+         else
+           frame = Qnil;
+
+         if (do_help > 0)
+           {
+             any_help_event_p = 1;
+             gen_help_event (help_echo_string, frame, help_echo_window,
+                             help_echo_object, help_echo_pos);
+           }
+         else
+           {
+             help_echo_string = Qnil;
+             gen_help_event (Qnil, frame, Qnil, Qnil, 0);
+           }
+         count++;
+       }
 
-               GetWindowPortBounds (wp, &r);
-               InvalWindowRect (wp, &r);
-             }
-#else /* not TARGET_API_MAC_CARBON */
-              InvalRect (&(wp->portRect));
-#endif /* not TARGET_API_MAC_CARBON */
-          }
-      default:
-       break;
-      }
-#if USE_CARBON_EVENTS
-      ReleaseEvent (eventRef);
     }
-#endif
 
   /* If the focus was just given to an autoraising frame,
      raise it now.  */
@@ -8584,61 +9801,28 @@ XTread_socket (int sd, int expected, struct input_event *hold_quit)
       pending_autoraise_frame = 0;
     }
 
-#if !TARGET_API_MAC_CARBON
-  check_alarm ();  /* simulate the handling of a SIGALRM */
-#endif
-
+#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).  */
   {
-    static Point old_mouse_pos = { -1, -1 };
+    Lisp_Object tail, frame;
 
-    if (app_is_suspended)
-      {
-        old_mouse_pos.h = -1;
-        old_mouse_pos.v = -1;
-      }
-    else
+    FOR_EACH_FRAME (tail, frame)
       {
-        Point mouse_pos;
-        WindowPtr wp;
-        struct frame *f;
-        Lisp_Object bar;
-        struct scroll_bar *sb;
-
-        wp = FrontWindow ();
-       if (is_emacs_window (wp))
-         {
-           f = ((mac_output *) GetWRefCon (wp))->mFP;
-
-#if TARGET_API_MAC_CARBON
-           SetPort (GetWindowPort (wp));
-#else
-           SetPort (wp);
-#endif
+       struct frame *f = XFRAME (frame);
 
-           GetMouse (&mouse_pos);
-
-           if (!EqualPt (mouse_pos, old_mouse_pos))
-             {
-               if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
-                   && 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);
+       /* The tooltip has been drawn already.  Avoid the
+          SET_FRAME_GARBAGED in mac_handle_visibility_change.  */
+       if (EQ (frame, tip_frame))
+         continue;
 
-               old_mouse_pos = mouse_pos;
-             }
-         }
+       if (FRAME_MAC_P (f))
+         mac_handle_visibility_change (f);
       }
   }
-
-  if (inev.kind != NO_EVENT)
-    {
-      kbd_buffer_store_event_hold (&inev, hold_quit);
-      count++;
-    }
+#endif
 
   UNBLOCK_INPUT;
   return count;
@@ -8663,106 +9847,70 @@ __convert_from_newlines (unsigned char * p, size_t * n)
 }
 #endif
 
-
-/* Initialize the struct pointed to by MW to represent a new COLS x
-   ROWS Macintosh window, using font with name FONTNAME and size
-   FONTSIZE.  */
+#ifdef MAC_OS8
 void
-NewMacWindow (FRAME_PTR fp)
+make_mac_terminal_frame (struct frame *f)
 {
-  mac_output *mwp;
-#if TARGET_API_MAC_CARBON
-  static int making_terminal_window = 0;
-#else
-  static int making_terminal_window = 1;
-#endif
-
-  mwp = fp->output_data.mac;
-
-  if (making_terminal_window)
-    {
-      if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
-                                     (WindowPtr) -1)))
-        abort ();
-      making_terminal_window = 0;
-    }
-  else
-    if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
-      abort ();
-
-  SetWRefCon (mwp->mWP, (long) mwp);
-    /* so that update events can find this mac_output struct */
-  mwp->mFP = fp;  /* point back to emacs frame */
+  Lisp_Object frame;
+  Rect r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (mwp->mWP));
-#else
-  SetPort (mwp->mWP);
-#endif
+  XSETFRAME (frame, f);
 
-  mwp->fontset = -1;
+  f->output_method = output_mac;
+  f->output_data.mac = (struct mac_output *)
+    xmalloc (sizeof (struct mac_output));
+  bzero (f->output_data.mac, sizeof (struct mac_output));
 
-  SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
-  ShowWindow (mwp->mWP);
+  XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
 
-}
+  FRAME_COLS (f) = 96;
+  FRAME_LINES (f) = 4;
 
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
 
-void
-make_mac_frame (struct frame *f)
-{
   FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
 
-  NewMacWindow(f);
-
   f->output_data.mac->cursor_pixel = 0;
   f->output_data.mac->border_pixel = 0x00ff00;
   f->output_data.mac->mouse_pixel = 0xff00ff;
   f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
 
+  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->scroll_bar_foreground_pixel = -1;
-  f->output_data.mac->scroll_bar_background_pixel = -1;
   f->output_data.mac->explicit_parent = 0;
-  f->left_pos = 4;
-  f->top_pos = 4;
+  f->left_pos = 8;
+  f->top_pos = 32;
   f->border_width = 0;
 
   f->internal_border_width = 0;
 
-  f->output_method = output_mac;
-
   f->auto_raise = 1;
   f->auto_lower = 1;
 
   f->new_text_cols = 0;
   f->new_text_lines = 0;
-}
-
-void
-make_mac_terminal_frame (struct frame *f)
-{
-  Lisp_Object frame;
-
-  XSETFRAME (frame, f);
-
-  f->output_method = output_mac;
-  f->output_data.mac = (struct mac_output *)
-    xmalloc (sizeof (struct mac_output));
-  bzero (f->output_data.mac, sizeof (struct mac_output));
-  FRAME_FONTSET (f) = -1;
-  f->output_data.mac->scroll_bar_foreground_pixel = -1;
-  f->output_data.mac->scroll_bar_background_pixel = -1;
 
-  XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
+  SetRect (&r, f->left_pos, f->top_pos,
+           f->left_pos + FRAME_PIXEL_WIDTH (f),
+           f->top_pos + FRAME_PIXEL_HEIGHT (f));
 
-  FRAME_COLS (f) = 96;
-  FRAME_LINES (f) = 4;
+  BLOCK_INPUT;
 
-  FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
-  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
+  if (!(FRAME_MAC_WINDOW (f) =
+       NewCWindow (NULL, &r, "\p", true, dBoxProc,
+                   (WindowPtr) -1, 1, (long) f->output_data.mac)))
+    abort ();
+  /* so that update events can find this mac_output struct */
+  f->output_data.mac->mFP = f;  /* point back to emacs frame */
 
-  make_mac_frame (f);
+  UNBLOCK_INPUT;
 
   x_make_gc (f);
 
@@ -8779,6 +9927,7 @@ make_mac_terminal_frame (struct frame *f)
                             Fcons (Fcons (Qbackground_color,
                                           build_string ("white")), Qnil));
 }
+#endif
 
 \f
 /***********************************************************************
@@ -8795,12 +9944,7 @@ mac_initialize_display_info ()
 
   bzero (dpyinfo, sizeof (*dpyinfo));
 
-  /* Put it on x_display_name_list.  */
-  x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
-                               x_display_name_list);
-  dpyinfo->name_list_element = XCAR (x_display_name_list);
-
-#if 0
+#ifdef MAC_OSX
   dpyinfo->mac_id_name
     = (char *) xmalloc (SCHARS (Vinvocation_name)
                        + SCHARS (Vsystem_name)
@@ -8818,10 +9962,29 @@ mac_initialize_display_info ()
   dpyinfo->resx = 75.0;
   dpyinfo->resy = 75.0;
   dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
+#ifdef MAC_OSX
+  /* HasDepth returns true if it is possible to have a 32 bit display,
+     but this may not be what is actually used.  Mac OSX can do better.
+     CGMainDisplayID is only available on OSX 10.2 and higher, but the
+     header for CGGetActiveDisplayList says that the first display returned
+     is the active one, so we use that.  */
+  {
+    CGDirectDisplayID disp_id[1];
+    CGDisplayCount disp_count;
+    CGDisplayErr error_code;
+
+    error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
+    if (error_code != 0)
+      error ("No display found, CGGetActiveDisplayList error %d", error_code);
+
+    dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
+  }
+#else
   for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
     if (HasDepth (main_device_handle, dpyinfo->n_planes,
                  gdDevType, dpyinfo->color_p))
       break;
+#endif
   dpyinfo->height = (**main_device_handle).gdRect.bottom;
   dpyinfo->width = (**main_device_handle).gdRect.right;
   dpyinfo->grabbed = 0;
@@ -8832,6 +9995,22 @@ mac_initialize_display_info ()
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
   dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
   dpyinfo->mouse_face_window = Qnil;
+  dpyinfo->mouse_face_overlay = Qnil;
+  dpyinfo->mouse_face_hidden = 0;
+}
+
+
+static XrmDatabase
+mac_make_rdb (xrm_option)
+     char *xrm_option;
+{
+  XrmDatabase database;
+
+  database = xrm_get_preference_database (NULL);
+  if (xrm_option)
+    xrm_merge_string_database (database, xrm_option);
+
+  return database;
 }
 
 struct mac_display_info *
@@ -8841,7 +10020,8 @@ mac_term_init (display_name, xrm_option, resource_name)
      char *resource_name;
 {
   struct mac_display_info *dpyinfo;
-  GDHandle main_device_handle;
+
+  BLOCK_INPUT;
 
   if (!mac_initialized)
     {
@@ -8849,17 +10029,91 @@ mac_term_init (display_name, xrm_option, resource_name)
       mac_initialized = 1;
     }
 
-  mac_initialize_display_info (display_name);
+  if (x_display_list)
+    error ("Sorry, this version can only handle one display");
+
+  mac_initialize_display_info ();
 
   dpyinfo = &one_mac_display_info;
 
-  main_device_handle = LMGetMainDevice();
+  dpyinfo->xrdb = mac_make_rdb (xrm_option);
 
-  dpyinfo->height = (**main_device_handle).gdRect.bottom;
-  dpyinfo->width = (**main_device_handle).gdRect.right;
+  /* 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,
+                                     Fcons (Qnil, dpyinfo->xrdb)),
+                               x_display_name_list);
+  dpyinfo->name_list_element = XCAR (x_display_name_list);
+
+  UNBLOCK_INPUT;
 
   return dpyinfo;
 }
+/* Get rid of display DPYINFO, assuming all frames are already gone.  */
+
+void
+x_delete_display (dpyinfo)
+     struct mac_display_info *dpyinfo;
+{
+  int i;
+
+  /* Discard this display from x_display_name_list and x_display_list.
+     We can't use Fdelq because that can quit.  */
+  if (! NILP (x_display_name_list)
+      && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
+    x_display_name_list = XCDR (x_display_name_list);
+  else
+    {
+      Lisp_Object tail;
+
+      tail = x_display_name_list;
+      while (CONSP (tail) && CONSP (XCDR (tail)))
+       {
+         if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
+           {
+             XSETCDR (tail, XCDR (XCDR (tail)));
+             break;
+           }
+         tail = XCDR (tail);
+       }
+    }
+
+  if (x_display_list == dpyinfo)
+    x_display_list = dpyinfo->next;
+  else
+    {
+      struct x_display_info *tail;
+
+      for (tail = x_display_list; tail; tail = tail->next)
+       if (tail->next == dpyinfo)
+         tail->next = tail->next->next;
+    }
+
+  /* Free the font names in the font table.  */
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name)
+      {
+       if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
+         xfree (dpyinfo->font_table[i].full_name);
+       xfree (dpyinfo->font_table[i].name);
+      }
+
+  if (dpyinfo->font_table->font_encoder)
+    xfree (dpyinfo->font_table->font_encoder);
+
+  xfree (dpyinfo->font_table);
+  xfree (dpyinfo->mac_id_name);
+
+  if (x_display_list == 0)
+    {
+      mac_clear_font_name_table ();
+      bzero (dpyinfo, sizeof (*dpyinfo));
+    }
+}
+
 \f
 #ifdef MAC_OSX
 void
@@ -8906,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
@@ -8980,30 +10234,63 @@ mac_check_for_quit_char ()
   mac_determine_quit_char_modifiers ();
 
   /* Fill the queue with events */
+  BLOCK_INPUT;
   ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
   event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
                                    NULL);
+  UNBLOCK_INPUT;
   if (event)
     {
       struct input_event e;
-      struct mac_output *mwp =
-       (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
+
       /* Use an input_event to emulate what the interrupt handler does. */
       EVENT_INIT (e);
       e.kind = ASCII_KEYSTROKE_EVENT;
       e.code = quit_char;
-      e.arg = NULL;
+      e.arg = Qnil;
       e.modifiers = NULL;
       e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
-      XSETFRAME (e.frame_or_window, mwp->mFP);
+      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.  */
 
@@ -9022,7 +10309,7 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   x_cursor_to,
   x_flush,
-  x_flush,
+  0, /* flush_display_optional */
   x_clear_window_mouse_face,
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
@@ -9031,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,
@@ -9073,67 +10360,35 @@ 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
-
-  mac_initialize_display_info ();
+  BLOCK_INPUT;
 
 #if TARGET_API_MAC_CARBON
   init_required_apple_events ();
 
-  init_mac_drag_n_drop ();
-
 #if USE_CARBON_EVENTS
+#ifdef MAC_OSX
   init_service_handler ();
 
   init_quit_char_handler ();
-#endif
+#endif /* MAC_OSX */
 
-  DisableMenuCommand (NULL, kHICommandQuit);
+  init_command_handler ();
 
+  init_menu_bar ();
+#endif /* USE_CARBON_EVENTS */
+
+#ifdef MAC_OSX
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
+#endif
+  UNBLOCK_INPUT;
 }
 
 
@@ -9145,7 +10400,27 @@ syms_of_macterm ()
   x_error_message_string = Qnil;
 #endif
 
+  Qmodifier_value = intern ("modifier-value");
+  Qalt = intern ("alt");
+  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
+  Qhyper = intern ("hyper");
+  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
+  Qsuper = intern ("super");
+  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+
+  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
 
   staticpro (&Qreverse);
   Qreverse = intern ("reverse");
@@ -9156,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;
@@ -9201,20 +10450,26 @@ to 4.1, set this to nil.  */);
 Otherwise the option key is used.  */);
   Vmac_command_key_is_meta = Qt;
 
+  DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
+    doc: /* Modifier to use for the Mac alt/option key.  The value can
+be alt, hyper, or super for the respective modifier.  If the value is
+nil then the key will act as the normal Mac option modifier.  */);
+  Vmac_option_modifier = Qnil;
+
   DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
     doc: /* Non-nil means that the control and meta keys are reversed.  This is
-           useful for non-standard keyboard layouts.  */);
+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
@@ -9233,22 +10488,30 @@ Toolbox for processing before Emacs sees it.  */);
    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_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;
+  DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
+   doc: /* If non-nil, allow anti-aliasing.
+The text will be rendered using Core Graphics text rendering which
+may anti-alias the text.  */);
+  Vmac_use_core_graphics = Qnil;
+
+  /* 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