]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
(x_clip_to_row): Add area arg. Callers changed.
[gnu-emacs] / src / macterm.c
index 328464fcad681e1065cd14273b8681cceeb7f7ff..f4f9235c8464df4688204c9821b975c5c76343b1 100644 (file)
@@ -1,5 +1,5 @@
 /* Implementation of GUI terminal on the Mac OS.
-   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -35,29 +35,6 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 #ifdef MAC_OSX
-#undef mktime
-#undef DEBUG
-#undef free
-#undef malloc
-#undef realloc
-/* Macros max and min defined in lisp.h conflict with those in
-   precompiled header Carbon.h.  */
-#undef max
-#undef min
-#undef init_process
-#include <Carbon/Carbon.h>
-#undef free
-#define free unexec_free
-#undef malloc
-#define malloc unexec_malloc
-#undef realloc
-#define realloc unexec_realloc
-#undef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#undef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#undef init_process
-#define init_process emacs_init_process
 /* 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.  */
@@ -73,10 +50,10 @@ 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>
@@ -108,8 +85,6 @@ Boston, MA 02111-1307, USA.  */
 #include "composite.h"
 #include "coding.h"
 
-#define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
-
 /* Set of macros that handle mapping of Mac modifier keys to emacs.  */
 #define macCtrlKey     (NILP (Vmac_reverse_ctrl_meta) ? controlKey :   \
                        (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
@@ -121,24 +96,10 @@ Boston, MA 02111-1307, USA.  */
 
 \f
 
-extern Lisp_Object Qhelp_echo;
-
 /* Non-nil means Emacs uses toolkit scroll bars.  */
 
 Lisp_Object Vx_toolkit_scroll_bars;
 
-/* If a string, XTread_socket generates an event to display that string.
-   (The display is done in read_char.)  */
-
-static Lisp_Object help_echo;
-static Lisp_Object help_echo_window;
-static Lisp_Object help_echo_object;
-static int help_echo_pos;
-
-/* Temporary variable for XTread_socket.  */
-
-static Lisp_Object previous_help_echo;
-
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    start.  */
 
@@ -148,15 +109,14 @@ static int any_help_event_p;
 
 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.  */
 
-int x_stretch_cursor_p;
-
-/* Non-zero means make use of UNDERLINE_POSITION font properties.  */
-
-int x_use_underline_position_properties;
 
 /* This is a chain of structures for all the X displays currently in
    use.  */
@@ -186,12 +146,6 @@ extern int waiting_for_input;
 
 struct frame *pending_autoraise_frame;
 
-/* Nominal cursor position -- where to draw output.
-   HPOS and VPOS are window relative glyph matrix coordinates.
-   X and Y are window relative pixel coordinates.  */
-
-struct cursor_pos output_cursor;
-
 /* Non-zero means user is interacting with a toolkit scroll bar.  */
 
 static int toolkit_scroll_bar_interaction;
@@ -218,7 +172,6 @@ static int toolkit_scroll_bar_interaction;
 
 /* Where the mouse was last time we reported a mouse event.  */
 
-FRAME_PTR last_mouse_frame;
 static Rect last_mouse_glyph;
 static Lisp_Object last_mouse_press_frame;
 
@@ -243,14 +196,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
@@ -277,22 +222,22 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
 extern Lisp_Object Vx_no_window_manager;
 
-extern Lisp_Object Qface, Qmouse_face;
-
 extern int errno;
 
 /* A mask of extra modifier bits to put into every keyboard char.  */
 
 extern int extra_keyboard_modifiers;
 
+/* The keysyms to use for the various modifiers.  */
+
+static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
+
 static Lisp_Object Qvendor_specific_keysyms;
 
 #if 0
 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
 #endif
 
-extern Lisp_Object x_icon_type P_ ((struct frame *));
-
 extern int inhibit_window_system;
 
 #if __MRC__
@@ -303,22 +248,7 @@ QDGlobals qd;  /* QuickDraw global information structure.  */
 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 frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
-static int fast_find_position P_ ((struct window *, int, int *, int *,
-                                  int *, int *, Lisp_Object));
-static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
-                                    int *, int *, int *, int *, int));
-static void set_output_cursor P_ ((struct cursor_pos *));
-static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
-                                          int *, int *, int *, int));
-static void note_mode_line_highlight P_ ((struct window *, int, int));
-static void note_mouse_highlight P_ ((struct frame *, int, int));
-static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
-static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
-static void show_mouse_face P_ ((struct x_display_info *,
-                                enum draw_glyphs_face));
-static int cursor_in_mouse_face_p P_ ((struct window *));
-static int clear_mouse_face P_ ((struct mac_display_info *));
+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));
@@ -333,59 +263,33 @@ void x_wm_set_icon_pixmap P_ ((struct frame *, int));
 void mac_initialize P_ ((void));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
-static void x_draw_phys_cursor_glyph P_ ((struct window *,
-                                         struct glyph_row *,
-                                         enum draw_glyphs_face));
 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 XTcursor_to P_ ((int, int, int, int));
-static void x_write_glyphs P_ ((struct glyph *, int));
-static void x_clear_end_of_line P_ ((int));
 static void x_clear_frame P_ ((void));
-static void x_clear_cursor P_ ((struct window *));
 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 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));
-static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
-static void expose_frame P_ ((struct frame *, int, int, int, int));
-static int expose_window_tree P_ ((struct window *, Rect *));
-static void expose_overlaps P_ ((struct window *, struct glyph_row *,
-                                struct glyph_row *));
-static int expose_window P_ ((struct window *, Rect *));
-static void expose_area P_ ((struct window *, struct glyph_row *,
-                            Rect *, enum glyph_row_area));
-static int expose_line P_ ((struct window *, struct glyph_row *,
-                           Rect *));
-void x_display_cursor (struct window *, int, int, int, int, int);
-void x_update_cursor P_ ((struct frame *, int));
-static void x_update_cursor_in_window_tree P_ ((struct window *, int));
-static void x_update_window_cursor P_ ((struct window *, int));
-static void x_erase_phys_cursor P_ ((struct window *));
-void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
-                              GC, int));
-static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
+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 *, 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_draw_vertical_border P_ ((struct window *));
 static void x_after_update_window_line P_ ((struct glyph_row *));
 
-static void activate_scroll_bars (FRAME_PTR);
-static void deactivate_scroll_bars (FRAME_PTR);
+void activate_scroll_bars (FRAME_PTR);
+void deactivate_scroll_bars (FRAME_PTR);
 
 static int is_emacs_window (WindowPtr);
 
-extern int image_ascent (struct image *, struct face *);
-void x_set_offset (struct frame *, int, int, int);
 int x_bitmap_icon (struct frame *, Lisp_Object);
 void x_make_frame_visible (struct frame *);
 
@@ -397,15 +301,12 @@ extern void set_frame_menubar (FRAME_PTR, int, int);
 
 /* X display function emulation */
 
-static void
+void
 XFreePixmap (display, pixmap)
-     Display *display;
+     Display *display;         /* not used */
      Pixmap pixmap;
 {
-  PixMap *p = (PixMap *) pixmap;
-
-  xfree (p->baseAddr);
-  xfree (p);
+  DisposeGWorld (pixmap);
 }
 
 
@@ -417,9 +318,9 @@ mac_set_forecolor (unsigned long color)
 {
   RGBColor fg_color;
 
-  fg_color.red = RED_FROM_ULONG (color) * 256;
-  fg_color.green = GREEN_FROM_ULONG (color) * 256;
-  fg_color.blue = BLUE_FROM_ULONG (color) * 256;
+  fg_color.red = RED16_FROM_ULONG (color);
+  fg_color.green = GREEN16_FROM_ULONG (color);
+  fg_color.blue = BLUE16_FROM_ULONG (color);
 
   RGBForeColor (&fg_color);
 }
@@ -433,9 +334,9 @@ mac_set_backcolor (unsigned long color)
 {
   RGBColor bg_color;
 
-  bg_color.red = RED_FROM_ULONG (color) * 256;
-  bg_color.green = GREEN_FROM_ULONG (color) * 256;
-  bg_color.blue = BLUE_FROM_ULONG (color) * 256;
+  bg_color.red = RED16_FROM_ULONG (color);
+  bg_color.green = GREEN16_FROM_ULONG (color);
+  bg_color.blue = BLUE16_FROM_ULONG (color);
 
   RGBBackColor (&bg_color);
 }
@@ -459,16 +360,35 @@ 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);
+
+  MoveTo (x1, y1);
+  LineTo (x2, y2);
+}
+
+void
+mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
+     Display *display;
+     Pixmap p;
+     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);
 
+  LockPixels (GetGWorldPixMap (p));
   MoveTo (x1, y1);
   LineTo (x2, y2);
+  UnlockPixels (GetGWorldPixMap (p));
+
+  SetGWorld (old_port, old_gdh);
 }
 
 /* Mac version of XClearArea.  */
@@ -488,11 +408,7 @@ XClearArea (display, w, x, y, width, height, exposures)
   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);
   SetRect (&r, x, y, x + width, y + height);
@@ -513,11 +429,7 @@ XClearWindow (display, w)
   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);
 
@@ -537,35 +449,34 @@ XClearWindow (display, w)
 /* Mac replacement for XCopyArea.  */
 
 static void
-mac_draw_bitmap (display, w, gc, x, y, bitmap)
+mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
      Display *display;
      WindowPtr w;
      GC gc;
-     int x, y;
-     BitMap *bitmap;
+     int x, y, width, height;
+     unsigned short *bits;
+     int overlay_p;
 {
+  BitMap bitmap;
   Rect r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
+  bitmap.rowBytes = sizeof(unsigned short);
+  bitmap.baseAddr = (char *)bits;
+  SetRect (&(bitmap.bounds), 0, 0, width, height);
+
+  SetPortWindowPort (w);
 
   mac_set_colors (gc);
-  SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
+  SetRect (&r, x, y, x + width, y + height);
 
 #if TARGET_API_MAC_CARBON
-  {
-    PixMapHandle pmh;
-
-    LockPortBits (GetWindowPort (w));
-    pmh = GetPortPixMap (GetWindowPort (w));
-    CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
-    UnlockPortBits (GetWindowPort (w));
-  }
+  LockPortBits (GetWindowPort (w));
+  CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
+           &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
+  UnlockPortBits (GetWindowPort (w));
 #else /* not TARGET_API_MAC_CARBON */
-  CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
+  CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
+           overlay_p ? srcOr : srcCopy, 0);
 #endif /* not TARGET_API_MAC_CARBON */
 }
 
@@ -578,11 +489,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);
 }
@@ -597,17 +504,30 @@ 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
@@ -616,18 +536,19 @@ mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
      char *bits;
      int w, h;
 {
-  int bytes_per_row, i, j;
+  int i, j, w1;
+  char *p;
 
-  bitmap->rowBytes = (w + 15) / 16 * 2;  /* must be on word boundary */
+  w1 = (w + 7) / 8;         /* nb of 8bits elt in X bitmap */
+  bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
   bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
-  if (!bitmap->baseAddr)
-    abort ();
-
   bzero (bitmap->baseAddr, bitmap->rowBytes * h);
   for (i = 0; i < h; i++)
-    for (j = 0; j < w; j++)
-      if (BitTst (bits, i * w + j))
-        BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
+    {
+      p = bitmap->baseAddr + i * bitmap->rowBytes;
+      for (j = 0; j < w1; j++)
+        *p++ = reflect_byte (*bits++);
+    }
 
   SetRect (&(bitmap->bounds), 0, 0, w, h);
 }
@@ -640,6 +561,67 @@ mac_free_bitmap (bitmap)
   xfree (bitmap->baseAddr);
 }
 
+
+Pixmap
+XCreatePixmap (display, w, width, height, depth)
+     Display *display;         /* not used */
+     WindowPtr w;
+     unsigned int width, height;
+     unsigned int depth;       /* not used */
+{
+  Pixmap pixmap;
+  Rect r;
+  QDErr err;
+
+  SetPortWindowPort (w);
+
+  SetRect (&r, 0, 0, width, height);
+  err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
+  if (err != noErr)
+    return NULL;
+  return pixmap;
+}
+
+
+Pixmap
+XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
+     Display *display;         /* not used */
+     WindowPtr w;
+     char *data;
+     unsigned int width, height;
+     unsigned long fg, bg;
+     unsigned int depth;       /* not used */
+{
+  Pixmap pixmap;
+  BitMap bitmap;
+  CGrafPtr old_port;
+  GDHandle old_gdh;
+
+  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);
+  LockPixels (GetGWorldPixMap (pixmap));
+#if TARGET_API_MAC_CARBON
+  CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
+           &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
+           &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;
+}
+
+
 /* Mac replacement for XFillRectangle.  */
 
 static void
@@ -652,16 +634,37 @@ 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);
+  SetRect (&r, x, y, x + width, y + height);
+
+  PaintRect (&r); /* using foreground color of gc */
+}
+
+
+static void
+mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
+     Display *display;
+     Pixmap p;
+     GC gc;
+     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);
   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);
 }
 
 
@@ -677,11 +680,7 @@ 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);
   SetRect (&r, x, y, x + width + 1, y + height + 1);
@@ -700,20 +699,20 @@ mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
      int x, y;
      unsigned int width, height;
 {
-#if 0 /* MAC_TODO: draw a rectangle in a PixMap */
+  CGrafPtr old_port;
+  GDHandle old_gdh;
   Rect r;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (w));
-#else
-  SetPort (w);
-#endif
-
+  GetGWorld (&old_port, &old_gdh);
+  SetGWorld (p, NULL);
   mac_set_colors (gc);
-  SetRect (&r, x, y, x + width, y + height);
+  SetRect (&r, x, y, x + width + 1, y + height + 1);
 
+  LockPixels (GetGWorldPixMap (p));
   FrameRect (&r); /* using foreground color of gc */
-#endif /* 0 */
+  UnlockPixels (GetGWorldPixMap (p));
+
+  SetGWorld (old_port, old_gdh);
 }
 
 
@@ -727,11 +726,7 @@ 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);
-#endif
+  SetPortWindowPort (w);
 
   mac_set_colors (gc);
 
@@ -822,29 +817,64 @@ mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
 {
   Rect src_r, dest_r;
 
+  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);
+
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  LockPixels (GetGWorldPixMap (src));
 #if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (dest));
-#else
-  SetPort (dest);
-#endif
+  LockPortBits (GetWindowPort (dest));
+  CopyBits (GetPortBitMapForCopyBits (src),
+           GetPortBitMapForCopyBits (GetWindowPort (dest)),
+           &src_r, &dest_r, srcCopy, 0);
+  UnlockPortBits (GetWindowPort (dest));
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
+           &src_r, &dest_r, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (src));
+}
 
-  mac_set_colors (gc);
+
+static void
+mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
+                        width, height, dest_x, dest_y)
+     Display *display;
+     Pixmap src, mask;
+     WindowPtr dest;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y;
+{
+  Rect src_r, dest_r;
+
+  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);
 
-#if TARGET_API_MAC_CARBON
-  {
-    PixMapHandle pmh;
+  ForeColor (blackColor);
+  BackColor (whiteColor);
 
-    LockPortBits (GetWindowPort (dest));
-    pmh = GetPortPixMap (GetWindowPort (dest));
-    CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
-    UnlockPortBits (GetWindowPort (dest));
-  }
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (mask));
+#if TARGET_API_MAC_CARBON
+  LockPortBits (GetWindowPort (dest));
+  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
+           GetPortBitMapForCopyBits (GetWindowPort (dest)),
+           &src_r, &src_r, &dest_r);
+  UnlockPortBits (GetWindowPort (dest));
 #else /* not TARGET_API_MAC_CARBON */
-  CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
+  CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
+           &(dest->portBits), &src_r, &src_r, &dest_r);
 #endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (mask));
+  UnlockPixels (GetGWorldPixMap (src));
 }
 
 
@@ -879,19 +909,20 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
 {
 #if TARGET_API_MAC_CARBON
   Rect gw_r, src_r, dest_r;
-  PixMapHandle pmh;
 
   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));
+  SetPortWindowPort (w);
 
   ForeColor (blackColor);
   BackColor (whiteColor);
 
   LockPortBits (GetWindowPort (w));
-  pmh = GetPortPixMap (GetWindowPort (w));
-  CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
+  {
+    const BitMap *bitmap = GetPortBitMapForCopyBits (GetWindowPort (w));
+    CopyBits (bitmap, bitmap, &src_r, &dest_r, srcCopy, 0);
+  }
   UnlockPortBits (GetWindowPort (w));
 
   mac_set_colors (gc);
@@ -934,25 +965,77 @@ static void
 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
                      dest_x, dest_y)
      Display *display;
-     Pixmap src;
-     Pixmap dest;
+     Pixmap src, dest;
      GC gc;
      int src_x, src_y;
      unsigned int width, height;
      int dest_x, dest_y;
 {
+  CGrafPtr old_port;
+  GDHandle old_gdh;
   Rect src_r, dest_r;
-  int src_right = ((PixMap *) src)->bounds.right;
-  int src_bottom = ((PixMap *) src)->bounds.bottom;
-  int w = src_right - src_x;
-  int h = src_bottom - src_y;
 
-  mac_set_colors (gc);
+  GetGWorld (&old_port, &old_gdh);
+  SetGWorld (dest, NULL);
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (dest));
+#if TARGET_API_MAC_CARBON
+  CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
+           &src_r, &dest_r, srcCopy, 0);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
+           &src_r, &dest_r, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (dest));
+  UnlockPixels (GetGWorldPixMap (src));
+
+  SetGWorld (old_port, old_gdh);
+}
+
+
+static void
+mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
+                                  width, height, dest_x, dest_y)
+     Display *display;
+     Pixmap src, mask, dest;
+     GC gc;
+     int src_x, src_y;
+     unsigned int width, height;
+     int dest_x, dest_y;
+{
+  CGrafPtr old_port;
+  GDHandle old_gdh;
+  Rect src_r, dest_r;
+
+  GetGWorld (&old_port, &old_gdh);
+  SetGWorld (dest, NULL);
+  ForeColor (blackColor);
+  BackColor (whiteColor);
+
+  SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+  SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
 
-  SetRect (&src_r, src_x, src_y, src_right, src_bottom);
-  SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
+  LockPixels (GetGWorldPixMap (src));
+  LockPixels (GetGWorldPixMap (mask));
+  LockPixels (GetGWorldPixMap (dest));
+#if TARGET_API_MAC_CARBON
+  CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
+           GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
+#else /* not TARGET_API_MAC_CARBON */
+  CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
+           &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
+#endif /* not TARGET_API_MAC_CARBON */
+  UnlockPixels (GetGWorldPixMap (dest));
+  UnlockPixels (GetGWorldPixMap (mask));
+  UnlockPixels (GetGWorldPixMap (src));
 
-  CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
+  SetGWorld (old_port, old_gdh);
 }
 
 
@@ -1009,7 +1092,7 @@ XGetGCValues (void* ignore, XGCValues *gc,
 
 /* Mac replacement for XSetForeground.  */
 
-static void
+void
 XSetForeground (display, gc, color)
      Display *display;
      GC gc;
@@ -1075,7 +1158,7 @@ x_flush (f)
       FOR_EACH_FRAME (rest, frame)
        x_flush (XFRAME (frame));
     }
-  else if (FRAME_X_P (f))
+  else if (FRAME_MAC_P (f))
     XFlush (FRAME_MAC_DISPLAY (f));
   UNBLOCK_INPUT;
 #endif /* TARGET_API_MAC_CARBON */
@@ -1155,7 +1238,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;
 
@@ -1169,31 +1252,17 @@ x_update_window_begin (w)
 }
 
 
-/* Draw a vertical window border to the right of window W if W doesn't
-   have vertical scroll bars.  */
+/* Draw a vertical window border from (x,y0) to (x,y1)  */
 
 static void
-x_draw_vertical_border (w)
+mac_draw_vertical_window_border (w, x, y0, y1)
      struct window *w;
+     int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 
-  /* Redraw borders between horizontally adjacent windows.  Don't
-     do it for frames with vertical scroll bars because either the
-     right scroll bar of a window, or the left scroll bar of its
-     neighbor will suffice as a border.  */
-  if (!WINDOW_RIGHTMOST_P (w)
-      && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-    {
-      int x0, x1, y0, y1;
-
-      window_box_edges (w, -1, &x0, &y0, &x1, &y1);
-      x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
-      y1 -= 1;
-
-      XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                f->output_data.mac->normal_gc, x1, y0, x1, y1);
-    }
+  XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+            f->output_data.mac->normal_gc, x, y0, x, y1);
 }
 
 
@@ -1215,19 +1284,20 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
      struct window *w;
      int cursor_on_p, mouse_face_overwritten_p;
 {
-  struct mac_display_info *dpyinfo
-    = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
 
   if (!w->pseudo_window_p)
     {
       BLOCK_INPUT;
 
       if (cursor_on_p)
-       x_display_and_set_cursor (w, 1, output_cursor.hpos,
-                                 output_cursor.vpos,
-                                 output_cursor.x, output_cursor.y);
+       display_and_set_cursor (w, 1, output_cursor.hpos,
+                               output_cursor.vpos,
+                               output_cursor.x, output_cursor.y);
+
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
 
-      x_draw_vertical_border (w);
       UNBLOCK_INPUT;
     }
 
@@ -1259,21 +1329,17 @@ static void
 x_update_end (f)
      struct frame *f;
 {
+  /* Mouse highlight may be displayed again.  */
+  FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
+
+  BLOCK_INPUT;
   /* Reset the background color of Mac OS Window to that of the frame after
      update so that it is used by Mac Toolbox to clear the update region before
      an update event is generated.  */
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
-#else
-  SetPort (FRAME_MAC_WINDOW (f));
-#endif
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
   mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
 
-  /* Mouse highlight may be displayed again.  */
-  FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
-
-  BLOCK_INPUT;
   XFlush (FRAME_MAC_DISPLAY (f));
   UNBLOCK_INPUT;
 }
@@ -1287,7 +1353,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);
 
@@ -1324,11 +1390,7 @@ x_after_update_window_line (desired_row)
   xassert (w);
 
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
-    {
-      BLOCK_INPUT;
-      draw_row_fringe_bitmaps (w, desired_row);
-      UNBLOCK_INPUT;
-    }
+    desired_row->redraw_fringe_bitmaps_p = 1;
 
   /* When a window has disappeared, make sure that no rest of
      full-width rows stays visible in the internal border.  Could
@@ -1355,7 +1417,7 @@ x_after_update_window_line (desired_row)
       XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
                  0, y, width, height, 0);
       XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 f->output_data.mac->pixel_width - width, y,
+                 FRAME_PIXEL_WIDTH (f) - width, y,
                  width, height, 0);
 
       UNBLOCK_INPUT;
@@ -1380,11 +1442,26 @@ x_draw_fringe_bitmap (w, row, p)
   XGCValues gcv;
   GC gc = f->output_data.mac->normal_gc;
   struct face *face = p->face;
+  int rowY;
 
   /* Must clip because of partially visible lines.  */
-  x_clip_to_row (w, row, gc, 1);
+  rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  if (p->y < rowY)
+    {
+      /* Adjust position of "bottom aligned" bitmap on partially
+        visible last row.  */
+      int oldY = row->y;
+      int oldVH = row->visible_height;
+      row->visible_height = p->h;
+      row->y -= rowY - p->y;
+      x_clip_to_row (w, row, -1, gc);
+      row->y = oldY;
+      row->visible_height = oldVH;
+    }
+  else
+    x_clip_to_row (w, row, -1, gc);
 
-  if (p->bx >= 0)
+  if (p->bx >= 0 && !p->overlay_p)
     {
       XGCValues gcv;
       gcv.foreground = face->background;
@@ -1410,18 +1487,18 @@ x_draw_fringe_bitmap (w, row, p)
 #endif
     }
 
-  if (p->which != NO_FRINGE_BITMAP)
+  if (p->which)
     {
-      unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh;
-      BitMap bitmap;
+      unsigned short *bits = p->bits + p->dh;
 
-      mac_create_bitmap_from_bitmap_data (&bitmap, bits, p->wd, p->h);
-      gcv.foreground = face->foreground;
+      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, &bitmap);
-
-      mac_free_bitmap (&bitmap);
+      mac_draw_bitmap (display, window, &gcv, p->x, p->y,
+                      p->wd, p->h, bits, p->overlay_p);
     }
 
   mac_reset_clipping (display, window);
@@ -1446,79 +1523,19 @@ XTreset_terminal_modes ()
 {
 }
 
-
 \f
 /***********************************************************************
-                           Output Cursor
+                          Display Iterator
  ***********************************************************************/
 
-/* Set the global variable output_cursor to CURSOR.  All cursor
-   positions are relative to updated_window.  */
-
-static void
-set_output_cursor (cursor)
-    struct cursor_pos *cursor;
-{
-  output_cursor.hpos = cursor->hpos;
-  output_cursor.vpos = cursor->vpos;
-  output_cursor.x = cursor->x;
-  output_cursor.y = cursor->y;
-}
-
-
-/* Set a nominal cursor position.
+/* Function prototypes of this page.  */
 
-   HPOS and VPOS are column/row positions in a window glyph matrix.  X
-   and Y are window text area relative pixel positions.
+static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
+static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
 
-   If this is done during an update, updated_window will contain the
-   window that is being updated and the position is the future output
-   cursor position for that window.  If updated_window is null, use
-   selected_window and display the cursor at the given position.  */
 
-static void
-XTcursor_to (vpos, hpos, y, x)
-     int vpos, hpos, y, x;
-{
-  struct window *w;
-
-  /* If updated_window is not set, work on selected_window.  */
-  if (updated_window)
-    w = updated_window;
-  else
-    w = XWINDOW (selected_window);
-
-  /* Set the output cursor.  */
-  output_cursor.hpos = hpos;
-  output_cursor.vpos = vpos;
-  output_cursor.x = x;
-  output_cursor.y = y;
-
-  /* If not called as part of an update, really display the cursor.
-     This will also set the cursor position of W.  */
-  if (updated_window == NULL)
-    {
-      BLOCK_INPUT;
-      x_display_cursor (w, 1, hpos, vpos, x, y);
-      XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
-      UNBLOCK_INPUT;
-    }
-}
-
-
-\f
-/***********************************************************************
-                          Display Iterator
- ***********************************************************************/
-
-/* Function prototypes of this page.  */
-
-static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
-static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
-
-
-/* Return a pointer to per-char metric information in FONT of a
-   character pointed by B which is a pointer to an XChar2b.  */
+/* Return a pointer to per-char metric information in FONT of a
+   character pointed by B which is a pointer to an XChar2b.  */
 
 #define PER_CHAR_METRIC(font, b)                                          \
   ((font)->per_char                                                       \
@@ -1685,33 +1702,6 @@ mac_encode_char (c, char2b, font_info, two_byte_p)
 }
 
 
-/* Estimate the pixel height of the mode or top line on frame F.
-   FACE_ID specifies what line's height to estimate.  */
-
-int
-x_estimate_mode_line_height (f, face_id)
-     struct frame *f;
-     enum face_id face_id;
-{
-  int height = FONT_HEIGHT (FRAME_FONT (f));
-
-  /* This function is called so early when Emacs starts that the face
-     cache and mode line face are not yet initialized.  */
-  if (FRAME_FACE_CACHE (f))
-      {
-       struct face *face = FACE_FROM_ID (f, face_id);
-       if (face)
-          {
-            if (face->font)
-              height = FONT_HEIGHT (face->font);
-           if (face->box_line_width > 0)
-             height += 2 * face->box_line_width;
-          }
-      }
-
-  return height;
-}
-
 \f
 /***********************************************************************
                            Glyph display
@@ -1741,11 +1731,10 @@ static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
-                                   int, int, int, int, Rect *));
+                                   int, int, int, int, int, int,
+                                   Rect *));
 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, Rect *));
-static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
-                                       enum glyph_row_area));
 
 #if GLYPH_DEBUG
 static void x_check_font P_ ((struct frame *, XFontStruct *));
@@ -1916,79 +1905,6 @@ x_set_glyph_string_gc (s)
 }
 
 
-/* Return in *R the clipping rectangle for glyph string S.  */
-
-static void
-x_get_glyph_string_clip_rect (s, r)
-     struct glyph_string *s;
-     Rect *r;
-{
-  int r_height, r_width;
-
-  if (s->row->full_width_p)
-    {
-      /* Draw full-width.  X coordinates are relative to S->w->left.  */
-      int canon_x = CANON_X_UNIT (s->f);
-
-      r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
-      r_width = XFASTINT (s->w->width) * canon_x;
-
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
-       {
-         int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
-         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
-           r->left -= width;
-       }
-
-      r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
-
-      /* Unless displaying a mode or menu bar line, which are always
-        fully visible, clip to the visible part of the row.  */
-      if (s->w->pseudo_window_p)
-       r_height = s->row->visible_height;
-      else
-       r_height = s->height;
-    }
-  else
-    {
-      /* This is a text line that may be partially visible.  */
-      r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
-      r_width = window_box_width (s->w, s->area);
-      r_height = s->row->visible_height;
-    }
-
-  /* If S draws overlapping rows, it's sufficient to use the top and
-     bottom of the window for clipping because this glyph string
-     intentionally draws over other lines.  */
-  if (s->for_overlaps_p)
-    {
-      r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
-      r_height = window_text_bottom_y (s->w) - r->top;
-    }
-  else
-    {
-      /* Don't use S->y for clipping because it doesn't take partially
-        visible lines into account.  For example, it can be negative for
-        partially visible lines at the top of a window.  */
-      if (!s->row->full_width_p
-         && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
-       r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
-      else
-       r->top = max (0, s->row->y);
-
-      /* If drawing a tool-bar window, draw it over the internal border
-        at the top of the window.  */
-      if (s->w == XWINDOW (s->f->tool_bar_window))
-       r->top -= s->f->output_data.mac->internal_border_width;
-    }
-
-  r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
-
-  r->bottom = r->top + r_height;
-  r->right = r->left + r_width;
-}
-
-
 /* Set clipping for output of glyph string S.  S may be part of a mode
    line or menu if we don't have X toolkit support.  */
 
@@ -1997,7 +1913,7 @@ x_set_glyph_string_clipping (s)
      struct glyph_string *s;
 {
   Rect r;
-  x_get_glyph_string_clip_rect (s, &r);
+  get_glyph_string_clip_rect (s, &r);
   mac_set_clip_rectangle (s->display, s->window, &r);
 }
 
@@ -2364,6 +2280,21 @@ x_copy_dpy_color (dpy, cmap, pixel)
 
 #endif /* MAC_TODO */
 
+
+/* Brightness beyond which a color won't have its highlight brightness
+   boosted.
+
+   Nominally, highlight colors for `3d' faces are calculated by
+   brightening an object's color by a constant scale factor, but this
+   doesn't yield good results for dark colors, so for colors who's
+   brightness is less than this value (on a scale of 0-255) have to
+   use an additional additive factor.
+
+   The value here is set so that the default menu-bar/mode-line color
+   (grey75) will not have its highlights changed at all.  */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
+
+
 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
    or DELTA.  Try a color with RGB values multiplied by FACTOR first.
    If this produces the same color as COLOR, try a color where all RGB
@@ -2379,12 +2310,42 @@ mac_alloc_lighter_color (f, color, factor, delta)
      int delta;
 {
   unsigned long new;
+  long bright;
+
+  /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
+  delta /= 256;
 
   /* Change RGB values by specified FACTOR.  Avoid overflow!  */
   xassert (factor >= 0);
   new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
                     min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
                     min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
+
+  /* Calculate brightness of COLOR.  */
+  bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
+            + BLUE_FROM_ULONG (*color)) / 6;
+
+  /* We only boost colors that are darker than
+     HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
+  if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+    /* Make an additive adjustment to NEW, because it's dark enough so
+       that scaling by FACTOR alone isn't enough.  */
+    {
+      /* How far below the limit this color is (0 - 1, 1 being darker).  */
+      double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+      /* The additive adjustment.  */
+      int min_delta = delta * dimness * factor / 2;
+
+      if (factor < 1)
+        new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
+                           max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
+                           max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
+      else
+        new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
+                           max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
+                           max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
+    }
+
   if (new == *color)
     new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
                       max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
@@ -2429,7 +2390,8 @@ x_setup_relief_color (f, relief, factor, delta, default_pixel)
   /* Allocate new color.  */
   xgcv.foreground = default_pixel;
   pixel = background;
-  if (mac_alloc_lighter_color (f, &pixel, factor, delta))
+  if (dpyinfo->n_planes != 1
+      && mac_alloc_lighter_color (f, &pixel, factor, delta))
     {
       relief->allocated_p = 1;
       xgcv.foreground = relief->pixel = pixel;
@@ -2459,6 +2421,10 @@ x_setup_relief_colors (s)
 
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
+  else if (s->first_glyph->type == IMAGE_GLYPH
+          && s->img->pixmap
+          && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+    color = IMAGE_BACKGROUND (s->img, s->f, 0);
   else
     {
       XGCValues xgcv;
@@ -2490,11 +2456,14 @@ x_setup_relief_colors (s)
 
 static void
 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
-                   raised_p, left_p, right_p, clip_rect)
+                   raised_p, top_p, bot_p, left_p, right_p, clip_rect)
      struct frame *f;
-     int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
+     int left_x, top_y, right_x, bottom_y, width;
+     int top_p, bot_p, left_p, right_p, raised_p;
      Rect *clip_rect;
 {
+  Display *dpy = FRAME_MAC_DISPLAY (f);
+  Window window = FRAME_MAC_WINDOW (f);
   int i;
   GC gc;
 
@@ -2502,41 +2471,43 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
     gc = f->output_data.mac->white_relief.gc;
   else
     gc = f->output_data.mac->black_relief.gc;
-  mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
+  mac_set_clip_rectangle (dpy, window, clip_rect);
 
   /* Top.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
-              left_x + i * left_p, top_y + i,
-              right_x + 1 - i * right_p, top_y + i);
+  if (top_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i * left_p, top_y + i,
+                right_x - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+      XDrawLine (dpy, window, gc,
                 left_x + i, top_y + i, left_x + i, bottom_y - i);
 
-  mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+  mac_reset_clipping (dpy, window);
   if (raised_p)
     gc = f->output_data.mac->black_relief.gc;
   else
     gc = f->output_data.mac->white_relief.gc;
-  mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+  mac_set_clip_rectangle (dpy, window,
                          clip_rect);
 
   /* Bottom.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
-              left_x + i * left_p, bottom_y - i,
-              right_x + 1 - i * right_p, bottom_y - i);
+  if (bot_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i * left_p, bottom_y - i,
+                right_x - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
-      XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
-                right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
+      XDrawLine (dpy, window, gc,
+                right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
 
-  mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+  mac_reset_clipping (dpy, window);
 }
 
 
@@ -2551,7 +2522,7 @@ static void
 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
                 left_p, right_p, clip_rect)
      struct glyph_string *s;
-     int left_x, top_y, right_x, bottom_y, left_p, right_p;
+     int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
      Rect *clip_rect;
 {
   XGCValues xgcv;
@@ -2561,21 +2532,21 @@ x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
 
   /* Top.  */
   XFillRectangle (s->display, s->window, &xgcv,
-                 left_x, top_y, right_x - left_x, width);
+                 left_x, top_y, right_x - left_x + 1, width);
 
   /* Left.  */
   if (left_p)
     XFillRectangle (s->display, s->window, &xgcv,
-                   left_x, top_y, width, bottom_y - top_y);
+                   left_x, top_y, width, bottom_y - top_y + 1);
 
   /* Bottom.  */
   XFillRectangle (s->display, s->window, &xgcv,
-                 left_x, bottom_y - width, right_x - left_x, width);
+                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
 
   /* Right.  */
   if (right_p)
     XFillRectangle (s->display, s->window, &xgcv,
-                   right_x - width, top_y, width, bottom_y - top_y);
+                   right_x - width + 1, top_y, width, bottom_y - top_y + 1);
 
   mac_reset_clipping (s->display, s->window);
 }
@@ -2596,9 +2567,10 @@ x_draw_glyph_string_box (s)
   if (s->row->full_width_p
       && !s->w->pseudo_window_p)
     {
-      last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
-       last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
+      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);
     }
 
   /* The glyph that may have a right box line.  */
@@ -2609,9 +2581,9 @@ x_draw_glyph_string_box (s)
   width = abs (s->face->box_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
-  right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
-             ? last_x - 1
-             : min (last_x, s->x + s->background_width) - 1));
+  right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
+            ? last_x - 1
+            : min (last_x, s->x + s->background_width) - 1);
   top_y = s->y;
   bottom_y = top_y + s->height - 1;
 
@@ -2624,7 +2596,7 @@ x_draw_glyph_string_box (s)
                 && (s->next == NULL
                     || s->next->hl != s->hl)));
 
-  x_get_glyph_string_clip_rect (s, &clip_rect);
+  get_glyph_string_clip_rect (s, &clip_rect);
 
   if (s->face->box == FACE_SIMPLE_BOX)
     x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
@@ -2633,7 +2605,7 @@ x_draw_glyph_string_box (s)
     {
       x_setup_relief_colors (s);
       x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
-                         width, raised_p, left_p, right_p, &clip_rect);
+                         width, raised_p, 1, 1, left_p, right_p, &clip_rect);
     }
 }
 
@@ -2644,57 +2616,57 @@ static void
 x_draw_image_foreground (s)
      struct glyph_string *s;
 {
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
-#if 0 /* MAC_TODO: image mask */
       if (s->img->mask)
        {
-         /* We can't set both a clip mask and use XSetClipRectangles
-            because the latter also sets a clip mask.  We also can't
-            trust on the shape extension to be available
-            (XShapeCombineRegion).  So, compute the rectangle to draw
-            manually.  */
-         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-                               | GCFunction);
-         XGCValues xgcv;
+         Rect nr;
          XRectangle clip_rect, image_rect, r;
 
-         xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
-         xgcv.function = GXcopy;
-         XChangeGC (s->display, s->gc, mask, &xgcv);
-
-         x_get_glyph_string_clip_rect (s, &clip_rect);
+         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->img->width;
-         image_rect.height = s->img->height;
+         image_rect.width = s->slice.width;
+         image_rect.height = s->slice.height;
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, 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 + r.x - x, s->slice.y + r.y - y,
+                                    r.width, r.height, r.x, r.y);
        }
       else
-#endif /* MAC_TODO */
        {
-         mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
-                      0, 0, s->img->width, s->img->height, x, y);
+         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);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2706,19 +2678,20 @@ x_draw_image_foreground (s)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
-                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+             mac_draw_rectangle (s->display, s->window, s->gc,
+                                 x - r, y - r,
+                                 s->slice.width + r*2 - 1,
+                                 s->slice.height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     mac_draw_rectangle (s->display, s->window, s->gc, x, y,
-                     s->img->width - 1, s->img->height - 1);
+                       s->slice.width - 1, s->slice.height - 1);
 }
 
 
-
 /* Draw a relief around the image glyph string S.  */
 
 static void
@@ -2727,21 +2700,22 @@ x_draw_image_relief (s)
 {
   int x0, y0, x1, y1, thick, raised_p;
   Rect r;
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -2757,12 +2731,17 @@ x_draw_image_relief (s)
 
   x0 = x - thick;
   y0 = y - thick;
-  x1 = x + s->img->width + thick - 1;
-  y1 = y + s->img->height + thick - 1;
+  x1 = x + s->slice.width + thick - 1;
+  y1 = y + s->slice.height + thick - 1;
 
   x_setup_relief_colors (s);
-  x_get_glyph_string_clip_rect (s, &r);
-  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+  get_glyph_string_clip_rect (s, &r);
+  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
+                     s->slice.y == 0,
+                     s->slice.y + s->slice.height == s->img->height,
+                     s->slice.x == 0,
+                     s->slice.x + s->slice.width == s->img->width,
+                     &r);
 }
 
 
@@ -2773,51 +2752,37 @@ x_draw_image_foreground_1 (s, pixmap)
      struct glyph_string *s;
      Pixmap pixmap;
 {
-  int x;
-  int y = s->ybase - s->y - image_ascent (s->img, s->face);
+  int x = 0;
+  int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = abs (s->face->box_line_width);
-  else
-    x = 0;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
-#if 0 /* MAC_TODO: image mask */
       if (s->img->mask)
-       {
-         /* We can't set both a clip mask and use XSetClipRectangles
-            because the latter also sets a clip mask.  We also can't
-            trust on the shape extension to be available
-            (XShapeCombineRegion).  So, compute the rectangle to draw
-            manually.  */
-         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-                               | GCFunction);
-         XGCValues xgcv;
-
-         xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
-         xgcv.function = GXcopy;
-         XChangeGC (s->display, s->gc, mask, &xgcv);
-
-         XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
-         XSetClipMask (s->display, s->gc, None);
-       }
+       mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
+                                          s->img->mask, pixmap, s->gc,
+                                          s->slice.x, s->slice.y,
+                                          s->slice.width, s->slice.height,
+                                          x, y);
       else
-#endif /* MAC_TODO */
        {
          mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
-                              0, 0, s->img->width, s->img->height, x, y);
+                                  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
@@ -2829,15 +2794,16 @@ x_draw_image_foreground_1 (s, pixmap)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
-                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+             mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
+                                 s->slice.width + r*2 - 1,
+                                 s->slice.height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
-                             s->img->width - 1, s->img->height - 1);
+                                 s->slice.width - 1, s->slice.height - 1);
 }
 
 
@@ -2870,7 +2836,7 @@ x_draw_glyph_string_bg_rect (s, x, y, w, h)
             |   s->face->box
             |
             |     +-------------------------
-            |     |  s->img->vmargin
+            |     |  s->img->margin
             |     |
             |     |       +-------------------
             |     |       |  the image
@@ -2889,44 +2855,41 @@ x_draw_image_glyph_string (s)
 
   height = s->height - 2 * box_line_vwidth;
 
+
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
-  if (height > s->img->height
+  if (height > s->slice.height
       || s->img->hmargin
       || s->img->vmargin
-#if 0 /* TODO: image mask */
       || s->img->mask
-#endif
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
-      if (box_line_hwidth && s->first_glyph->left_box_line_p)
-       x = s->x + box_line_hwidth;
-      else
-       x = s->x;
+      x = s->x;
+      if (s->first_glyph->left_box_line_p
+         && s->slice.x == 0)
+       x += box_line_hwidth;
+
+      y = s->y;
+      if (s->slice.y == 0)
+       y += box_line_vwidth;
 
-      y = s->y + box_line_vwidth;
-#if 0 /* TODO: image mask */
       if (s->img->mask)
        {
          /* Create a pixmap as large as the glyph string.  Fill it
             with the background color.  Copy the image to it, using
             its mask.  Copy the temporary pixmap to the display.  */
-         Screen *screen = FRAME_X_SCREEN (s->f);
-         int depth = DefaultDepthOfScreen (screen);
+         int depth = one_mac_display_info.n_planes;
 
          /* Create a pixmap as large as the glyph string.  */
          pixmap = XCreatePixmap (s->display, s->window,
                                  s->background_width,
                                  s->height, depth);
 
-         /* Don't clip in the following because we're working on the
-            pixmap.  */
-         XSetClipMask (s->display, s->gc, None);
-
          /* Fill the pixmap with the background color/stipple.  */
+#if 0 /* TODO: stipple */
          if (s->stippled_p)
            {
              /* Fill background with a stipple pattern.  */
@@ -2936,18 +2899,19 @@ x_draw_image_glyph_string (s)
              XSetFillStyle (s->display, s->gc, FillSolid);
            }
          else
+#endif
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
                            &xgcv);
              XSetForeground (s->display, s->gc, xgcv.background);
-             XFillRectangle (s->display, pixmap, s->gc,
-                             0, 0, s->background_width, s->height);
+             mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
+                                           0, 0, s->background_width,
+                                           s->height);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
       else
-#endif
        x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
 
       s->background_filled_p = 1;
@@ -2959,7 +2923,7 @@ x_draw_image_glyph_string (s)
       x_draw_image_foreground_1 (s, pixmap);
       x_set_glyph_string_clipping (s);
       mac_copy_area (s->display, pixmap, s->window, s->gc,
-                  0, 0, s->background_width, s->height, s->x, s->y);
+                    0, 0, s->background_width, s->height, s->x, s->y);
       mac_reset_clipping (s->display, s->window);
       XFreePixmap (s->display, pixmap);
     }
@@ -2988,7 +2952,7 @@ x_draw_stretch_glyph_string (s)
     {
       /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
         as wide as the stretch glyph.  */
-      int width = min (CANON_X_UNIT (s->f), s->background_width);
+      int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
 
       /* Draw cursor.  */
       x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
@@ -2996,10 +2960,10 @@ x_draw_stretch_glyph_string (s)
       /* Clear rest using the GC of the original non-cursor face.  */
       if (width < s->background_width)
        {
-         GC gc = s->face->gc;
          int x = s->x + width, y = s->y;
          int w = s->background_width - width, h = s->height;
          Rect r;
+         GC gc;
 
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
@@ -3010,7 +2974,7 @@ x_draw_stretch_glyph_string (s)
          else
            gc = s->face->gc;
 
-         x_get_glyph_string_clip_rect (s, &r);
+         get_glyph_string_clip_rect (s, &r);
          mac_set_clip_rectangle (s->display, s->window, &r);
 
 #if 0 /* MAC_TODO: stipple */
@@ -3059,7 +3023,6 @@ x_draw_glyph_string (s)
       x_set_glyph_string_gc (s->next);
       x_set_glyph_string_clipping (s->next);
       x_draw_glyph_string_background (s->next, 1);
-
     }
 
   /* Set up S->gc, set clipping and draw S.  */
@@ -3096,7 +3059,7 @@ x_draw_glyph_string (s)
       if (s->for_overlaps_p)
        s->background_filled_p = 1;
       else
-        x_draw_glyph_string_background (s, 0);
+       x_draw_glyph_string_background (s, 0);
       x_draw_glyph_string_foreground (s);
       break;
 
@@ -3173,151 +3136,28 @@ x_draw_glyph_string (s)
            }
        }
 
-      /* Draw relief.  */
+      /* Draw relief if not yet drawn.  */
       if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
-        x_draw_glyph_string_box (s);
+       x_draw_glyph_string_box (s);
     }
 
   /* Reset clipping.  */
   mac_reset_clipping (s->display, s->window);
 }
 
+/* Shift display to make room for inserted glyphs.   */
 
-/* Fix the display of area AREA of overlapping row ROW in window W.  */
-
-static void
-x_fix_overlapping_area (w, row, area)
-     struct window *w;
-     struct glyph_row *row;
-     enum glyph_row_area area;
-{
-  int i, x;
-
-  BLOCK_INPUT;
-
-  if (area == LEFT_MARGIN_AREA)
-    x = 0;
-  else if (area == TEXT_AREA)
-    x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-  else
-    x = (window_box_width (w, LEFT_MARGIN_AREA)
-        + window_box_width (w, TEXT_AREA));
-
-  for (i = 0; i < row->used[area];)
-    {
-      if (row->glyphs[area][i].overlaps_vertically_p)
-       {
-         int start = i, start_x = x;
-
-         do
-           {
-             x += row->glyphs[area][i].pixel_width;
-             ++i;
-           }
-         while (i < row->used[area]
-                && row->glyphs[area][i].overlaps_vertically_p);
-
-         x_draw_glyphs (w, start_x, row, area, start, i,
-                        DRAW_NORMAL_TEXT, 1);
-       }
-      else
-       {
-         x += row->glyphs[area][i].pixel_width;
-         ++i;
-       }
-    }
-
-  UNBLOCK_INPUT;
-}
-
-
-/* Output LEN glyphs starting at START at the nominal cursor position.
-   Advance the nominal cursor over the text.  The global variable
-   updated_window contains the window being updated, updated_row is
-   the glyph row being updated, and updated_area is the area of that
-   row being updated.  */
-
-static void
-x_write_glyphs (start, len)
-     struct glyph *start;
-     int len;
-{
-  int x, hpos;
-
-  xassert (updated_window && updated_row);
-  BLOCK_INPUT;
-
-  /* Write glyphs.  */
-
-  hpos = start - updated_row->glyphs[updated_area];
-  x = x_draw_glyphs (updated_window, output_cursor.x,
-                    updated_row, updated_area,
-                    hpos, hpos + len,
-                    DRAW_NORMAL_TEXT, 0);
-
-  UNBLOCK_INPUT;
-
-  /* Advance the output cursor.  */
-  output_cursor.hpos += len;
-  output_cursor.x = x;
-}
-
-
-/* Insert LEN glyphs from START at the nominal cursor position.   */
-
-static void
-x_insert_glyphs (start, len)
-     struct glyph *start;
-     register int len;
+void
+mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
+     struct frame *f;
+     int x, y, width, height, shift_by;
 {
-  struct frame *f;
-  struct window *w;
-  int line_height, shift_by_width, shifted_region_width;
-  struct glyph_row *row;
-  struct glyph *glyph;
-  int frame_x, frame_y, hpos;
-
-  xassert (updated_window && updated_row);
-  BLOCK_INPUT;
-  w = updated_window;
-  f = XFRAME (WINDOW_FRAME (w));
-
-  /* Get the height of the line we are in.  */
-  row = updated_row;
-  line_height = row->height;
-
-  /* Get the width of the glyphs to insert.  */
-  shift_by_width = 0;
-  for (glyph = start; glyph < start + len; ++glyph)
-    shift_by_width += glyph->pixel_width;
-
-  /* Get the width of the region to shift right.  */
-  shifted_region_width = (window_box_width (w, updated_area)
-                         - output_cursor.x
-                         - shift_by_width);
-
-  /* Shift right.  */
-  frame_x = window_box_left (w, updated_area) + output_cursor.x;
-  frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
-
   mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                f->output_data.mac->normal_gc,
-                frame_x, frame_y,
-                shifted_region_width, line_height,
-                frame_x + shift_by_width, frame_y);
-
-  /* Write the glyphs.  */
-  hpos = start - row->glyphs[updated_area];
-  x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
-                DRAW_NORMAL_TEXT, 0);
-
-  /* Advance the output cursor.  */
-  output_cursor.hpos += len;
-  output_cursor.x += shift_by_width;
-  UNBLOCK_INPUT;
+                  f->output_data.mac->normal_gc,
+                  x, y, width, height,
+                  x + shift_by, y);
 }
 
-
 /* Delete N glyphs at the nominal cursor position.  Not implemented
    for X frames.  */
 
@@ -3329,84 +3169,6 @@ x_delete_glyphs (n)
 }
 
 
-/* Erase the current text line from the nominal cursor position
-   (inclusive) to pixel column TO_X (exclusive).  The idea is that
-   everything from TO_X onward is already erased.
-
-   TO_X is a pixel position relative to updated_area of
-   updated_window.  TO_X == -1 means clear to the end of this area.  */
-
-static void
-x_clear_end_of_line (to_x)
-     int to_x;
-{
-  struct frame *f;
-  struct window *w = updated_window;
-  int max_x, min_y, max_y;
-  int from_x, from_y, to_y;
-
-  xassert (updated_window && updated_row);
-  f = XFRAME (w->frame);
-
-  if (updated_row->full_width_p)
-    {
-      max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-         && !w->pseudo_window_p)
-       max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
-    }
-  else
-    max_x = window_box_width (w, updated_area);
-  max_y = window_text_bottom_y (w);
-
-  /* TO_X == 0 means don't do anything.  TO_X < 0 means clear to end
-     of window.  For TO_X > 0, truncate to end of drawing area.  */
-  if (to_x == 0)
-    return;
-  else if (to_x < 0)
-    to_x = max_x;
-  else
-    to_x = min (to_x, max_x);
-
-  to_y = min (max_y, output_cursor.y + updated_row->height);
-
-  /* Notice if the cursor will be cleared by this operation.  */
-  if (!updated_row->full_width_p)
-    notice_overwritten_cursor (w, updated_area,
-                              output_cursor.x, -1,
-                              updated_row->y,
-                              MATRIX_ROW_BOTTOM_Y (updated_row));
-
-  from_x = output_cursor.x;
-
-  /* Translate to frame coordinates.  */
-  if (updated_row->full_width_p)
-    {
-      from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
-      to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
-    }
-  else
-    {
-      from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
-      to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
-    }
-
-  min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-  from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
-  to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
-
-  /* Prevent inadvertently clearing to end of the X window.  */
-  if (to_x > from_x && to_y > from_y)
-    {
-      BLOCK_INPUT;
-      XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 from_x, from_y, to_x - from_x, to_y - from_y,
-                 0);
-      UNBLOCK_INPUT;
-    }
-}
-
-
 /* Clear entire frame.  If updating_frame is non-null, clear that
    frame.  Otherwise clear the selected frame.  */
 
@@ -3450,6 +3212,7 @@ x_clear_frame ()
 
 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
 
+
 /* Subtract the `struct timeval' values X and Y, storing the result in
    *RESULT.  Return 1 if the difference is negative, otherwise 0.  */
 
@@ -3553,7 +3316,7 @@ XTring_bell ()
    This, and those operations, are used only within an update
    that is bounded by calls to x_update_begin and x_update_end.  */
 
-void
+static void
 XTset_terminal_window (n)
      register int n;
 {
@@ -3589,10 +3352,8 @@ x_scroll_run (w, run)
 
   /* Get frame-relative bounding box of the text display area of W,
      without mode lines.  Include in this box the left and right
-     fringes of W.  */
+     fringe of W.  */
   window_box (w, -1, &x, &y, &width, &height);
-  width += FRAME_X_FRINGE_WIDTH (f);
-  x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
@@ -3638,498 +3399,55 @@ x_scroll_run (w, run)
                           Exposure Events
  ***********************************************************************/
 
-/* Redisplay an exposed area of frame F.  X and Y are the upper-left
-   corner of the exposed rectangle.  W and H are width and height of
-   the exposed area.  All are pixel values.  W or H zero means redraw
-   the entire frame.  */
+\f
+static void
+frame_highlight (f)
+     struct frame *f;
+{
+  x_update_cursor (f, 1);
+}
 
 static void
-expose_frame (f, x, y, w, h)
+frame_unhighlight (f)
      struct frame *f;
-     int x, y, w, h;
 {
-  Rect r;
-  int mouse_face_overwritten_p = 0;
+  x_update_cursor (f, 1);
+}
+
+/* The focus has changed.  Update the frames as necessary to reflect
+   the new situation.  Note that we can't change the selected frame
+   here, because the Lisp code we are interrupting might become confused.
+   Each event gets marked with the frame in which it occurred, so the
+   Lisp code can tell when the switch took place by examining the events.  */
 
-  TRACE ((stderr, "expose_frame "));
+static void
+x_new_focus_frame (dpyinfo, frame)
+     struct x_display_info *dpyinfo;
+     struct frame *frame;
+{
+  struct frame *old_focus = dpyinfo->x_focus_frame;
 
-  /* No need to redraw if frame will be redrawn soon.  */
-  if (FRAME_GARBAGED_P (f))
+  if (frame != dpyinfo->x_focus_frame)
     {
-      TRACE ((stderr, " garbaged\n"));
-      return;
-    }
+      /* Set this before calling other routines, so that they see
+        the correct value of x_focus_frame.  */
+      dpyinfo->x_focus_frame = frame;
 
-  /* MAC_TODO: this is a kludge, but if scroll bars are not activated
-     or deactivated here, for unknown reasons, activated scroll bars
-     are shown in deactivated frames in some instances.  */
-  if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
-    activate_scroll_bars (f);
-  else
-    deactivate_scroll_bars (f);
+      if (old_focus && old_focus->auto_lower)
+       x_lower_frame (old_focus);
 
-  /* If basic faces haven't been realized yet, there is no point in
-     trying to redraw anything.  This can happen when we get an expose
-     event while Emacs is starting, e.g. by moving another window.  */
-  if (FRAME_FACE_CACHE (f) == NULL
-      || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
-    {
-      TRACE ((stderr, " no faces\n"));
-      return;
-    }
+#if 0
+      selected_frame = frame;
+      XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
+                selected_frame);
+      Fselect_window (selected_frame->selected_window, Qnil);
+      choose_minibuf_frame ();
+#endif /* ! 0 */
 
-  if (w == 0 || h == 0)
-    {
-      r.left = r.top = 0;
-      r.right = CANON_X_UNIT (f) * f->width;
-      r.bottom = CANON_Y_UNIT (f) * f->height;
-    }
-  else
-    {
-      r.left = x;
-      r.top = y;
-      r.right = x + w;
-      r.bottom = y + h;
-    }
-
-  TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
-  mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
-
-  if (WINDOWP (f->tool_bar_window))
-    mouse_face_overwritten_p
-      |= expose_window (XWINDOW (f->tool_bar_window), &r);
-
-  /* Some window managers support a focus-follows-mouse style with
-     delayed raising of frames.  Imagine a partially obscured frame,
-     and moving the mouse into partially obscured mouse-face on that
-     frame.  The visible part of the mouse-face will be highlighted,
-     then the WM raises the obscured frame.  With at least one WM, KDE
-     2.1, Emacs is not getting any event for the raising of the frame
-     (even tried with SubstructureRedirectMask), only Expose events.
-     These expose events will draw text normally, i.e. not
-     highlighted.  Which means we must redo the highlight here.
-     Subsume it under ``we love X''.  --gerd 2001-08-15  */
-  /* Included in Windows version because Windows most likely does not
-     do the right thing if any third party tool offers
-     focus-follows-mouse with delayed raise.  --jason 2001-10-12  */
-  if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
-    {
-      struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-      if (f == dpyinfo->mouse_face_mouse_frame)
-       {
-         int x = dpyinfo->mouse_face_mouse_x;
-         int y = dpyinfo->mouse_face_mouse_y;
-         clear_mouse_face (dpyinfo);
-         note_mouse_highlight (f, x, y);
-       }
-    }
-}
-
-
-/* Redraw (parts) of all windows in the window tree rooted at W that
-   intersect R.  R contains frame pixel coordinates.  */
-
-static int
-expose_window_tree (w, r)
-     struct window *w;
-     Rect *r;
-{
-  struct frame *f = XFRAME (w->frame);
-  int mouse_face_overwritten_p = 0;
-
-  while (w && !FRAME_GARBAGED_P (f))
-    {
-      if (!NILP (w->hchild))
-       mouse_face_overwritten_p
-         |= expose_window_tree (XWINDOW (w->hchild), r);
-      else if (!NILP (w->vchild))
-       mouse_face_overwritten_p
-         |= expose_window_tree (XWINDOW (w->vchild), r);
-      else
-       mouse_face_overwritten_p |= expose_window (w, r);
-
-      w = NILP (w->next) ? NULL : XWINDOW (w->next);
-    }
-
-  return mouse_face_overwritten_p;
-}
-
-
-/* Redraw the part of glyph row area AREA of glyph row ROW on window W
-   which intersects rectangle R.  R is in window-relative coordinates.  */
-
-static void
-expose_area (w, row, r, area)
-     struct window *w;
-     struct glyph_row *row;
-     Rect *r;
-     enum glyph_row_area area;
-{
-  struct glyph *first = row->glyphs[area];
-  struct glyph *end = row->glyphs[area] + row->used[area];
-  struct glyph *last;
-  int first_x, start_x, x;
-
-  if (area == TEXT_AREA && row->fill_line_p)
-    /* If row extends face to end of line write the whole line.  */
-    x_draw_glyphs (w, 0, row, area,
-                  0, row->used[area],
-                  DRAW_NORMAL_TEXT, 0);
-  else
-    {
-      /* Set START_X to the window-relative start position for drawing glyphs of
-        AREA.  The first glyph of the text area can be partially visible.
-        The first glyphs of other areas cannot.  */
-      if (area == LEFT_MARGIN_AREA)
-       start_x = 0;
-      else if (area == TEXT_AREA)
-       start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-      else
-       start_x = (window_box_width (w, LEFT_MARGIN_AREA)
-                  + window_box_width (w, TEXT_AREA));
-      x = start_x;
-
-      /* Find the first glyph that must be redrawn.  */
-      while (first < end
-             && x + first->pixel_width < r->left)
-        {
-          x += first->pixel_width;
-          ++first;
-        }
-
-      /* Find the last one.  */
-      last = first;
-      first_x = x;
-      while (last < end
-             && x < r->right)
-        {
-          x += last->pixel_width;
-          ++last;
-        }
-
-      /* Repaint.  */
-      if (last > first)
-        x_draw_glyphs (w, first_x - start_x, row, area,
-                       first - row->glyphs[area],
-                       last - row->glyphs[area],
-                       DRAW_NORMAL_TEXT, 0);
-    }
-}
-
-
-/* Redraw the parts of the glyph row ROW on window W intersecting
-   rectangle R.  R is in window-relative coordinates.  Value is
-   non-zero if mouse face was overwritten.  */
-
-static int
-expose_line (w, row, r)
-     struct window *w;
-     struct glyph_row *row;
-     Rect *r;
-{
-  xassert (row->enabled_p);
-
-  if (row->mode_line_p || w->pseudo_window_p)
-    x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
-                  DRAW_NORMAL_TEXT, 0);
-  else
-    {
-      if (row->used[LEFT_MARGIN_AREA])
-       expose_area (w, row, r, LEFT_MARGIN_AREA);
-      if (row->used[TEXT_AREA])
-       expose_area (w, row, r, TEXT_AREA);
-      if (row->used[RIGHT_MARGIN_AREA])
-       expose_area (w, row, r, RIGHT_MARGIN_AREA);
-      draw_row_fringe_bitmaps (w, row);
-    }
-
-  return row->mouse_face_p;
-}
-
-
-/* Return non-zero if W's cursor intersects rectangle R.  */
-
-static int
-x_phys_cursor_in_rect_p (w, r)
-     struct window *w;
-     Rect *r;
-{
-  Rect cr, result;
-  struct glyph *cursor_glyph;
-
-  cursor_glyph = get_phys_cursor_glyph (w);
-  if (cursor_glyph)
-    {
-      cr.left = w->phys_cursor.x;
-      cr.top = w->phys_cursor.y;
-      cr.right = cr.left + cursor_glyph->pixel_width;
-      cr.bottom = cr.top + w->phys_cursor_height;
-      return x_intersect_rectangles (&cr, r, &result);
-    }
-  else
-    return 0;
-}
-
-
-/* Redraw those parts of glyphs rows during expose event handling that
-   overlap other rows.  Redrawing of an exposed line writes over parts
-   of lines overlapping that exposed line; this function fixes that.
-
-   W is the window being exposed.  FIRST_OVERLAPPING_ROW is the first
-   row in W's current matrix that is exposed and overlaps other rows.
-   LAST_OVERLAPPING_ROW is the last such row.  */
-
-static void
-expose_overlaps (w, first_overlapping_row, last_overlapping_row)
-     struct window *w;
-     struct glyph_row *first_overlapping_row;
-     struct glyph_row *last_overlapping_row;
-{
-  struct glyph_row *row;
-
-  for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
-    if (row->overlapping_p)
-      {
-       xassert (row->enabled_p && !row->mode_line_p);
-
-       if (row->used[LEFT_MARGIN_AREA])
-         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
-
-       if (row->used[TEXT_AREA])
-         x_fix_overlapping_area (w, row, TEXT_AREA);
-
-       if (row->used[RIGHT_MARGIN_AREA])
-         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
-      }
-}
-
-
-/* Redraw the part of window W intersection rectangle FR.  Pixel
-   coordinates in FR are frame-relative.  Call this function with
-   input blocked.  Value is non-zero if the exposure overwrites
-   mouse-face.  */
-
-static int
-expose_window (w, fr)
-     struct window *w;
-     Rect *fr;
-{
-  struct frame *f = XFRAME (w->frame);
-  Rect wr, r;
-  int mouse_face_overwritten_p = 0;
-
-  /* If window is not yet fully initialized, do nothing.  This can
-     happen when toolkit scroll bars are used and a window is split.
-     Reconfiguring the scroll bar will generate an expose for a newly
-     created window.  */
-  if (w->current_matrix == NULL)
-    return 0;
-
-  /* When we're currently updating the window, display and current
-     matrix usually don't agree.  Arrange for a thorough display
-     later.  */
-  if (w == updated_window)
-    {
-      SET_FRAME_GARBAGED (f);
-      return 0;
-    }
-
-  /* Frame-relative pixel rectangle of W.  */
-  wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
-  wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
-  wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
-  wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
-
-  if (x_intersect_rectangles (fr, &wr, &r))
-    {
-      int yb = window_text_bottom_y (w);
-      struct glyph_row *row;
-      int cursor_cleared_p;
-      struct glyph_row *first_overlapping_row, *last_overlapping_row;
-
-      TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
-             r.left, r.top, r.right, r.bottom));
-
-      /* Convert to window coordinates.  */
-      r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
-      r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
-      r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
-      r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
-
-      /* Turn off the cursor.  */
-      if (!w->pseudo_window_p
-         && x_phys_cursor_in_rect_p (w, &r))
-       {
-         x_clear_cursor (w);
-         cursor_cleared_p = 1;
-       }
-      else
-       cursor_cleared_p = 0;
-
-      /* Update lines intersecting rectangle R.  */
-      first_overlapping_row = last_overlapping_row = NULL;
-      for (row = w->current_matrix->rows;
-          row->enabled_p;
-          ++row)
-       {
-         int y0 = row->y;
-         int y1 = MATRIX_ROW_BOTTOM_Y (row);
-
-         if ((y0 >= r.top && y0 < r.bottom)
-             || (y1 > r.top && y1 < r.bottom)
-             || (r.top >= y0 && r.top < y1)
-             || (r.bottom > y0 && r.bottom < y1))
-           {
-             if (row->overlapping_p)
-               {
-                 if (first_overlapping_row == NULL)
-                   first_overlapping_row = row;
-                 last_overlapping_row = row;
-               }
-
-             if (expose_line (w, row, &r))
-               mouse_face_overwritten_p = 1;
-           }
-
-         if (y1 >= yb)
-           break;
-       }
-
-      /* Display the mode line if there is one.  */
-      if (WINDOW_WANTS_MODELINE_P (w)
-         && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
-             row->enabled_p)
-         && row->y < r.bottom)
-       {
-         if (expose_line (w, row, &r))
-           mouse_face_overwritten_p = 1;
-       }
-
-      if (!w->pseudo_window_p)
-       {
-         /* Fix the display of overlapping rows.  */
-         if (first_overlapping_row)
-           expose_overlaps (w, first_overlapping_row, last_overlapping_row);
-
-         /* Draw border between windows.  */
-         x_draw_vertical_border (w);
-
-         /* Turn the cursor on again.  */
-         if (cursor_cleared_p)
-           x_update_window_cursor (w, 1);
-       }
-    }
-
-  /* Display scroll bar for this window.  */
-  if (!NILP (w->vertical_scroll_bar))
-    {
-      ControlHandle ch
-       = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
-
-      Draw1Control (ch);
-    }
-
-  return mouse_face_overwritten_p;
-}
-
-static int
-x_intersect_rectangles (r1, r2, result)
-     Rect *r1, *r2, *result;
-{
-  Rect *left, *right;
-  Rect *upper, *lower;
-  int intersection_p = 0;
-
-  /* Rerrange so that R1 is the left-most rectangle.  */
-  if (r1->left < r2->left)
-    left = r1, right = r2;
-  else
-    left = r2, right = r1;
-
-  /* X0 of the intersection is right.x0, if this is inside R1,
-     otherwise there is no intersection.  */
-  if (right->left <= left->right)
-    {
-      result->left = right->left;
-
-      /* The right end of the intersection is the minimum of the
-        the right ends of left and right.  */
-      result->right = min (left->right, right->right);
-
-      /* Same game for Y.  */
-      if (r1->top < r2->top)
-       upper = r1, lower = r2;
-      else
-       upper = r2, lower = r1;
-
-      /* The upper end of the intersection is lower.y0, if this is inside
-        of upper.  Otherwise, there is no intersection.  */
-      if (lower->top <= upper->bottom)
-       {
-         result->top = lower->top;
-
-         /* The lower end of the intersection is the minimum of the lower
-            ends of upper and lower.  */
-         result->bottom = min (lower->bottom, upper->bottom);
-         intersection_p = 1;
-       }
-    }
-
-  return intersection_p;
-}
-
-
-
-
-\f
-static void
-frame_highlight (f)
-     struct frame *f;
-{
-  x_update_cursor (f, 1);
-}
-
-static void
-frame_unhighlight (f)
-     struct frame *f;
-{
-  x_update_cursor (f, 1);
-}
-
-/* The focus has changed.  Update the frames as necessary to reflect
-   the new situation.  Note that we can't change the selected frame
-   here, because the Lisp code we are interrupting might become confused.
-   Each event gets marked with the frame in which it occurred, so the
-   Lisp code can tell when the switch took place by examining the events.  */
-
-static void
-x_new_focus_frame (dpyinfo, frame)
-     struct x_display_info *dpyinfo;
-     struct frame *frame;
-{
-  struct frame *old_focus = dpyinfo->x_focus_frame;
-
-  if (frame != dpyinfo->x_focus_frame)
-    {
-      /* Set this before calling other routines, so that they see
-        the correct value of x_focus_frame.  */
-      dpyinfo->x_focus_frame = frame;
-
-      if (old_focus && old_focus->auto_lower)
-       x_lower_frame (old_focus);
-
-#if 0
-      selected_frame = frame;
-      XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
-                selected_frame);
-      Fselect_window (selected_frame->selected_window);
-      choose_minibuf_frame ();
-#endif /* ! 0 */
-
-      if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
-       pending_autoraise_frame = dpyinfo->x_focus_frame;
-      else
-       pending_autoraise_frame = 0;
+      if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
+       pending_autoraise_frame = dpyinfo->x_focus_frame;
+      else
+       pending_autoraise_frame = 0;
     }
 
   x_frame_rehighlight (dpyinfo);
@@ -4348,1454 +3666,106 @@ x_get_keysym_name (keysym)
 
 
 \f
-/* Mouse clicks and mouse movement.  Rah.  */
-
-/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
-   co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle that the
-   glyph at X, Y occupies, if BOUNDS != 0.  If NOCLIP is non-zero, do
-   not force the value into range.  */
-
-void
-pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
-     FRAME_PTR f;
-     register int pix_x, pix_y;
-     register int *x, *y;
-     Rect *bounds;
-     int noclip;
-{
-  /* Support tty mode: if Vwindow_system is nil, behave correctly. */
-  if (NILP (Vwindow_system))
-    {
-      *x = pix_x;
-      *y = pix_y;
-      return;
-    }
-
-  /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
-     even for negative values.  */
-  if (pix_x < 0)
-    pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
-  if (pix_y < 0)
-    pix_y -= (f)->output_data.mac->line_height - 1;
-
-  pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
-  pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
-
-  if (bounds)
-    {
-      bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
-      bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
-      bounds->right  = bounds->left + FONT_WIDTH  (FRAME_FONT (f)) - 1;
-      bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
-    }
-
-  if (!noclip)
-    {
-      if (pix_x < 0)
-       pix_x = 0;
-      else if (pix_x > FRAME_WINDOW_WIDTH (f))
-       pix_x = FRAME_WINDOW_WIDTH (f);
-
-      if (pix_y < 0)
-       pix_y = 0;
-      else if (pix_y > f->height)
-       pix_y = f->height;
-    }
-
-  *x = pix_x;
-  *y = pix_y;
-}
-
-
-/* Given HPOS/VPOS in the current matrix of W, return corresponding
-   frame-relative pixel positions in *FRAME_X and *FRAME_Y.  If we
-   can't tell the positions because W's display is not up to date,
-   return 0.  */
-
-int
-glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
-     struct window *w;
-     int hpos, vpos;
-     int *frame_x, *frame_y;
-{
-  int success_p;
-
-  xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
-  xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
-
-  if (display_completed)
-    {
-      struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
-      struct glyph *glyph = row->glyphs[TEXT_AREA];
-      struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
-
-      *frame_y = row->y;
-      *frame_x = row->x;
-      while (glyph < end)
-       {
-         *frame_x += glyph->pixel_width;
-         ++glyph;
-       }
-
-      success_p = 1;
-    }
-  else
-    {
-      *frame_y = *frame_x = 0;
-      success_p = 0;
-    }
-
-  *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
-  *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
-  return success_p;
-}
-
-
-/* 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.
-
-   We have received a mouse movement event, which is given in *event.
-   If the mouse is over a different glyph than it was last time, tell
-   the mainstream emacs code by setting mouse_moved.  If not, ask for
-   another motion event, so we can check again the next time it moves.  */
-
-static Point last_mouse_motion_position;
-static Lisp_Object last_mouse_motion_frame;
-
-static void
-note_mouse_movement (frame, pos)
-     FRAME_PTR frame;
-     Point *pos;
-{
-#if TARGET_API_MAC_CARBON
-  Rect r;
-#endif
-
-  last_mouse_movement_time = TickCount () * (1000 / 60);  /* to milliseconds */
-  last_mouse_motion_position = *pos;
-  XSETFRAME (last_mouse_motion_frame, frame);
-
-#if TARGET_API_MAC_CARBON
-  if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
-#else
-  if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
-#endif
-    {
-      frame->mouse_moved = 1;
-      last_mouse_scroll_bar = Qnil;
-      note_mouse_highlight (frame, -1, -1);
-    }
-  /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (pos->h < last_mouse_glyph.left
-          || pos->h >= last_mouse_glyph.right
-          || pos->v < last_mouse_glyph.top
-          || pos->v >= last_mouse_glyph.bottom)
-    {
-      frame->mouse_moved = 1;
-      last_mouse_scroll_bar = Qnil;
-      note_mouse_highlight (frame, pos->h, pos->v);
-    }
-}
-
-/* This is used for debugging, to turn off note_mouse_highlight.  */
-
-int disable_mouse_highlight;
-
-
-\f
-/************************************************************************
-                             Mouse Face
- ************************************************************************/
-
-/* Find the glyph under window-relative coordinates X/Y in window W.
-   Consider only glyphs from buffer text, i.e. no glyphs from overlay
-   strings.  Return in *HPOS and *VPOS the row and column number of
-   the glyph found.  Return in *AREA the glyph area containing X.
-   Value is a pointer to the glyph found or null if X/Y is not on
-   text, or we can't tell because W's current matrix is not up to
-   date.  */
-
-static struct glyph *
-x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
-     struct window *w;
-     int x, y;
-     int *hpos, *vpos, *area;
-     int buffer_only_p;
-{
-  struct glyph *glyph, *end;
-  struct glyph_row *row = NULL;
-  int x0, i, left_area_width;
-
-  /* Find row containing Y.  Give up if some row is not enabled.  */
-  for (i = 0; i < w->current_matrix->nrows; ++i)
-    {
-      row = MATRIX_ROW (w->current_matrix, i);
-      if (!row->enabled_p)
-       return NULL;
-      if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
-       break;
-    }
-
-  *vpos = i;
-  *hpos = 0;
-
-  /* Give up if Y is not in the window.  */
-  if (i == w->current_matrix->nrows)
-    return NULL;
-
-  /* Get the glyph area containing X.  */
-  if (w->pseudo_window_p)
-    {
-      *area = TEXT_AREA;
-      x0 = 0;
-    }
-  else
-    {
-      left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
-      if (x < left_area_width)
-       {
-         *area = LEFT_MARGIN_AREA;
-         x0 = 0;
-       }
-      else if (x < left_area_width + window_box_width (w, TEXT_AREA))
-       {
-         *area = TEXT_AREA;
-         x0 = row->x + left_area_width;
-       }
-      else
-       {
-         *area = RIGHT_MARGIN_AREA;
-         x0 = left_area_width + window_box_width (w, TEXT_AREA);
-       }
-    }
-
-  /* Find glyph containing X.  */
-  glyph = row->glyphs[*area];
-  end = glyph + row->used[*area];
-  while (glyph < end)
-    {
-      if (x < x0 + glyph->pixel_width)
-       {
-         if (w->pseudo_window_p)
-           break;
-         else if (!buffer_only_p || BUFFERP (glyph->object))
-           break;
-       }
-
-      x0 += glyph->pixel_width;
-      ++glyph;
-    }
-
-  if (glyph == end)
-    return NULL;
-
-  *hpos = glyph - row->glyphs[*area];
-  return glyph;
-}
-
-
-/* Convert frame-relative x/y to coordinates relative to window W.
-   Takes pseudo-windows into account.  */
-
-static void
-frame_to_window_pixel_xy (w, x, y)
-     struct window *w;
-     int *x, *y;
-{
-  if (w->pseudo_window_p)
-    {
-      /* A pseudo-window is always full-width, and starts at the
-        left edge of the frame, plus a frame border.  */
-      struct frame *f = XFRAME (w->frame);
-      *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
-      *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
-    }
-  else
-    {
-      *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
-      *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
-    }
-}
-
-
-/* Take proper action when mouse has moved to the mode or header line of
-   window W, x-position X.  MODE_LINE_P non-zero means mouse is on the
-   mode line.  X is relative to the start of the text display area of
-   W, so the width of fringes and scroll bars must be subtracted
-   to get a position relative to the start of the mode line.  */
-
-static void
-note_mode_line_highlight (w, x, mode_line_p)
-     struct window *w;
-     int x, mode_line_p;
-{
-  struct frame *f = XFRAME (w->frame);
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-  struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
-  struct glyph_row *row;
-
-  if (mode_line_p)
-    row = MATRIX_MODE_LINE_ROW (w->current_matrix);
-  else
-    row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
-
-  if (row->enabled_p)
-    {
-      struct glyph *glyph, *end;
-      Lisp_Object help, map;
-      int x0;
-
-      /* Find the glyph under X.  */
-      glyph = row->glyphs[TEXT_AREA];
-      end = glyph + row->used[TEXT_AREA];
-      x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
-             + FRAME_X_LEFT_FRINGE_WIDTH (f));
-
-      while (glyph < end
-            && x >= x0 + glyph->pixel_width)
-       {
-         x0 += glyph->pixel_width;
-         ++glyph;
-       }
-
-      if (glyph < end
-         && STRINGP (glyph->object)
-         && STRING_INTERVALS (glyph->object)
-         && glyph->charpos >= 0
-         && glyph->charpos < SCHARS (glyph->object))
-       {
-         /* If we're on a string with `help-echo' text property,
-            arrange for the help to be displayed.  This is done by
-            setting the global variable help_echo to the help string.  */
-         help = Fget_text_property (make_number (glyph->charpos),
-                                    Qhelp_echo, glyph->object);
-         if (!NILP (help))
-            {
-              help_echo = help;
-              XSETWINDOW (help_echo_window, w);
-              help_echo_object = glyph->object;
-              help_echo_pos = glyph->charpos;
-            }
-
-         /* Change the mouse pointer according to what is under X/Y.  */
-         map = Fget_text_property (make_number (glyph->charpos),
-                                   Qlocal_map, glyph->object);
-         if (KEYMAPP (map))
-           cursor = f->output_data.mac->nontext_cursor;
-         else
-           {
-             map = Fget_text_property (make_number (glyph->charpos),
-                                       Qkeymap, glyph->object);
-             if (KEYMAPP (map))
-               cursor = f->output_data.mac->nontext_cursor;
-           }
-       }
-    }
-
-#if 0 /* MAC_TODO: mouse cursor */
-  XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
-#endif
-}
-
-
-/* Take proper action when the mouse has moved to position X, Y on
-   frame F as regards highlighting characters that have mouse-face
-   properties.  Also de-highlighting chars where the mouse was before.
-   X and Y can be negative or out of range.  */
-
-static void
-note_mouse_highlight (f, x, y)
-     struct frame *f;
-     int x, y;
-{
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-  int portion;
-  Lisp_Object window;
-  struct window *w;
-  struct buffer *b;
-
-#if 0
-  /* When a menu is active, don't highlight because this looks odd. */
-  if (popup_activated ())
-    return;
-#endif
-
-  if (NILP (Vmouse_highlight)
-      || !f->glyphs_initialized_p)
-    return;
-
-  dpyinfo->mouse_face_mouse_x = x;
-  dpyinfo->mouse_face_mouse_y = y;
-  dpyinfo->mouse_face_mouse_frame = f;
-
-  if (dpyinfo->mouse_face_defer)
-    return;
-
-  if (gc_in_progress)
-    {
-      dpyinfo->mouse_face_deferred_gc = 1;
-      return;
-    }
-
-  /* Which window is that in?  */
-  window = window_from_coordinates (f, x, y, &portion, 1);
-
-  /* If we were displaying active text in another window, clear that.  */
-  if (! EQ (window, dpyinfo->mouse_face_window))
-    clear_mouse_face (dpyinfo);
-
-  /* Not on a window -> return.  */
-  if (!WINDOWP (window))
-    return;
-
-  /* Reset help_echo. It will get recomputed below.  */
-  help_echo = Qnil;
-
-  /* Convert to window-relative pixel coordinates.  */
-  w = XWINDOW (window);
-  frame_to_window_pixel_xy (w, &x, &y);
-
-  /* Handle tool-bar window differently since it doesn't display a
-     buffer.  */
-  if (EQ (window, f->tool_bar_window))
-    {
-      note_tool_bar_highlight (f, x, y);
-      return;
-    }
-
-  /* Mouse is on the mode or header line?  */
-  if (portion == 1 || portion == 3)
-    {
-      note_mode_line_highlight (w, x, portion == 1);
-      return;
-    }
-#if 0 /* TODO: mouse cursor */
-  if (portion == 2)
-    cursor = f->output_data.x->horizontal_drag_cursor;
-  else
-    cursor = f->output_data.x->text_cursor;
-#endif
-  /* Are we in a window whose display is up to date?
-     And verify the buffer's text has not changed.  */
-  b = XBUFFER (w->buffer);
-  if (/* Within text portion of the window.  */
-      portion == 0
-      && EQ (w->window_end_valid, w->buffer)
-      && XFASTINT (w->last_modified) == BUF_MODIFF (b)
-      && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
-    {
-      int hpos, vpos, pos, i, area;
-      struct glyph *glyph;
-      Lisp_Object object;
-      Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
-      Lisp_Object *overlay_vec = NULL;
-      int len, noverlays;
-      struct buffer *obuf;
-      int obegv, ozv, same_region;
-
-      /* Find the glyph under X/Y.  */
-      glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
-
-      /* Clear mouse face if X/Y not over text.  */
-      if (glyph == NULL
-         || area != TEXT_AREA
-         || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
-       {
-         clear_mouse_face (dpyinfo);
-         /* TODO: mouse cursor */
-         goto set_cursor;
-       }
-
-      pos = glyph->charpos;
-      object = glyph->object;
-      if (!STRINGP (object) && !BUFFERP (object))
-       goto set_cursor;
-
-      /* If we get an out-of-range value, return now; avoid an error.  */
-      if (BUFFERP (object) && pos > BUF_Z (b))
-       goto set_cursor;
-
-      /* Make the window's buffer temporarily current for
-        overlays_at and compute_char_face.  */
-      obuf = current_buffer;
-      current_buffer = b;
-      obegv = BEGV;
-      ozv = ZV;
-      BEGV = BEG;
-      ZV = Z;
-
-      /* Is this char mouse-active or does it have help-echo?  */
-      position = make_number (pos);
-
-      if (BUFFERP (object))
-       {
-         /* Put all the overlays we want in a vector in overlay_vec.
-            Store the length in len.  If there are more than 10, make
-            enough space for all, and try again.  */
-         len = 10;
-         overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-         noverlays =  overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
-         if (noverlays > len)
-           {
-             len = noverlays;
-             overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-             noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
-           }
-
-         /* Sort overlays into increasing priority order.  */
-         noverlays = sort_overlays (overlay_vec, noverlays, w);
-       }
-      else
-       noverlays = 0;
-
-      same_region = (EQ (window, dpyinfo->mouse_face_window)
-                    && vpos >= dpyinfo->mouse_face_beg_row
-                    && vpos <= dpyinfo->mouse_face_end_row
-                    && (vpos > dpyinfo->mouse_face_beg_row
-                        || hpos >= dpyinfo->mouse_face_beg_col)
-                    && (vpos < dpyinfo->mouse_face_end_row
-                        || hpos < dpyinfo->mouse_face_end_col
-                        || dpyinfo->mouse_face_past_end));
-
-      /* TODO: if (same_region)
-        mouse cursor */
-
-      /* Check mouse-face highlighting.  */
-      if (! same_region
-         /* If there exists an overlay with mouse-face overlapping
-            the one we are currently highlighting, we have to
-            check if we enter the overlapping overlay, and then
-            highlight that.  */
-         || (OVERLAYP (dpyinfo->mouse_face_overlay)
-             && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
-       {
-         /* Find the highest priority overlay that has a mouse-face
-            property.  */
-         overlay = Qnil;
-         for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
-           {
-             mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
-             if (!NILP (mouse_face))
-               overlay = overlay_vec[i];
-           }
-
-         /* If we're actually highlighting the same overlay as
-            before, there's no need to do that again.  */
-         if (!NILP (overlay)
-             && EQ (overlay, dpyinfo->mouse_face_overlay))
-           goto check_help_echo;
-
-         dpyinfo->mouse_face_overlay = overlay;
-
-         /* Clear the display of the old active region, if any.  */
-         clear_mouse_face (dpyinfo);
-         /* TODO: mouse cursor changes.  */
-
-         /* If no overlay applies, get a text property.  */
-         if (NILP (overlay))
-           mouse_face = Fget_text_property (position, Qmouse_face, object);
-
-         /* Handle the overlay case.  */
-         if (!NILP (overlay))
-           {
-             /* Find the range of text around this char that
-                should be active.  */
-             Lisp_Object before, after;
-             int ignore;
-
-             before = Foverlay_start (overlay);
-             after = Foverlay_end (overlay);
-             /* Record this as the current active region.  */
-             fast_find_position (w, XFASTINT (before),
-                                 &dpyinfo->mouse_face_beg_col,
-                                 &dpyinfo->mouse_face_beg_row,
-                                 &dpyinfo->mouse_face_beg_x,
-                                 &dpyinfo->mouse_face_beg_y, Qnil);
-
-             dpyinfo->mouse_face_past_end
-               = !fast_find_position (w, XFASTINT (after),
-                                      &dpyinfo->mouse_face_end_col,
-                                      &dpyinfo->mouse_face_end_row,
-                                      &dpyinfo->mouse_face_end_x,
-                                      &dpyinfo->mouse_face_end_y, Qnil);
-             dpyinfo->mouse_face_window = window;
-
-             dpyinfo->mouse_face_face_id
-               = face_at_buffer_position (w, pos, 0, 0,
-                                          &ignore, pos + 1,
-                                          !dpyinfo->mouse_face_hidden);
-
-             /* Display it as active.  */
-             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             /* TODO: mouse cursor changes.  */
-           }
-         /* Handle the text property case.  */
-         else if (! NILP (mouse_face) && BUFFERP (object))
-           {
-             /* Find the range of text around this char that
-                should be active.  */
-             Lisp_Object before, after, beginning, end;
-             int ignore;
-
-             beginning = Fmarker_position (w->start);
-             end = make_number (BUF_Z (XBUFFER (object))
-                                - XFASTINT (w->window_end_pos));
-             before
-               = Fprevious_single_property_change (make_number (pos + 1),
-                                                   Qmouse_face,
-                                                   object, beginning);
-             after
-               = Fnext_single_property_change (position, Qmouse_face,
-                                               object, end);
-
-             /* Record this as the current active region.  */
-             fast_find_position (w, XFASTINT (before),
-                                 &dpyinfo->mouse_face_beg_col,
-                                 &dpyinfo->mouse_face_beg_row,
-                                 &dpyinfo->mouse_face_beg_x,
-                                 &dpyinfo->mouse_face_beg_y, Qnil);
-             dpyinfo->mouse_face_past_end
-               = !fast_find_position (w, XFASTINT (after),
-                                      &dpyinfo->mouse_face_end_col,
-                                      &dpyinfo->mouse_face_end_row,
-                                      &dpyinfo->mouse_face_end_x,
-                                      &dpyinfo->mouse_face_end_y, Qnil);
-             dpyinfo->mouse_face_window = window;
-
-             if (BUFFERP (object))
-               dpyinfo->mouse_face_face_id
-                 = face_at_buffer_position (w, pos, 0, 0,
-                                            &ignore, pos + 1,
-                                            !dpyinfo->mouse_face_hidden);
-
-             /* Display it as active.  */
-             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             /* TODO: mouse cursor changes.  */
-           }
-         else if (!NILP (mouse_face) && STRINGP (object))
-           {
-             Lisp_Object b, e;
-             int ignore;
-
-             b = Fprevious_single_property_change (make_number (pos + 1),
-                                                   Qmouse_face,
-                                                   object, Qnil);
-             e = Fnext_single_property_change (position, Qmouse_face,
-                                               object, Qnil);
-             if (NILP (b))
-               b = make_number (0);
-             if (NILP (e))
-               e = make_number (SCHARS (object) - 1);
-             fast_find_string_pos (w, XINT (b), object,
-                                   &dpyinfo->mouse_face_beg_col,
-                                   &dpyinfo->mouse_face_beg_row,
-                                   &dpyinfo->mouse_face_beg_x,
-                                   &dpyinfo->mouse_face_beg_y, 0);
-             fast_find_string_pos (w, XINT (e), object,
-                                   &dpyinfo->mouse_face_end_col,
-                                   &dpyinfo->mouse_face_end_row,
-                                   &dpyinfo->mouse_face_end_x,
-                                   &dpyinfo->mouse_face_end_y, 1);
-             dpyinfo->mouse_face_past_end = 0;
-             dpyinfo->mouse_face_window = window;
-             dpyinfo->mouse_face_face_id
-               = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
-                                          glyph->face_id, 1);
-             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             /* TODO: mouse cursor changes.  */
-           }
-         else if (STRINGP (object) && NILP (mouse_face))
-           {
-             /* A string which doesn't have mouse-face, but
-                the text ``under'' it might have.  */
-             struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
-             int start = MATRIX_ROW_START_CHARPOS (r);
-
-             pos = string_buffer_position (w, object, start);
-             if (pos > 0)
-               mouse_face = get_char_property_and_overlay (make_number (pos),
-                                                           Qmouse_face,
-                                                           w->buffer,
-                                                           &overlay);
-             if (!NILP (mouse_face) && !NILP (overlay))
-               {
-                 Lisp_Object before = Foverlay_start (overlay);
-                 Lisp_Object after = Foverlay_end (overlay);
-                 int ignore;
-
-                 /* Note that we might not be able to find position
-                    BEFORE in the glyph matrix if the overlay is
-                    entirely covered by a `display' property.  In
-                    this case, we overshoot.  So let's stop in
-                    the glyph matrix before glyphs for OBJECT.  */
-                 fast_find_position (w, XFASTINT (before),
-                                     &dpyinfo->mouse_face_beg_col,
-                                     &dpyinfo->mouse_face_beg_row,
-                                     &dpyinfo->mouse_face_beg_x,
-                                     &dpyinfo->mouse_face_beg_y,
-                                     object);
-
-                 dpyinfo->mouse_face_past_end
-                   = !fast_find_position (w, XFASTINT (after),
-                                          &dpyinfo->mouse_face_end_col,
-                                          &dpyinfo->mouse_face_end_row,
-                                          &dpyinfo->mouse_face_end_x,
-                                          &dpyinfo->mouse_face_end_y,
-                                          Qnil);
-                 dpyinfo->mouse_face_window = window;
-                 dpyinfo->mouse_face_face_id
-                   = face_at_buffer_position (w, pos, 0, 0,
-                                              &ignore, pos + 1,
-                                              !dpyinfo->mouse_face_hidden);
-
-                 /* Display it as active.  */
-                 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-                 /* TODO: mouse cursor changes.  */
-               }
-           }
-       }
-
-    check_help_echo:
-
-      /* Look for a `help-echo' property.  */
-      {
-       Lisp_Object help, overlay;
-
-       /* Check overlays first.  */
-       help = overlay = Qnil;
-       for (i = noverlays - 1; i >= 0 && NILP (help); --i)
-         {
-           overlay = overlay_vec[i];
-           help = Foverlay_get (overlay, Qhelp_echo);
-         }
-
-       if (!NILP (help))
-         {
-           help_echo = help;
-           help_echo_window = window;
-           help_echo_object = overlay;
-           help_echo_pos = pos;
-         }
-       else
-         {
-           Lisp_Object object = glyph->object;
-           int charpos = glyph->charpos;
-
-           /* Try text properties.  */
-           if (STRINGP (object)
-               && charpos >= 0
-               && charpos < SCHARS (object))
-             {
-               help = Fget_text_property (make_number (charpos),
-                                          Qhelp_echo, object);
-               if (NILP (help))
-                 {
-                   /* If the string itself doesn't specify a help-echo,
-                      see if the buffer text ``under'' it does.  */
-                   struct glyph_row *r
-                     = MATRIX_ROW (w->current_matrix, vpos);
-                   int start = MATRIX_ROW_START_CHARPOS (r);
-                   int pos = string_buffer_position (w, object, start);
-                   if (pos > 0)
-                     {
-                       help = Fget_char_property (make_number (pos),
-                                                  Qhelp_echo, w->buffer);
-                       if (!NILP (help))
-                         {
-                           charpos = pos;
-                           object = w->buffer;
-                         }
-                     }
-                 }
-             }
-           else if (BUFFERP (object)
-                    && charpos >= BEGV
-                    && charpos < ZV)
-             help = Fget_text_property (make_number (charpos), Qhelp_echo,
-                                        object);
-
-           if (!NILP (help))
-             {
-               help_echo = help;
-               help_echo_window = window;
-               help_echo_object = object;
-               help_echo_pos = charpos;
-             }
-         }
-      }
-
-      BEGV = obegv;
-      ZV = ozv;
-      current_buffer = obuf;
-    }
-
- set_cursor:
-  /* TODO: mouse cursor changes. */
-  ;
-}
-
-static void
-redo_mouse_highlight ()
-{
-  if (!NILP (last_mouse_motion_frame)
-      && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
-    note_mouse_highlight (XFRAME (last_mouse_motion_frame),
-                         last_mouse_motion_position.h,
-                         last_mouse_motion_position.v);
-}
-
-
-\f
-/***********************************************************************
-                              Tool-bars
- ***********************************************************************/
-
-static int x_tool_bar_item P_ ((struct frame *, int, int,
-                               struct glyph **, int *, int *, int *));
-
-/* Tool-bar item index of the item on which a mouse button was pressed
-   or -1.  */
-
-static int last_tool_bar_item;
-
-
-/* Get information about the tool-bar item at position X/Y on frame F.
-   Return in *GLYPH a pointer to the glyph of the tool-bar item in
-   the current matrix of the tool-bar window of F, or NULL if not
-   on a tool-bar item.  Return in *PROP_IDX the index of the tool-bar
-   item in F->current_tool_bar_items.  Value is
-
-   -1  if X/Y is not on a tool-bar item
-   0   if X/Y is on the same item that was highlighted before.
-   1   otherwise.  */
-
-static int
-x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
-     struct frame *f;
-     int x, y;
-     struct glyph **glyph;
-     int *hpos, *vpos, *prop_idx;
-{
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-  struct window *w = XWINDOW (f->tool_bar_window);
-  int area;
-
-  /* Find the glyph under X/Y.  */
-  *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
-  if (*glyph == NULL)
-    return -1;
-
-  /* Get the start of this tool-bar item's properties in
-     f->current_tool_bar_items.  */
-  if (!tool_bar_item_info (f, *glyph, prop_idx))
-    return -1;
-
-  /* Is mouse on the highlighted item?  */
-  if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
-      && *vpos >= dpyinfo->mouse_face_beg_row
-      && *vpos <= dpyinfo->mouse_face_end_row
-      && (*vpos > dpyinfo->mouse_face_beg_row
-         || *hpos >= dpyinfo->mouse_face_beg_col)
-      && (*vpos < dpyinfo->mouse_face_end_row
-         || *hpos < dpyinfo->mouse_face_end_col
-         || dpyinfo->mouse_face_past_end))
-    return 0;
-
-  return 1;
-}
-
-
-/* Handle mouse button event on the tool-bar of frame F, at
-   frame-relative coordinates X/Y.  EVENT_TYPE is either ButtionPress
-   or ButtonRelase.  */
-
-static void
-x_handle_tool_bar_click (f, button_event)
-     struct frame *f;
-     EventRecord *button_event;
-{
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-  struct window *w = XWINDOW (f->tool_bar_window);
-  int hpos, vpos, prop_idx;
-  struct glyph *glyph;
-  Lisp_Object enabled_p;
-  int x = button_event->where.h;
-  int y = button_event->where.v;
-
-  /* If not on the highlighted tool-bar item, return.  */
-  frame_to_window_pixel_xy (w, &x, &y);
-  if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
-    return;
-
-  /* If item is disabled, do nothing.  */
-  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
-  if (NILP (enabled_p))
-    return;
-
-  if (button_event->what == mouseDown)
-    {
-      /* Show item in pressed state.  */
-      show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
-      dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
-      last_tool_bar_item = prop_idx;
-    }
-  else
-    {
-      Lisp_Object key, frame;
-      struct input_event event;
-
-      /* Show item in released state.  */
-      show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
-      dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
-
-      key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
-
-      XSETFRAME (frame, f);
-      event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = frame;
-      event.arg = frame;
-      kbd_buffer_store_event (&event);
-
-      event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = frame;
-      event.arg = key;
-      event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                                 button_event->modifiers);
-      kbd_buffer_store_event (&event);
-      last_tool_bar_item = -1;
-    }
-}
-
-
-/* Possibly highlight a tool-bar item on frame F when mouse moves to
-   tool-bar window-relative coordinates X/Y.  Called from
-   note_mouse_highlight.  */
-
-static void
-note_tool_bar_highlight (f, x, y)
-     struct frame *f;
-     int x, y;
-{
-  Lisp_Object window = f->tool_bar_window;
-  struct window *w = XWINDOW (window);
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-  int hpos, vpos;
-  struct glyph *glyph;
-  struct glyph_row *row;
-  int i;
-  Lisp_Object enabled_p;
-  int prop_idx;
-  enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
-  int mouse_down_p, rc;
-
-  /* Function note_mouse_highlight is called with negative x(y
-     values when mouse moves outside of the frame.  */
-  if (x <= 0 || y <= 0)
-    {
-      clear_mouse_face (dpyinfo);
-      return;
-    }
-
-  rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
-  if (rc < 0)
-    {
-      /* Not on tool-bar item.  */
-      clear_mouse_face (dpyinfo);
-      return;
-    }
-  else if (rc == 0)
-    /* On same tool-bar item as before.  */
-    goto set_help_echo;
-
-  clear_mouse_face (dpyinfo);
-
-  /* Mouse is down, but on different tool-bar item?  */
-  mouse_down_p = (dpyinfo->grabbed
-                 && f == last_mouse_frame
-                 && FRAME_LIVE_P (f));
-  if (mouse_down_p
-      && last_tool_bar_item != prop_idx)
-    return;
-
-  dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
-  draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
-
-  /* If tool-bar item is not enabled, don't highlight it.  */
-  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
-  if (!NILP (enabled_p))
-    {
-      /* Compute the x-position of the glyph.  In front and past the
-        image is a space.  We include this is the highlighted area.  */
-      row = MATRIX_ROW (w->current_matrix, vpos);
-      for (i = x = 0; i < hpos; ++i)
-       x += row->glyphs[TEXT_AREA][i].pixel_width;
-
-      /* Record this as the current active region.  */
-      dpyinfo->mouse_face_beg_col = hpos;
-      dpyinfo->mouse_face_beg_row = vpos;
-      dpyinfo->mouse_face_beg_x = x;
-      dpyinfo->mouse_face_beg_y = row->y;
-      dpyinfo->mouse_face_past_end = 0;
-
-      dpyinfo->mouse_face_end_col = hpos + 1;
-      dpyinfo->mouse_face_end_row = vpos;
-      dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
-      dpyinfo->mouse_face_end_y = row->y;
-      dpyinfo->mouse_face_window = window;
-      dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
-
-      /* Display it as active.  */
-      show_mouse_face (dpyinfo, draw);
-      dpyinfo->mouse_face_image_state = draw;
-    }
-
- set_help_echo:
-
-  /* Set help_echo to a help string.to display for this tool-bar item.
-     XTread_socket does the rest.  */
-  help_echo_object = help_echo_window = Qnil;
-  help_echo_pos = -1;
-  help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
-  if (NILP (help_echo))
-    help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
-}
-
-
-\f
-/* Find the glyph matrix position of buffer position CHARPOS in window
-   *W.  HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
-   current glyphs must be up to date.  If CHARPOS is above window
-   start return (0, 0, 0, 0).  If CHARPOS is after end of W, return end
-   of last line in W.  In the row containing CHARPOS, stop before glyphs
-   having STOP as object.  */
-
-#if 0 /* This is a version of fast_find_position that's more correct
-        in the presence of hscrolling, for example.  I didn't install
-        it right away because the problem fixed is minor, it failed
-        in 20.x as well, and I think it's too risky to install
-        so near the release of 21.1.  2001-09-25 gerd.  */
-
-static int
-fast_find_position (w, charpos, hpos, vpos, x, y, stop)
-     struct window *w;
-     int charpos;
-     int *hpos, *vpos, *x, *y;
-     Lisp_Object stop;
-{
-  struct glyph_row *row, *first;
-  struct glyph *glyph, *end;
-  int i, past_end = 0;
-
-  first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  row = row_containing_pos (w, charpos, first, NULL, 0);
-  if (row == NULL)
-    {
-      if (charpos < MATRIX_ROW_START_CHARPOS (first))
-       {
-         *x = *y = *hpos = *vpos = 0;
-         return 0;
-       }
-      else
-       {
-         row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
-         past_end = 1;
-       }
-    }
-
-  *x = row->x;
-  *y = row->y;
-  *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
-
-  glyph = row->glyphs[TEXT_AREA];
-  end = glyph + row->used[TEXT_AREA];
-
-  /* Skip over glyphs not having an object at the start of the row.
-     These are special glyphs like truncation marks on terminal
-     frames.  */
-  if (row->displays_text_p)
-    while (glyph < end
-          && INTEGERP (glyph->object)
-          && !EQ (stop, glyph->object)
-          && glyph->charpos < 0)
-      {
-       *x += glyph->pixel_width;
-       ++glyph;
-      }
-
-  while (glyph < end
-        && !INTEGERP (glyph->object)
-        && !EQ (stop, glyph->object)
-        && (!BUFFERP (glyph->object)
-            || glyph->charpos < charpos))
-    {
-      *x += glyph->pixel_width;
-      ++glyph;
-    }
-
-  *hpos = glyph - row->glyphs[TEXT_AREA];
-  return past_end;
-}
-
-#else /* not 0 */
-
-static int
-fast_find_position (w, pos, hpos, vpos, x, y, stop)
-     struct window *w;
-     int pos;
-     int *hpos, *vpos, *x, *y;
-     Lisp_Object stop;
-{
-  int i;
-  int lastcol;
-  int maybe_next_line_p = 0;
-  int line_start_position;
-  int yb = window_text_bottom_y (w);
-  struct glyph_row *row, *best_row;
-  int row_vpos, best_row_vpos;
-  int current_x;
-
-  row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
-
-  while (row->y < yb)
-    {
-      if (row->used[TEXT_AREA])
-       line_start_position = row->glyphs[TEXT_AREA]->charpos;
-      else
-       line_start_position = 0;
-
-      if (line_start_position > pos)
-       break;
-      /* If the position sought is the end of the buffer,
-        don't include the blank lines at the bottom of the window.  */
-      else if (line_start_position == pos
-               && pos == BUF_ZV (XBUFFER (w->buffer)))
-       {
-         maybe_next_line_p = 1;
-         break;
-       }
-      else if (line_start_position > 0)
-        {
-          best_row = row;
-          best_row_vpos = row_vpos;
-        }
-
-      if (row->y + row->height >= yb)
-        break;
-
-      ++row;
-      ++row_vpos;
-    }
-
-  /* Find the right column within BEST_ROW.  */
-  lastcol = 0;
-  current_x = best_row->x;
-  for (i = 0; i < best_row->used[TEXT_AREA]; i++)
-    {
-      struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
-      int charpos = glyph->charpos;
-
-      if (BUFFERP (glyph->object))
-       {
-         if (charpos == pos)
-           {
-             *hpos = i;
-             *vpos = best_row_vpos;
-             *x = current_x;
-             *y = best_row->y;
-             return 1;
-           }
-         else if (charpos > pos)
-           break;
-       }
-      else if (EQ (glyph->object, stop))
-       break;
-
-      if (charpos > 0)
-       lastcol = i;
-      current_x += glyph->pixel_width;
-    }
-
-  /* If we're looking for the end of the buffer,
-     and we didn't find it in the line we scanned,
-     use the start of the following line.  */
-  if (maybe_next_line_p)
-    {
-      ++best_row;
-      ++best_row_vpos;
-      lastcol = 0;
-      current_x = best_row->x;
-    }
-
-  *vpos = best_row_vpos;
-  *hpos = lastcol + 1;
-  *x = current_x;
-  *y = best_row->y;
-  return 0;
-}
-
-#endif /* not 0 */
-
-
-/* Find the position of the glyph for position POS in OBJECT in
-   window W's current matrix, and return in *X/*Y the pixel
-   coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
-
-   RIGHT_P non-zero means return the position of the right edge of the
-   glyph, RIGHT_P zero means return the left edge position.
-
-   If no glyph for POS exists in the matrix, return the position of
-   the glyph with the next smaller position that is in the matrix, if
-   RIGHT_P is zero.  If RIGHT_P is non-zero, and no glyph for POS
-   exists in the matrix, return the position of the glyph with the
-   next larger position in OBJECT.
-
-   Value is non-zero if a glyph was found.  */
-
-static int
-fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
-     struct window *w;
-     int pos;
-     Lisp_Object object;
-     int *hpos, *vpos, *x, *y;
-     int right_p;
-{
-  int yb = window_text_bottom_y (w);
-  struct glyph_row *r;
-  struct glyph *best_glyph = NULL;
-  struct glyph_row *best_row = NULL;
-  int best_x = 0;
-
-  for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-       r->enabled_p && r->y < yb;
-       ++r)
-    {
-      struct glyph *g = r->glyphs[TEXT_AREA];
-      struct glyph *e = g + r->used[TEXT_AREA];
-      int gx;
-
-      for (gx = r->x; g < e; gx += g->pixel_width, ++g)
-       if (EQ (g->object, object))
-         {
-           if (g->charpos == pos)
-             {
-               best_glyph = g;
-               best_x = gx;
-               best_row = r;
-               goto found;
-             }
-           else if (best_glyph == NULL
-                    || ((abs (g->charpos - pos)
-                        < abs (best_glyph->charpos - pos))
-                        && (right_p
-                            ? g->charpos < pos
-                            : g->charpos > pos)))
-             {
-               best_glyph = g;
-               best_x = gx;
-               best_row = r;
-             }
-         }
-    }
-
- found:
-
-  if (best_glyph)
-    {
-      *x = best_x;
-      *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
-
-      if (right_p)
-       {
-         *x += best_glyph->pixel_width;
-         ++*hpos;
-       }
-
-      *y = best_row->y;
-      *vpos = best_row - w->current_matrix->rows;
-    }
-
-  return best_glyph != NULL;
-}
-
-
-/* Display the active region described by mouse_face_*
-   in its mouse-face if HL > 0, in its normal face if HL = 0.  */
-
-static void
-show_mouse_face (dpyinfo, draw)
-     struct mac_display_info *dpyinfo;
-     enum draw_glyphs_face draw;
-{
-  struct window *w = XWINDOW (dpyinfo->mouse_face_window);
-  struct frame *f = XFRAME (WINDOW_FRAME (w));
-
-  if (/* If window is in the process of being destroyed, don't bother
-        to do anything.  */
-      w->current_matrix != NULL
-      /* Don't update mouse highlight if hidden */
-      && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
-      /* Recognize when we are called to operate on rows that don't exist
-        anymore.  This can happen when a window is split.  */
-      && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
-    {
-      int phys_cursor_on_p = w->phys_cursor_on_p;
-      struct glyph_row *row, *first, *last;
-
-      first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
-      last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
-
-      for (row = first; row <= last && row->enabled_p; ++row)
-       {
-         int start_hpos, end_hpos, start_x;
-
-         /* For all but the first row, the highlight starts at column 0.  */
-         if (row == first)
-           {
-             start_hpos = dpyinfo->mouse_face_beg_col;
-             start_x = dpyinfo->mouse_face_beg_x;
-           }
-         else
-           {
-             start_hpos = 0;
-             start_x = 0;
-           }
-
-         if (row == last)
-           end_hpos = dpyinfo->mouse_face_end_col;
-         else
-           end_hpos = row->used[TEXT_AREA];
-
-         if (end_hpos > start_hpos)
-           {
-             x_draw_glyphs (w, start_x, row, TEXT_AREA,
-                            start_hpos, end_hpos, draw, 0);
-
-             row->mouse_face_p
-               = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
-           }
-       }
-
-      /* When we've written over the cursor, arrange for it to
-        be displayed again.  */
-      if (phys_cursor_on_p && !w->phys_cursor_on_p)
-       x_display_cursor (w, 1,
-                         w->phys_cursor.hpos, w->phys_cursor.vpos,
-                         w->phys_cursor.x, w->phys_cursor.y);
-    }
-
-#if 0 /* MAC_TODO: mouse cursor */
-  /* Change the mouse cursor.  */
-  if (draw == DRAW_NORMAL_TEXT)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->text_cursor);
-  else if (draw == DRAW_MOUSE_FACE)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->cross_cursor);
-  else
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->nontext_cursor);
-#endif
-}
+/* Mouse clicks and mouse movement.  Rah.  */
 
-/* Clear out the mouse-highlighted active region.
-   Redraw it un-highlighted first.  */
+/* Prepare a mouse-event in *RESULT for placement in the input queue.
 
-static int
-clear_mouse_face (dpyinfo)
-     struct mac_display_info *dpyinfo;
+   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;
 {
-  int cleared = 0;
+  Point mouseLoc;
 
-  if (! NILP (dpyinfo->mouse_face_window))
-    {
-      show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
-      cleared = 1;
-    }
+  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;
 
-  dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
-  dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
-  dpyinfo->mouse_face_window = Qnil;
-  dpyinfo->mouse_face_overlay = Qnil;
-  return cleared;
-}
+  mouseLoc = event->where;
 
+  SetPortWindowPort (FRAME_MAC_WINDOW (f));
 
-/* Clear any mouse-face on window W.  This function is part of the
-   redisplay interface, and is called from try_window_id and similar
-   functions to ensure the mouse-highlight is off.  */
+  GlobalToLocal (&mouseLoc);
+  XSETINT (result->x, mouseLoc.h);
+  XSETINT (result->y, mouseLoc.v);
 
-static void
-x_clear_mouse_face (w)
-     struct window *w;
-{
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
-  Lisp_Object window;
+  XSETFRAME (result->frame_or_window, f);
 
-  BLOCK_INPUT;
-  XSETWINDOW (window, w);
-  if (EQ (window, dpyinfo->mouse_face_window))
-    clear_mouse_face (dpyinfo);
-  UNBLOCK_INPUT;
+  result->arg = Qnil;
+  return Qnil;
 }
 
+\f
+/* Function to report a mouse movement to the mainstream Emacs code.
+   The input handler calls this.
 
-/* Just discard the mouse face information for frame F, if any.
-   This is used when the size of F is changed.  */
+   We have received a mouse movement event, which is given in *event.
+   If the mouse is over a different glyph than it was last time, tell
+   the mainstream emacs code by setting mouse_moved.  If not, ask for
+   another motion event, so we can check again the next time it moves.  */
 
-void
-cancel_mouse_face (f)
-     FRAME_PTR f;
+static Point last_mouse_motion_position;
+static Lisp_Object last_mouse_motion_frame;
+
+static void
+note_mouse_movement (frame, pos)
+     FRAME_PTR frame;
+     Point *pos;
 {
-  Lisp_Object window;
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
+#if TARGET_API_MAC_CARBON
+  Rect r;
+#endif
+
+  last_mouse_movement_time = TickCount () * (1000 / 60);  /* to milliseconds */
+  last_mouse_motion_position = *pos;
+  XSETFRAME (last_mouse_motion_frame, frame);
 
-  window = dpyinfo->mouse_face_window;
-  if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
+#if TARGET_API_MAC_CARBON
+  if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
+#else
+  if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
+#endif
     {
-      dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
-      dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
-      dpyinfo->mouse_face_window = Qnil;
+      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
+          || pos->h >= last_mouse_glyph.right
+          || pos->v < last_mouse_glyph.top
+          || pos->v >= last_mouse_glyph.bottom)
+    {
+      frame->mouse_moved = 1;
+      last_mouse_scroll_bar = Qnil;
+      note_mouse_highlight (frame, pos->h, pos->v);
     }
 }
+
+/* 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 *));
@@ -5803,6 +3773,19 @@ static void x_check_fullscreen_move P_ ((struct frame *));
 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
 
 
+/* MAC TODO:  This should be called from somewhere (or removed)  ++KFS */
+
+static void
+redo_mouse_highlight ()
+{
+  if (!NILP (last_mouse_motion_frame)
+      && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
+    note_mouse_highlight (XFRAME (last_mouse_motion_frame),
+                         last_mouse_motion_position.h,
+                         last_mouse_motion_position.v);
+}
+
+
 /* Try to determine frame pixel position and size of the glyph under
    frame pixel coordinates X/Y on frame F .  Return the position and
    size in *RECT.  Value is non-zero if we could compute these
@@ -5815,17 +3798,15 @@ glyph_rect (f, x, y, rect)
      Rect *rect;
 {
   Lisp_Object window;
-  int part;
 
-  window = window_from_coordinates (f, x, y, &part, 0);
+  window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
+
   if (!NILP (window))
     {
       struct window *w = XWINDOW (window);
       struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
       struct glyph_row *end = r + w->current_matrix->nrows - 1;
 
-      frame_to_window_pixel_xy (w, &x, &y);
-
       for (; r < end && r->enabled_p; ++r)
        if (r->y <= y && r->y + r->height > y)
          {
@@ -5840,7 +3821,10 @@ glyph_rect (f, x, y, rect)
            if (x < r->x)
              {
                /* x is to the left of the first glyph in the row.  */
-               rect->left = XINT (w->left);
+               /* Shouldn't this be a pixel value?
+                  WINDOW_LEFT_EDGE_X (w) seems to be the right value.
+                  ++KFS */
+               rect->left = WINDOW_LEFT_EDGE_COL (w);
                rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
                return 1;
              }
@@ -5856,7 +3840,10 @@ glyph_rect (f, x, y, rect)
 
            /* x is to the right of the last glyph in the row.  */
            rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-           rect->right = XINT (w->left) + XINT (w->width);
+           /* Shouldn't this be a pixel value?
+              WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
+              ++KFS */
+           rect->right = WINDOW_RIGHT_EDGE_COL (w);
            return 1;
          }
     }
@@ -5865,6 +3852,8 @@ glyph_rect (f, x, y, rect)
   return 0;
 }
 
+/* MAC TODO:  This should be called from somewhere (or removed)  ++KFS */
+
 /* Record the position of the mouse in last_mouse_glyph.  */
 static void
 remember_mouse_glyph (f1, gx, gy)
@@ -5876,7 +3865,7 @@ remember_mouse_glyph (f1, gx, gy)
       int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
       int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
 
-      /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
+      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
         round down even for negative values.  */
       if (gx < 0)
        gx -= width - 1;
@@ -5900,6 +3889,27 @@ remember_mouse_glyph (f1, gx, gy)
     }
 }
 
+
+static WindowPtr
+front_emacs_window ()
+{
+#if TARGET_API_MAC_CARBON
+  WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
+
+  while (wp && !is_emacs_window (wp))
+    wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
+#else
+  WindowPtr wp = FrontWindow ();
+
+  while (wp && (wp == tip_window || !is_emacs_window (wp)))
+    wp = GetNextWindow (wp);
+#endif
+
+  return wp;
+}
+
+#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
+
 /* Return the current position of the mouse.
    *fp should be a frame which indicates which display to ask about.
 
@@ -5931,12 +3941,12 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 {
   Point mouse_pos;
   int ignore1, ignore2;
-  WindowPtr wp = FrontWindow ();
+  WindowPtr wp = front_emacs_window ();
   struct frame *f;
   Lisp_Object frame, tail;
 
   if (is_emacs_window(wp))
-    f = ((mac_output *) GetWRefCon (wp))->mFP;
+    f = mac_window_to_frame (wp);
 
   BLOCK_INPUT;
 
@@ -5950,11 +3960,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);
 
@@ -5972,6 +3978,31 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
   UNBLOCK_INPUT;
 }
 
+\f
+/***********************************************************************
+                              Tool-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.  */
+
+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;
+
+  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));
+}
+
 \f
 /************************************************************************
                         Scroll bars, general
@@ -6136,35 +4167,30 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   struct frame *f = XFRAME (w->frame);
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
-  int window_x, window_y, window_width, window_height;
+  int window_y, window_height;
 
   /* Get window dimensions.  */
-  window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+  window_box (w, -1, 0, &window_y, 0, &window_height);
   top = window_y;
 #ifdef MAC_OSX
   width = 16;
 #else
-  width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+  width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
 #endif
   height = window_height;
 
   /* Compute the left edge of the scroll bar area.  */
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-    left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
-  else
-    left = XFASTINT (w->left);
-  left *= CANON_X_UNIT (f);
-  left += FRAME_INTERNAL_BORDER_WIDTH (f);
+  left = WINDOW_SCROLL_BAR_AREA_X (w);
 
   /* Compute the width of the scroll bar which might be less than
      the width of the area reserved for the scroll bar.  */
-  if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
-    sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
+  if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
+    sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
   else
     sb_width = width;
 
   /* Compute the left edge of the scroll bar.  */
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     sb_left = left + width - sb_width - (width - sb_width) / 2;
   else
     sb_left = left + (width - sb_width) / 2;
@@ -6177,13 +4203,13 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
       disp_top = -1;
       disp_height++;
     }
-  else if (disp_top == PIXEL_HEIGHT (f) - 16)
+  else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
     {
       disp_top++;
       disp_height--;
     }
 
-  if (sb_left + sb_width == PIXEL_WIDTH (f))
+  if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
     sb_left++;
 
   /* Does the scroll bar exist yet?  */
@@ -6219,12 +4245,12 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
             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 = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+         int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
          XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
                      left, top, area_width, height, 0);
 
 #if 0
-          if (sb_left + sb_width >= PIXEL_WIDTH (f))
+          if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
             XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
                        sb_left - 1, top, 1, height, 0);
 #endif
@@ -6372,7 +4398,7 @@ XTjudge_scroll_bars (f)
 }
 
 
-static void
+void
 activate_scroll_bars (frame)
      FRAME_PTR frame;
 {
@@ -6396,7 +4422,7 @@ activate_scroll_bars (frame)
 }
 
 
-static void
+void
 deactivate_scroll_bars (frame)
      FRAME_PTR frame;
 {
@@ -6429,6 +4455,8 @@ x_scroll_bar_handle_click (bar, part_code, er, bufp)
      EventRecord *er;
      struct input_event *bufp;
 {
+  int win_y, top_range;
+
   if (! GC_WINDOWP (bar->window))
     abort ();
 
@@ -6463,6 +4491,24 @@ 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);
 }
 
 
@@ -6512,16 +4558,12 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
      unsigned long *time;
 {
   struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
-  WindowPtr wp = FrontWindow ();
+  WindowPtr wp = front_emacs_window ();
   Point mouse_pos;
-  struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
+  struct frame *f = mac_window_to_frame (wp);
   int win_y, top_range;
 
-#if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (wp));
-#else
-  SetPort (wp);
-#endif
+  SetPortWindowPort (wp);
 
   GetMouse (&mouse_pos);
 
@@ -6567,40 +4609,30 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
 
 /* Set clipping for output in glyph row ROW.  W is the window in which
    we operate.  GC is the graphics context to set clipping in.
-   WHOLE_LINE_P non-zero means include the areas used for truncation
-   mark display and alike in the clipping rectangle.
 
    ROW may be a text row or, e.g., a mode line.  Text rows must be
    clipped to the interior of the window dedicated to text display,
    mode lines must be clipped to the whole window.  */
 
 static void
-x_clip_to_row (w, row, gc, whole_line_p)
+x_clip_to_row (w, row, area, gc)
      struct window *w;
      struct glyph_row *row;
+     int area;
      GC gc;
-     int whole_line_p;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Rect clip_rect;
-  int window_x, window_y, window_width, window_height;
+  int window_x, window_y, window_width;
 
-  window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+  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;
   clip_rect.bottom = clip_rect.top + row->visible_height;
 
-  /* If clipping to the whole line, including trunc marks, extend
-     the rectangle to the left and increase its width.  */
-  if (whole_line_p)
-    {
-      clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
-      clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
-    }
-
   mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
 }
 
@@ -6620,13 +4652,6 @@ x_draw_hollow_cursor (w, row)
   struct glyph *cursor_glyph;
   GC gc;
 
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
-  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
-       + row->ascent - w->phys_cursor_ascent);
-  h = row->height - 1;
-
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
   cursor_glyph = get_phys_cursor_glyph (w);
@@ -6640,7 +4665,22 @@ x_draw_hollow_cursor (w, row)
   wd = cursor_glyph->pixel_width - 1;
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
-    wd = min (CANON_X_UNIT (f), wd);
+    wd = min (FRAME_COLUMN_WIDTH (f), wd);
+  w->phys_cursor_width = wd;
+
+  /* Compute frame-relative coordinates from window-relative
+     coordinates.  */
+  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--;
 
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
@@ -6653,7 +4693,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, 0);
+  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));
 }
@@ -6666,413 +4706,161 @@ x_draw_hollow_cursor (w, row)
    Unfortunately, I didn't find a font yet that has this property set.
    --gerd.  */
 
-static void
-x_draw_bar_cursor (w, row, width)
-     struct window *w;
-     struct glyph_row *row;
-     int width;
-{
-  /* If cursor hpos is out of bounds, don't draw garbage.  This can
-     happen in mini-buffer windows when switching between echo area
-     glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
-    {
-      struct frame *f = XFRAME (w->frame);
-      struct glyph *cursor_glyph;
-      GC gc;
-      int x;
-      unsigned long mask;
-      XGCValues xgcv;
-      Display *dpy;
-      Window window;
-
-      cursor_glyph = get_phys_cursor_glyph (w);
-      if (cursor_glyph == NULL)
-       return;
-
-      xgcv.background = f->output_data.mac->cursor_pixel;
-      xgcv.foreground = f->output_data.mac->cursor_pixel;
-      mask = GCForeground | GCBackground;
-      dpy = FRAME_MAC_DISPLAY (f);
-      window = FRAME_MAC_WINDOW (f);
-      gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
-
-      if (gc)
-       XChangeGC (dpy, gc, mask, &xgcv);
-      else
-       {
-         gc = XCreateGC (dpy, window, mask, &xgcv);
-         FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
-       }
-
-      if (width < 0)
-       width = FRAME_CURSOR_WIDTH (f);
-
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-      x_clip_to_row (w, row, gc, 0);
-      XFillRectangle (dpy, window, gc,
-                     x,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                     min (cursor_glyph->pixel_width, width),
-                     row->height);
-      mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
-    }
-}
-
-
-/* Clear the cursor of window W to background color, and mark the
-   cursor as not shown.  This is used when the text where the cursor
-   is is about to be rewritten.  */
-
-static void
-x_clear_cursor (w)
-     struct window *w;
-{
-  if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
-    x_update_window_cursor (w, 0);
-}
-
-
-/* Draw the cursor glyph of window W in glyph row ROW.  See the
-   comment of x_draw_glyphs for the meaning of HL.  */
-
-static void
-x_draw_phys_cursor_glyph (w, row, hl)
-     struct window *w;
-     struct glyph_row *row;
-     enum draw_glyphs_face hl;
-{
-  /* If cursor hpos is out of bounds, don't draw garbage.  This can
-     happen in mini-buffer windows when switching between echo area
-     glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
-    {
-      int on_p = w->phys_cursor_on_p;
-      x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
-                     w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
-                     hl, 0);
-      w->phys_cursor_on_p = on_p;
-
-      /* When we erase the cursor, and ROW is overlapped by other
-        rows, make sure that these overlapping parts of other rows
-        are redrawn.  */
-      if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
-       {
-         if (row > w->current_matrix->rows
-             && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
-           x_fix_overlapping_area (w, row - 1, TEXT_AREA);
-
-         if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
-             && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
-           x_fix_overlapping_area (w, row + 1, TEXT_AREA);
-       }
-    }
-}
-
-
-/* Erase the image of a cursor of window W from the screen.  */
-
-static void
-x_erase_phys_cursor (w)
-     struct window *w;
-{
-  struct frame *f = XFRAME (w->frame);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int hpos = w->phys_cursor.hpos;
-  int vpos = w->phys_cursor.vpos;
-  int mouse_face_here_p = 0;
-  struct glyph_matrix *active_glyphs = w->current_matrix;
-  struct glyph_row *cursor_row;
-  struct glyph *cursor_glyph;
-  enum draw_glyphs_face hl;
-
-  /* No cursor displayed or row invalidated => nothing to do on the
-     screen.  */
-  if (w->phys_cursor_type == NO_CURSOR)
-    goto mark_cursor_off;
-
-  /* VPOS >= active_glyphs->nrows means that window has been resized.
-     Don't bother to erase the cursor.  */
-  if (vpos >= active_glyphs->nrows)
-    goto mark_cursor_off;
-
-  /* If row containing cursor is marked invalid, there is nothing we
-     can do.  */
-  cursor_row = MATRIX_ROW (active_glyphs, vpos);
-  if (!cursor_row->enabled_p)
-    goto mark_cursor_off;
-
-  /* If row is completely invisible, don't attempt to delete a cursor which
-     isn't there.  This may happen if cursor is at top of window, and
-     we switch to a buffer with a header line in that window.  */
-  if (cursor_row->visible_height <= 0)
-    goto mark_cursor_off;
-
-  /* This can happen when the new row is shorter than the old one.
-     In this case, either x_draw_glyphs or clear_end_of_line
-     should have cleared the cursor.  Note that we wouldn't be
-     able to erase the cursor in this case because we don't have a
-     cursor glyph at hand.  */
-  if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
-    goto mark_cursor_off;
-
-  /* If the cursor is in the mouse face area, redisplay that when
-     we clear the cursor.  */
-  if (! NILP (dpyinfo->mouse_face_window)
-      && w == XWINDOW (dpyinfo->mouse_face_window)
-      && (vpos > dpyinfo->mouse_face_beg_row
-         || (vpos == dpyinfo->mouse_face_beg_row
-             && hpos >= dpyinfo->mouse_face_beg_col))
-      && (vpos < dpyinfo->mouse_face_end_row
-         || (vpos == dpyinfo->mouse_face_end_row
-             && hpos < dpyinfo->mouse_face_end_col))
-      /* Don't redraw the cursor's spot in mouse face if it is at the
-        end of a line (on a newline).  The cursor appears there, but
-        mouse highlighting does not.  */
-      && cursor_row->used[TEXT_AREA] > hpos)
-    mouse_face_here_p = 1;
-
-  /* Maybe clear the display under the cursor.  */
-  if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
-    {
-      int x;
-      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-
-      cursor_glyph = get_phys_cursor_glyph (w);
-      if (cursor_glyph == NULL)
-       goto mark_cursor_off;
-
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
-
-      XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
-                 x,
-                 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                  cursor_row->y)),
-                 cursor_glyph->pixel_width,
-                 cursor_row->visible_height,
-                 0);
-    }
-
-  /* Erase the cursor by redrawing the character underneath it.  */
-  if (mouse_face_here_p)
-    hl = DRAW_MOUSE_FACE;
-  else
-    hl = DRAW_NORMAL_TEXT;
-  x_draw_phys_cursor_glyph (w, cursor_row, hl);
-
- mark_cursor_off:
-  w->phys_cursor_on_p = 0;
-  w->phys_cursor_type = NO_CURSOR;
-}
-
-
-/* Non-zero if physical cursor of window W is within mouse face.  */
-
-static int
-cursor_in_mouse_face_p (w)
-     struct window *w;
-{
-  struct mac_display_info *dpyinfo
-    = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
-  int in_mouse_face = 0;
-
-  if (WINDOWP (dpyinfo->mouse_face_window)
-      && XWINDOW (dpyinfo->mouse_face_window) == w)
-    {
-      int hpos = w->phys_cursor.hpos;
-      int vpos = w->phys_cursor.vpos;
-
-      if (vpos >= dpyinfo->mouse_face_beg_row
-         && vpos <= dpyinfo->mouse_face_end_row
-         && (vpos > dpyinfo->mouse_face_beg_row
-             || hpos >= dpyinfo->mouse_face_beg_col)
-         && (vpos < dpyinfo->mouse_face_end_row
-             || hpos < dpyinfo->mouse_face_end_col
-             || dpyinfo->mouse_face_past_end))
-       in_mouse_face = 1;
-    }
-
-  return in_mouse_face;
-}
-
-
-/* Display or clear cursor of window W.  If ON is zero, clear the
-   cursor.  If it is non-zero, display the cursor.  If ON is nonzero,
-   where to put the cursor is specified by HPOS, VPOS, X and Y.  */
-
-void
-x_display_and_set_cursor (w, on, hpos, vpos, x, y)
+static void
+x_draw_bar_cursor (w, row, width, kind)
      struct window *w;
-     int on, hpos, vpos, x, y;
+     struct glyph_row *row;
+     int width;
+     enum text_cursor_kinds kind;
 {
   struct frame *f = XFRAME (w->frame);
-  int new_cursor_type;
-  int new_cursor_width;
-  int active_cursor;
-  struct glyph_matrix *current_glyphs;
-  struct glyph_row *glyph_row;
-  struct glyph *glyph;
-
-  /* This is pointless on invisible frames, and dangerous on garbaged
-     windows and frames; in the latter case, the frame or window may
-     be in the midst of changing its size, and x and y may be off the
-     window.  */
-  if (! FRAME_VISIBLE_P (f)
-      || FRAME_GARBAGED_P (f)
-      || vpos >= w->current_matrix->nrows
-      || hpos >= w->current_matrix->matrix_w)
-    return;
+  struct glyph *cursor_glyph;
 
-  /* If cursor is off and we want it off, return quickly.  */
-  if (!on && !w->phys_cursor_on_p)
+  /* If cursor is out of bounds, don't draw garbage.  This can happen
+     in mini-buffer windows when switching between echo area glyphs
+     and mini-buffer.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph == NULL)
     return;
 
-  current_glyphs = w->current_matrix;
-  glyph_row = MATRIX_ROW (current_glyphs, vpos);
-  glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
-
-  /* If cursor row is not enabled, we don't really know where to
-     display the cursor.  */
-  if (!glyph_row->enabled_p)
+  /* If on an image, draw like a normal cursor.  That's usually better
+     visible than drawing a bar, esp. if the image is large so that
+     the bar might not be in the window.  */
+  if (cursor_glyph->type == IMAGE_GLYPH)
     {
-      w->phys_cursor_on_p = 0;
-      return;
+      struct glyph_row *row;
+      row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
+      draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
     }
-
-  xassert (interrupt_input_blocked);
-
-  /* Set new_cursor_type to the cursor we want to be displayed.  */
-  new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
-
-
-  /* If cursor is currently being shown and we don't want it to be or
-     it is in the wrong place, or the cursor type is not what we want,
-     erase it.  */
-  if (w->phys_cursor_on_p
-      && (!on
-         || w->phys_cursor.x != x
-         || w->phys_cursor.y != y
-         || new_cursor_type != w->phys_cursor_type
-         || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
-             && new_cursor_width != w->phys_cursor_width)))
-    x_erase_phys_cursor (w);
-
-  /* If the cursor is now invisible and we want it to be visible,
-     display it.  */
-  if (on && !w->phys_cursor_on_p)
+  else
     {
-      w->phys_cursor_ascent = glyph_row->ascent;
-      w->phys_cursor_height = glyph_row->height;
+      Display *dpy = FRAME_MAC_DISPLAY (f);
+      Window window = FRAME_MAC_WINDOW (f);
+      GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
+      unsigned long mask = GCForeground | GCBackground;
+      struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
+      XGCValues xgcv;
 
-      /* Set phys_cursor_.* before x_draw_.* is called because some
-        of them may need the information.  */
-      w->phys_cursor.x = x;
-      w->phys_cursor.y = glyph_row->y;
-      w->phys_cursor.hpos = hpos;
-      w->phys_cursor.vpos = vpos;
-      w->phys_cursor_type = new_cursor_type;
-      w->phys_cursor_width = new_cursor_width;
-      w->phys_cursor_on_p = 1;
+      /* If the glyph's background equals the color we normally draw
+        the bar cursor in, the bar cursor in its normal color is
+        invisible.  Use the glyph's foreground color instead in this
+        case, on the assumption that the glyph's colors are chosen so
+        that the glyph is legible.  */
+      if (face->background == f->output_data.mac->cursor_pixel)
+       xgcv.background = xgcv.foreground = face->foreground;
+      else
+       xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
 
-      switch (new_cursor_type)
+      if (gc)
+       XChangeGC (dpy, gc, mask, &xgcv);
+      else
        {
-       case HOLLOW_BOX_CURSOR:
-         x_draw_hollow_cursor (w, glyph_row);
-         break;
+         gc = XCreateGC (dpy, window, mask, &xgcv);
+         FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
+       }
 
-       case FILLED_BOX_CURSOR:
-         x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
-         break;
+      if (width < 0)
+       width = FRAME_CURSOR_WIDTH (f);
+      width = min (cursor_glyph->pixel_width, width);
 
-       case HBAR_CURSOR:
-         /* TODO.  For now, just draw bar cursor. */
-       case BAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row, new_cursor_width);
-         break;
+      w->phys_cursor_width = width;
+      x_clip_to_row (w, row, TEXT_AREA, gc);
 
-       case NO_CURSOR:
-         break;
+      if (kind == BAR_CURSOR)
+       XFillRectangle (dpy, window, gc,
+                       WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                       WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                       width, row->height);
+      else
+       XFillRectangle (dpy, window, gc,
+                       WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                       WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+                                                row->height - width),
+                       cursor_glyph->pixel_width,
+                       width);
 
-       default:
-         abort ();
-       }
+      mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
     }
 }
 
 
-/* Display the cursor on window W, or clear it.  X and Y are window
-   relative pixel coordinates.  HPOS and VPOS are glyph matrix
-   positions.  If W is not the selected window, display a hollow
-   cursor.  ON non-zero means display the cursor at X, Y which
-   correspond to HPOS, VPOS, otherwise it is cleared.  */
+/* RIF: Define cursor CURSOR on frame F.  */
 
-void
-x_display_cursor (w, on, hpos, vpos, x, y)
-     struct window *w;
-     int on, hpos, vpos, x, y;
+static void
+mac_define_frame_cursor (f, cursor)
+     struct frame *f;
+     Cursor cursor;
 {
-  BLOCK_INPUT;
-  x_display_and_set_cursor (w, on, hpos, vpos, x, y);
-  UNBLOCK_INPUT;
+#if TARGET_API_MAC_CARBON
+  SetThemeCursor (cursor);
+#else
+  SetCursor (*cursor);
+#endif
 }
 
 
-/* Display the cursor on window W, or clear it, according to ON_P.
-   Don't change the cursor's position.  */
+/* RIF: Clear area on frame F.  */
 
-void
-x_update_cursor (f, on_p)
+static void
+mac_clear_frame_area (f, x, y, width, height)
      struct frame *f;
-     int on_p;
+     int x, y, width, height;
 {
-  x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
+  XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+             x, y, width, height, 0);
 }
 
 
-/* Call x_update_window_cursor with parameter ON_P on all leaf windows
-   in the window tree rooted at W.  */
+/* RIF: Draw cursor on window W.  */
 
 static void
-x_update_cursor_in_window_tree (w, on_p)
+mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
      struct window *w;
-     int on_p;
+     struct glyph_row *glyph_row;
+     int x, y;
+     int cursor_type, cursor_width;
+     int on_p, active_p;
 {
-  while (w)
+  if (on_p)
     {
-      if (!NILP (w->hchild))
-       x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-       x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
+      w->phys_cursor_type = cursor_type;
+      w->phys_cursor_on_p = 1;
+
+      if (glyph_row->exact_window_width_line_p
+         && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+       {
+         glyph_row->cursor_in_fringe_p = 1;
+         draw_fringe_bitmap (w, glyph_row, 0);
+       }
       else
-       x_update_window_cursor (w, on_p);
+      switch (cursor_type)
+       {
+       case HOLLOW_BOX_CURSOR:
+         x_draw_hollow_cursor (w, glyph_row);
+         break;
 
-      w = NILP (w->next) ? 0 : XWINDOW (w->next);
-    }
-}
+       case FILLED_BOX_CURSOR:
+         draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+         break;
 
+       case BAR_CURSOR:
+         x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+         break;
 
-/* Switch the display of W's cursor on or off, according to the value
-   of ON.  */
+       case HBAR_CURSOR:
+         x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
+         break;
 
-static void
-x_update_window_cursor (w, on)
-     struct window *w;
-     int on;
-{
-  /* Don't update cursor in windows whose frame is in the process
-     of being deleted.  */
-  if (w->current_matrix)
-    {
-      BLOCK_INPUT;
-      x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
-                                w->phys_cursor.vpos, w->phys_cursor.x,
-                                w->phys_cursor.y);
-      UNBLOCK_INPUT;
+       case NO_CURSOR:
+         w->phys_cursor_width = 0;
+         break;
+
+       default:
+         abort ();
+       }
     }
 }
 
-
-
 \f
 /* Icons.  */
 
@@ -7172,36 +4960,37 @@ 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_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
+
+  compute_fringe_widths (f, 1);
+
   /* Compute the scroll bar width in character columns.  */
-  if (f->scroll_bar_pixel_width > 0)
+  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
     {
-      int wid = FONT_WIDTH (FRAME_FONT (f));
-      f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f)
+       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
     }
   else
     {
-      int wid = FONT_WIDTH (FRAME_FONT (f));
-      f->scroll_bar_cols = (14 + wid - 1) / wid;
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
     }
 
   /* Now make the frame display the given font.  */
   if (FRAME_MAC_WINDOW (f) != 0)
     {
       XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
-               f->output_data.mac->font);
+               FRAME_FONT (f));
       XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
-               f->output_data.mac->font);
+               FRAME_FONT (f));
       XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
-               f->output_data.mac->font);
+               FRAME_FONT (f));
 
-      frame_update_line_height (f);
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-        x_set_window_size (f, 0, f->width, f->height);
+        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
     }
-  else
-    /* If we are setting a new frame's font for the first time,
-       there are no faces yet, so this font's height is the line height.  */
-    f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
 
   return build_string (fontp->full_name);
 }
@@ -7255,6 +5044,26 @@ 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 */
+}
+
+
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
 
@@ -7262,55 +5071,40 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Point pt;
-  int flags = f->output_data.mac->size_hint_flags;
+  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->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
-                             - 2 * f->output_data.mac->border_width - pt.h
-                             - PIXEL_WIDTH (f)
-                             + f->output_data.mac->left_pos);
-  /* NTEMACS_TODO: Subtract menubar height?  */
+    f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
+                   - width_diff
+                  - FRAME_PIXEL_WIDTH (f)
+                  + f->left_pos);
+
   if (flags & YNegative)
-    f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
-                            - 2 * f->output_data.mac->border_width - pt.v
-                            - PIXEL_HEIGHT (f)
-                            + f->output_data.mac->top_pos);
+    f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
+                 - 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.  */
-  f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
+  f->size_hint_flags &= ~ (XNegative | YNegative);
 }
 
 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
@@ -7325,29 +5119,71 @@ 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->output_data.mac->top_pos = yoff;
-      f->output_data.mac->left_pos = xoff;
-      f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
+      f->top_pos = yoff;
+      f->left_pos = xoff;
+      f->size_hint_flags &= ~ (XNegative | YNegative);
       if (xoff < 0)
-       f->output_data.mac->size_hint_flags |= XNegative;
+       f->size_hint_flags |= XNegative;
       if (yoff < 0)
-       f->output_data.mac->size_hint_flags |= YNegative;
-      f->output_data.mac->win_gravity = NorthWestGravity;
+       f->size_hint_flags |= YNegative;
+      f->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
 
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
-  modified_left = f->output_data.mac->left_pos;
-  modified_top = f->output_data.mac->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;
 }
@@ -7368,17 +5204,15 @@ x_set_window_size (f, change_gravity, cols, rows)
   BLOCK_INPUT;
 
   check_frame_size (f, &rows, &cols);
-  f->output_data.mac->vertical_scroll_bar_extra
-    = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-       ? 0
-       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
+  f->scroll_bar_actual_width
+    = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
 
   compute_fringe_widths (f, 0);
 
-  pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
-  pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
+  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
+  pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
 
-  f->output_data.mac->win_gravity = NorthWestGravity;
+  f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
 
   SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
@@ -7397,8 +5231,8 @@ x_set_window_size (f, change_gravity, cols, rows)
      We pass 1 for DELAY since we can't run Lisp code inside of
      a BLOCK_INPUT.  */
   change_frame_size (f, rows, cols, 0, 1, 0);
-  PIXEL_WIDTH (f) = pixelwidth;
-  PIXEL_HEIGHT (f) = pixelheight;
+  FRAME_PIXEL_WIDTH (f) = pixelwidth;
+  FRAME_PIXEL_HEIGHT (f) = pixelheight;
 
   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
      receive in the ConfigureNotify event; if we get what we asked
@@ -7431,14 +5265,14 @@ x_set_mouse_position (f, x, y)
 {
   int pix_x, pix_y;
 
-  pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->output_data.mac->font) / 2;
-  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
+  pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
+  pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
 
   if (pix_x < 0) pix_x = 0;
-  if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
+  if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
 
   if (pix_y < 0) pix_y = 0;
-  if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
+  if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
 
   x_set_mouse_pixel_position (f, pix_x, pix_y);
 }
@@ -7488,7 +5322,11 @@ 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.  */
@@ -7497,7 +5335,11 @@ 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
@@ -7537,8 +5379,7 @@ 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->output_data.mac->left_pos,
-                     f->output_data.mac->top_pos, 0);
+       x_set_offset (f, f->left_pos, f->top_pos, 0);
 
       f->output_data.mac->asked_for_visible = 1;
 
@@ -7547,7 +5388,6 @@ x_make_frame_visible (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.  */
@@ -7591,7 +5431,6 @@ x_make_frame_visible (f)
        FRAME_SAMPLE_VISIBILITY (f);
       }
   }
-#endif /* MAC_TODO */
 }
 
 /* Change from mapped state to withdrawn state.  */
@@ -7647,23 +5486,33 @@ x_iconify_frame (f)
 }
 
 \f
-/* Destroy the X window of frame F.  */
+/* Free X resources of frame F.  */
 
 void
-x_destroy_window (f)
+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));
+  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);
-  free_frame_faces (f);
+
+  if (FRAME_FACE_CACHE (f))
+    free_frame_faces (f);
+
+  x_free_gcs (f);
 
   xfree (f->output_data.mac);
-  f->output_data.mac = 0;
+  f->output_data.mac = NULL;
+
   if (f == dpyinfo->x_focus_frame)
     dpyinfo->x_focus_frame = 0;
   if (f == dpyinfo->x_focus_event_frame)
@@ -7671,8 +5520,6 @@ x_destroy_window (f)
   if (f == dpyinfo->x_highlight_frame)
     dpyinfo->x_highlight_frame = 0;
 
-  dpyinfo->reference_count--;
-
   if (f == dpyinfo->mouse_face_mouse_frame)
     {
       dpyinfo->mouse_face_beg_row
@@ -7686,6 +5533,21 @@ x_destroy_window (f)
 
   UNBLOCK_INPUT;
 }
+
+
+/* Destroy the X window of frame F.  */
+
+void
+x_destroy_window (f)
+     struct frame *f;
+{
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+  x_free_frame_resources (f);
+
+  dpyinfo->reference_count--;
+}
+
 \f
 /* Setting window manager hints.  */
 
@@ -7715,8 +5577,8 @@ x_wm_set_size_hint (f, flags, user_position)
   /* Setting PMaxSize caused various problems.  */
   size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
 
-  size_hints.x = f->output_data.x->left_pos;
-  size_hints.y = f->output_data.x->top_pos;
+  size_hints.x = f->left_pos;
+  size_hints.y = f->top_pos;
 
 #ifdef USE_X_TOOLKIT
   XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
@@ -7725,16 +5587,16 @@ x_wm_set_size_hint (f, flags, user_position)
   size_hints.height = widget_height;
   size_hints.width = widget_width;
 #else /* not USE_X_TOOLKIT */
-  size_hints.height = PIXEL_HEIGHT (f);
-  size_hints.width = PIXEL_WIDTH (f);
+  size_hints.height = FRAME_PIXEL_HEIGHT (f);
+  size_hints.width = FRAME_PIXEL_WIDTH (f);
 #endif /* not USE_X_TOOLKIT */
 
-  size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
-  size_hints.height_inc = f->output_data.x->line_height;
+  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 - CHAR_TO_PIXEL_WIDTH (f, 0);
+    = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
   size_hints.max_height
-    = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
+    = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
   /* Calculate the base and minimum sizes.
 
@@ -7745,8 +5607,8 @@ x_wm_set_size_hint (f, flags, user_position)
     int base_width, base_height;
     int min_rows = 0, min_cols = 0;
 
-    base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
-    base_height = CHAR_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);
 
     check_frame_size (f, &min_rows, &min_cols);
 
@@ -7821,7 +5683,7 @@ x_wm_set_size_hint (f, flags, user_position)
 #endif
 
 #ifdef PWinGravity
-  size_hints.win_gravity = f->output_data.x->win_gravity;
+  size_hints.win_gravity = f->win_gravity;
   size_hints.flags |= PWinGravity;
 
   if (user_position)
@@ -7952,6 +5814,7 @@ char **font_name_table = NULL;
 int font_name_table_size = 0;
 int font_name_count = 0;
 
+#if 0
 /* compare two strings ignoring case */
 static int
 stricmp (const char *s, const char *t)
@@ -8031,13 +5894,53 @@ mac_font_match (char *mf, char *xf)
           && wildstrieq (m_charset, x_charset))
          || mac_font_pattern_match (mf, xf);
 }
+#endif
+
+static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
+
+static void
+decode_mac_font_name (char *name, int size, short scriptcode)
+{
+  Lisp_Object coding_system;
+  struct coding_system coding;
+  char *buf;
+
+  switch (scriptcode)
+    {
+    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;
+    }
+
+  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 (char *name, int size, Style style, short scriptcode)
 {
   char foundry[32], family[32], cs[32];
-  char xf[255], *result, *p;
+  char xf[256], *result, *p;
 
   if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
     {
@@ -8096,6 +5999,8 @@ static void
 x_font_name_to_mac_font_name (char *xf, char *mf)
 {
   char foundry[32], family[32], weight[20], slant[2], cs[32];
+  Lisp_Object coding_system = Qnil;
+  struct coding_system coding;
 
   strcpy (mf, "");
 
@@ -8105,13 +6010,29 @@ x_font_name_to_mac_font_name (char *xf, char *mf)
               foundry, family, weight, slant, cs) != 5)
     return;
 
-  if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
-      || strcmp (cs, "jisx0208.1983-sjis") == 0
-      || strcmp (cs, "jisx0201.1976-0") == 0
-      || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
-    strcpy(mf, family);
+  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);
   else
-    sprintf(mf, "%s-%s-%s", foundry, family, cs);
+    sprintf (mf, "%s-%s-%s", foundry, family, cs);
+
+  if (!NILP (coding_system))
+    {
+      setup_coding_system (coding_system, &coding);
+      coding.src_multibyte = 1;
+      coding.dst_multibyte = 1;
+      coding.mode |= CODING_MODE_LAST_BLOCK;
+      encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
+      mf[coding.produced] = '\0';
+    }
 }
 
 
@@ -8175,36 +6096,45 @@ init_font_name_table ()
          if (FMGetFontFamilyName (ff, name) != noErr)
            break;
          p2cstr (name);
+         if (*name == '.')
+           continue;
 
          sc = FontToScript (ff);
+         decode_mac_font_name (name, sizeof (name), sc);
 
          /* Point the instance iterator at the current font family.  */
-         if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
+         if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
            break;
 
          while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
                 == noErr)
-           if (size == 0)
-             {
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             style, sc));
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             italic, sc));
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             bold, sc));
-               add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                             italic | bold,
-                                                             sc));
-             }
-           else
-             {
+           {
+             /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
+                contained in Apple Japanese (SJIS) font.  */
+           again:
+             if (size == 0)
+               {
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               style, sc));
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               italic, sc));
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               bold, sc));
+                 add_font_name_table_entry (mac_to_x_fontname (name, size,
+                                                               italic | bold,
+                                                               sc));
+               }
+             else
                add_font_name_table_entry (mac_to_x_fontname (name, size,
                                                              style, sc));
-               if (smJapanese == sc)
-                 add_font_name_table_entry (mac_to_x_fontname (name, size,
-                                                               style,
-                                                               -smJapanese));
-             }
+             if (sc == smJapanese)
+               {
+                 sc = -smJapanese;
+                 goto again;
+               }
+             else if (sc == -smJapanese)
+               sc = smJapanese;
+           }
        }
 
       /* Dispose of the iterators.  */
@@ -8246,6 +6176,7 @@ init_font_name_table ()
 
          TextFont (fontnum);
          scriptcode = FontToScript (fontnum);
+         decode_mac_font_name (name, sizeof (name), scriptcode);
          do
            {
              HLock (font_handle);
@@ -8280,9 +6211,9 @@ init_font_name_table ()
                                             assc_entry->fontSize,
                                             assc_entry->fontStyle,
                                             scriptcode);
-                     /* Both jisx0208.1983-sjis and
-                        jisx0201.1976-sjis parts are contained in
-                        Apple Japanese (SJIS) font.  */
+                     /* 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++]
@@ -8302,17 +6233,157 @@ init_font_name_table ()
          while (ResError () == noErr && font_handle);
        }
 
-      TextFont (old_fontnum);
-#if TARGET_API_MAC_CARBON
+      TextFont (old_fontnum);
+#if TARGET_API_MAC_CARBON
+    }
+#endif  /* TARGET_API_MAC_CARBON */
+}
+
+
+enum xlfd_scalable_field_index
+  {
+    XLFD_SCL_PIXEL_SIZE,
+    XLFD_SCL_POINT_SIZE,
+    XLFD_SCL_AVGWIDTH,
+    XLFD_SCL_LAST
+  };
+
+static int xlfd_scalable_fields[] =
+  {
+    6,                         /* PIXEL_SIZE */
+    7,                         /* POINT_SIZE */
+    11,                                /* AVGWIDTH */
+    -1
+  };
+
+static Lisp_Object
+mac_do_list_fonts (pattern, maxnames)
+     char *pattern;
+     int maxnames;
+{
+  int i, n_fonts = 0;
+  Lisp_Object font_list = Qnil, pattern_regex, fontname;
+  char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
+  char scaled[256];
+  char *ptr;
+  int scl_val[XLFD_SCL_LAST], *field, *val;
+
+  for (i = 0; i < XLFD_SCL_LAST; i++)
+    scl_val[i] = -1;
+
+  /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
+     POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
+     fonts are scaled according to the specified size.  */
+  ptr = pattern;
+  i = 0;
+  field = xlfd_scalable_fields;
+  val = scl_val;
+  if (*ptr == '-')
+    do
+      {
+       ptr++;
+       if (i == *field)
+         {
+           if ('1' <= *ptr && *ptr <= '9')
+             {
+               *val = *ptr++ - '0';
+               while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
+                 *val = *val * 10 + *ptr++ - '0';
+               if (*ptr != '-')
+                 *val = -1;
+             }
+           field++;
+           val++;
+         }
+       ptr = strchr (ptr, '-');
+       i++;
+      }
+    while (ptr && i < 14);
+
+  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];
+       }
+    }
+  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';
+
+  pattern_regex = build_string (regex);
+
+  for (i = 0; i < font_name_count; i++)
+    {
+      fontname = build_string (font_name_table[i]);
+      if (fast_string_match (pattern_regex, fontname) >= 0)
+       {
+         font_list = Fcons (fontname, font_list);
+
+          n_fonts++;
+          if (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-")))
+       {
+         int former_len = ptr - font_name_table[i];
+
+         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);
+
+             n_fonts++;
+             if (maxnames > 0 && n_fonts >= maxnames)
+               break;
+           }
+       }
     }
-#endif  /* TARGET_API_MAC_CARBON */
+  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).  */
+   calling mac_font_pattern_match (slow).  Return as many matching
+   fonts as possible if MAXNAMES = -1.  */
 
 Lisp_Object
 x_list_fonts (struct frame *f,
@@ -8320,11 +6391,7 @@ x_list_fonts (struct frame *f,
               int size,
               int maxnames)
 {
-  char *ptnstr;
   Lisp_Object newlist = Qnil, tem, key;
-  int n_fonts = 0;
-  int i;
-  struct gcpro gcpro1, gcpro2;
   struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
 
   if (font_name_table == NULL)  /* Initialize when first used.  */
@@ -8343,27 +6410,10 @@ x_list_fonts (struct frame *f,
        }
     }
 
-  ptnstr = SDATA (pattern);
-
-  GCPRO2 (pattern, newlist);
-
-  /* Scan and matching bitmap fonts.  */
-  for (i = 0; i < font_name_count; i++)
-    {
-      if (mac_font_pattern_match (font_name_table[i], ptnstr))
-        {
-          newlist = Fcons (build_string (font_name_table[i]), newlist);
-
-          n_fonts++;
-          if (n_fonts >= maxnames)
-            break;
-        }
-    }
+  newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
 
   /* MAC_TODO: add code for matching outline fonts here */
 
-  UNGCPRO;
-
   if (dpyinfo)
     {
       XSETCDR (dpyinfo->name_list_element,
@@ -8523,14 +6573,12 @@ XLoadQueryFont (Display *dpy, char *fontname)
     name = fontname;
   else
     {
-      for (i = 0; i < font_name_count; i++)
-        if (mac_font_pattern_match (font_name_table[i], fontname))
-          break;
-
-      if (i >= font_name_count)
-        return NULL;
+      Lisp_Object matched_fonts;
 
-      name = font_name_table[i];
+      matched_fonts = mac_do_list_fonts (fontname, 1);
+      if (NILP (matched_fonts))
+       return NULL;
+      name = SDATA (XCAR (matched_fonts));
     }
 
   GetPort (&port);  /* save the current font number used */
@@ -8652,7 +6700,8 @@ XLoadQueryFont (Display *dpy, char *fontname)
         for (c = 0x20; c <= 0xff; c++)
           {
             font->per_char[c - 0x20] = font->max_bounds;
-            font->per_char[c - 0x20].width = CharWidth (c);
+            font->per_char[c - 0x20].width =
+             font->per_char[c - 0x20].rbearing = CharWidth (c);
           }
       }
     }
@@ -8741,6 +6790,7 @@ x_load_font (f, fontname, size)
 
     /* Now fill in the slots of *FONTP.  */
     BLOCK_INPUT;
+    bzero (fontp, sizeof (*fontp));
     fontp->font = font;
     fontp->font_idx = i;
     fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
@@ -8874,81 +6924,6 @@ x_find_ccl_program (fontp)
 
 
 \f
-/***********************************************************************
-                           Initialization
- ***********************************************************************/
-
-#ifdef USE_X_TOOLKIT
-static XrmOptionDescRec emacs_options[] = {
-  {"-geometry",        ".geometry", XrmoptionSepArg, NULL},
-  {"-iconic",  ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
-
-  {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
-     XrmoptionSepArg, NULL},
-  {"-ib",      "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
-
-  {"-T",       "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
-  {"-wn",      "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
-  {"-title",   "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
-  {"-iconname",        "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
-  {"-in",      "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
-  {"-mc",      "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
-  {"-cr",      "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
-};
-#endif /* USE_X_TOOLKIT */
-
-static int x_initialized;
-
-#ifdef MULTI_KBOARD
-/* Test whether two display-name strings agree up to the dot that separates
-   the screen number from the server number.  */
-static int
-same_x_server (name1, name2)
-     char *name1, *name2;
-{
-  int seen_colon = 0;
-  unsigned char *system_name = SDATA (Vsystem_name);
-  int system_name_length = strlen (system_name);
-  int length_until_period = 0;
-
-  while (system_name[length_until_period] != 0
-        && system_name[length_until_period] != '.')
-    length_until_period++;
-
-  /* Treat `unix' like an empty host name.  */
-  if (! strncmp (name1, "unix:", 5))
-    name1 += 4;
-  if (! strncmp (name2, "unix:", 5))
-    name2 += 4;
-  /* Treat this host's name like an empty host name.  */
-  if (! strncmp (name1, system_name, system_name_length)
-      && name1[system_name_length] == ':')
-    name1 += system_name_length;
-  if (! strncmp (name2, system_name, system_name_length)
-      && name2[system_name_length] == ':')
-    name2 += system_name_length;
-  /* Treat this host's domainless name like an empty host name.  */
-  if (! strncmp (name1, system_name, length_until_period)
-      && name1[length_until_period] == ':')
-    name1 += length_until_period;
-  if (! strncmp (name2, system_name, length_until_period)
-      && name2[length_until_period] == ':')
-    name2 += length_until_period;
-
-  for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
-    {
-      if (*name1 == ':')
-       seen_colon++;
-      if (seen_colon && *name1 == '.')
-       return 1;
-    }
-  return (seen_colon
-         && (*name1 == '.' || *name1 == '\0')
-         && (*name2 == '.' || *name2 == '\0'));
-}
-#endif
-
-
 /* The Mac Event loop code */
 
 #ifndef MAC_OSX
@@ -8992,6 +6967,7 @@ same_x_server (name1, name2)
 /* true when cannot handle any Mac OS events */
 static int handling_window_update = 0;
 
+#if 0
 /* the flag appl_is_suspended is used both for determining the sleep
    time to be passed to WaitNextEvent and whether the cursor should be
    drawn when updating the display.  The cursor is turned off when
@@ -9001,6 +6977,7 @@ static int handling_window_update = 0;
    suspended.  */
 static Boolean app_is_suspended = false;
 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
+#endif
 
 #define EXTRA_STACK_ALLOC (256 * 1024)
 
@@ -9010,12 +6987,22 @@ static long app_sleep_time = WNE_SLEEP_AT_RESUME;
 
 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;
 
+/* True if the option and command modifiers should be used to emulate
+   a three button mouse */
+Lisp_Object Vmac_emulate_three_button_mouse;
+
 #if USE_CARBON_EVENTS
 /* True if the mouse wheel button (i.e. button 4) should map to
    mouse-2, instead of mouse-3.  */
@@ -9043,6 +7030,11 @@ Lisp_Object drag_and_drop_file_list;
 
 Point saved_menu_event_location;
 
+#if !TARGET_API_MAC_CARBON
+/* Place holder for the default arrow cursor.  */
+CursPtr arrow_cursor;
+#endif
+
 /* Apple Events */
 static void init_required_apple_events (void);
 static pascal OSErr
@@ -9085,6 +7077,26 @@ 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;
+}
+
+static int
+mac_get_emulated_btn ( UInt32 modifiers )
+{
+  int result = 0;
+  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;
+  }
   return result;
 }
 
@@ -9097,6 +7109,11 @@ mac_event_to_emacs_modifiers (EventRef eventRef)
   UInt32 mods = 0;
   GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
                    sizeof (UInt32), NULL, &mods);
+  if (!NILP (Vmac_emulate_three_button_mouse) &&
+      GetEventClass(eventRef) == kEventClassMouse)
+    {
+      mods &= ~(optionKey | cmdKey);
+    }
   return mac_to_emacs_modifiers (mods);
 }
 
@@ -9111,7 +7128,14 @@ mac_get_mouse_btn (EventRef ref)
   switch (result)
     {
     case kEventMouseButtonPrimary:
-      return 0;
+      if (NILP (Vmac_emulate_three_button_mouse))
+       return 0;
+      else {
+       UInt32 mods = 0;
+       GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
+                          sizeof (UInt32), NULL, &mods);
+       return mac_get_emulated_btn(mods);
+      }
     case kEventMouseButtonSecondary:
       return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
     case kEventMouseButtonTertiary:
@@ -9203,6 +7227,8 @@ do_init_managers (void)
   InitCursor ();
 
 #if !TARGET_API_MAC_CARBON
+  arrow_cursor = &qd.arrow;
+
   /* set up some extra stack space for use by emacs */
   SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
 
@@ -9220,8 +7246,8 @@ do_check_ram_size (void)
 
   if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
       || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
-      || physical_ram_size > 256 * 1024 * 1024
-      || logical_ram_size > 256 * 1024 * 1024)
+      || physical_ram_size > (1 << VALBITS)
+      || logical_ram_size > (1 << VALBITS))
     {
       StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
       exit (1);
@@ -9231,8 +7257,12 @@ 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 (win == tip_window)
+    /* The tooltip has been drawn already.  Avoid the
+       SET_FRAME_GARBAGED below.  */
+    return;
 
   if (f)
     {
@@ -9280,56 +7310,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 ()
 {
+  /* Window-activate events will do the job. */
+#if 0
   WindowPtr wp;
-  mac_output *mwp;
   struct frame *f;
 
-  wp = FrontWindow();
-  if (is_emacs_window (wp))
+  wp = front_emacs_window ();
+  if (wp)
     {
-      mwp = (mac_output *) GetWRefCon (wp);
-      f = mwp->mFP;
+      f = mac_window_to_frame (wp);
 
       if (f)
        {
@@ -9340,20 +7332,21 @@ do_app_resume ()
 
   app_is_suspended = false;
   app_sleep_time = WNE_SLEEP_AT_RESUME;
+#endif
 }
 
 static void
 do_app_suspend ()
 {
+  /* Window-deactivate events will do the job. */
+#if 0
   WindowPtr wp;
-  mac_output *mwp;
   struct frame *f;
 
-  wp = FrontWindow();
-  if (is_emacs_window (wp))
+  wp = front_emacs_window ();
+  if (wp)
     {
-      mwp = (mac_output *) GetWRefCon (wp);
-      f = mwp->mFP;
+      f = mac_window_to_frame (wp);
 
       if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
        {
@@ -9364,71 +7357,43 @@ do_app_suspend ()
 
   app_is_suspended = true;
   app_sleep_time = WNE_SLEEP_AT_SUSPEND;
+#endif
 }
 
 
 static void
-do_mouse_moved (Point mouse_pos)
+do_mouse_moved (mouse_pos, f)
+     Point mouse_pos;
+     FRAME_PTR *f;
 {
-  WindowPtr wp = FrontWindow ();
-  struct frame *f;
+  WindowPtr wp = front_emacs_window ();
+  struct x_display_info *dpyinfo;
 
-  if (is_emacs_window (wp))
+  if (wp)
     {
-      f = ((mac_output *) GetWRefCon (wp))->mFP;
-
-#if TARGET_API_MAC_CARBON
-      SetPort (GetWindowPort (wp));
-#else
-      SetPort (wp);
-#endif
+      *f = mac_window_to_frame (wp);
+      dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
 
-      GlobalToLocal (&mouse_pos);
+      if (dpyinfo->mouse_face_hidden)
+       {
+         dpyinfo->mouse_face_hidden = 0;
+         clear_mouse_face (dpyinfo);
+       }
 
-      note_mouse_movement (f, &mouse_pos);
-    }
-}
+      SetPortWindowPort (wp);
 
+      GlobalToLocal (&mouse_pos);
 
-static void
-do_os_event (EventRecord *erp)
-{
-  switch((erp->message >> 24) & 0x000000FF)
-    {
-    case suspendResumeMessage:
-      if((erp->message & resumeFlag) == 1)
-       do_app_resume ();
+      if (dpyinfo->grabbed && tracked_scroll_bar)
+       x_scroll_bar_note_movement (tracked_scroll_bar,
+                                   mouse_pos.v
+                                   - XINT (tracked_scroll_bar->top),
+                                   TickCount() * (1000 / 60));
       else
-       do_app_suspend ();
-      break;
-
-    case mouseMovedMessage:
-      do_mouse_moved (erp->where);
-      break;
+       note_mouse_movement (*f, &mouse_pos);
     }
 }
 
-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)
@@ -9466,8 +7431,7 @@ do_menu_choice (SInt32 menu_choice)
 
     default:
       {
-        WindowPtr wp = FrontWindow ();
-        struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
+        struct frame *f = mac_window_to_frame (front_emacs_window ());
         MenuHandle menu = GetMenuHandle (menu_id);
         if (menu)
           {
@@ -9492,8 +7456,7 @@ 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;
+  struct frame *f = mac_window_to_frame (w);
 
   SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
 
@@ -9502,8 +7465,8 @@ do_grow_window (WindowPtr w, EventRecord *e)
   /* see if it really changed size */
   if (grow_size != 0)
     {
-      rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
-      columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, HiWord (grow_size));
+      columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, LoWord (grow_size));
 
       x_set_window_size (f, 0, columns, rows);
     }
@@ -9521,46 +7484,43 @@ 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;
+  struct frame *f = mac_window_to_frame (w);
 
-  /* 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 = FRAME_MAC_DISPLAY_INFO (f)->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
-         + CHAR_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)
     {
@@ -9577,14 +7537,21 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
       InsetRect (&zoom_rect, 8, 4);  /* not too tight */
 
       zoom_rect.right = zoom_rect.left
-       + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+       + 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, w == front_emacs_window ());
+
+  SetPort (save_port);
+#endif /* not TARGET_API_MAC_CARBON */
 
   /* retrieve window size and update application values */
 #if TARGET_API_MAC_CARBON
@@ -9592,11 +7559,10 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
 #else
   port_rect = w->portRect;
 #endif
-  rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
-  columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
-  x_set_window_size (mwp->mFP, 0, columns, rows);
-
-  SetPort (save_port);
+  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 (f, 0, columns, rows);
+  x_real_positions (f, &f->left_pos, &f->top_pos);
 }
 
 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
@@ -9925,8 +7891,8 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
     {
       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);
+      SetPortWindowPort (window);
       GlobalToLocal (&mouse);
 
       event.kind = DRAG_N_DROP_EVENT;
@@ -10020,7 +7986,9 @@ main (void)
 
   do_get_menus ();
 
+#ifndef USE_LSB_TAG
   do_check_ram_size ();
+#endif
 
   init_emacs_passwd_dir ();
 
@@ -10098,25 +8066,26 @@ keycode_to_xkeysym (int keyCode, int *xKeySym)
 /* Emacs calls this whenever it wants to read an input event from the
    user. */
 int
-XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
+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 = GetEventDispatcherTarget ();
+#else
+  EventMask event_mask;
 #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;
@@ -10124,9 +8093,6 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  if (numchars <= 0)
-    abort ();
-
   /* 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
@@ -10141,40 +8107,57 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
   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.  */
-  bufp->arg = Qnil;
-
+#if !USE_CARBON_EVENTS
   event_mask = everyEvent;
   if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
     event_mask -= highLevelEventMask;
 
-#if USE_CARBON_EVENTS
-  rneResult = ReceiveNextEvent (0, NULL,
-                               expected
-                               ? TicksToEventTime (app_sleep_time)
-                               : 0,
-                               kEventRemoveFromQueue, &eventRef);
-  if (!rneResult)
+  while (WaitNextEvent (event_mask, &er, 0L, NULL))
+#else /* USE_CARBON_EVENTS */
+  while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
+                           kEventRemoveFromQueue, &eventRef))
+#endif /* USE_CARBON_EVENTS */
     {
+      int do_help = 0;
+      struct frame *f;
+
+      /* 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
       /* Handle new events */
       if (!mac_convert_event_ref (eventRef, &er))
        switch (GetEventClass (eventRef))
          {
+         case kEventClassWindow:
+           if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
+             {
+               WindowPtr window_ptr;
+               GetEventParameter(eventRef, kEventParamDirectObject,
+                                 typeWindowRef, NULL, sizeof(WindowPtr),
+                                 NULL, &window_ptr);
+               f = mac_window_to_frame (window_ptr);
+               if (f && !f->async_iconified)
+                 x_real_positions (f, &f->left_pos, &f->top_pos);
+               SendEventToEventTarget (eventRef, toolbox_dispatcher);
+             }
+           break;
          case kEventClassMouse:
            if (GetEventKind (eventRef) == kEventMouseWheelMoved)
              {
                SInt32 delta;
                Point point;
-               WindowPtr window_ptr = FrontNonFloatingWindow ();
-               struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
+               WindowPtr window_ptr = front_emacs_window ();
+
                if (!IsValidWindowPtr (window_ptr))
                  {
                    SysBeep(1);
-                   UNBLOCK_INPUT;
-                   return 0;
+                   break;
                  }
 
                GetEventParameter(eventRef, kEventParamMouseWheelDelta,
@@ -10183,443 +8166,578 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
                GetEventParameter(eventRef, kEventParamMouseLocation,
                                  typeQDPoint, NULL, sizeof (Point),
                                  NULL, &point);
-               bufp->kind = MOUSE_WHEEL_EVENT;
-               bufp->code = delta;
-               bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
-               SetPort (GetWindowPort (window_ptr));
+               inev.kind = WHEEL_EVENT;
+               inev.code = 0;
+               inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
+                                 | ((delta < 0) ? down_modifier
+                                    : up_modifier));
+               SetPortWindowPort (window_ptr);
                GlobalToLocal (&point);
-               XSETINT (bufp->x, point.h);
-               XSETINT (bufp->y, point.v);
-               XSETFRAME (bufp->frame_or_window, mwp->mFP);
-               bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
-               count++;
+               XSETINT (inev.x, point.h);
+               XSETINT (inev.y, point.v);
+               XSETFRAME (inev.frame_or_window,
+                          mac_window_to_frame (window_ptr));
+               inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
              }
            else
-             SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+             SendEventToEventTarget (eventRef, toolbox_dispatcher);
 
            break;
          default:
            /* Send the event to the appropriate receiver.  */
-           SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+           SendEventToEventTarget (eventRef, toolbox_dispatcher);
          }
       else
-#else
-  if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
 #endif /* USE_CARBON_EVENTS */
-    switch (er.what)
-      {
-      case mouseDown:
-      case mouseUp:
+      switch (er.what)
        {
-         WindowPtr window_ptr = FrontWindow ();
-         SInt16 part_code;
+       case mouseDown:
+       case mouseUp:
+         {
+           WindowPtr window_ptr;
+           SInt16 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 (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
-           break;
-         }
-
-         if (!is_emacs_window(window_ptr))
-           break;
+           /* This is needed to send mouse events like aqua window
+              buttons to the correct handler.  */
+           if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+               != eventNotHandledErr)
+             break;
 #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;
+           if (dpyinfo->grabbed && last_mouse_frame
+               && FRAME_LIVE_P (last_mouse_frame))
+             {
+               window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
+               part_code = inContent;
+             }
+           else
+             {
+               part_code = FindWindow (er.where, &window_ptr);
+               if (tip_window && window_ptr == tip_window)
+                 {
+                   HideWindow (tip_window);
+                   part_code = FindWindow (er.where, &window_ptr);
+                 }
+             }
+
+           if (er.what != mouseDown && part_code != inContent)
+             break;
+
+           switch (part_code)
+             {
+             case inMenuBar:
+               f = mac_window_to_frame (front_emacs_window ());
+               saved_menu_event_location = er.where;
+               inev.kind = MENU_BAR_ACTIVATE_EVENT;
+               XSETFRAME (inev.frame_or_window, f);
+               break;
 
-             /* Convert to local coordinates of new window.  */
+             case inContent:
+               if (window_ptr != front_emacs_window ())
+                 SelectWindow (window_ptr);
+               else
+                 {
+                   SInt16 control_part_code;
+                   ControlHandle ch;
+                   Point mouse_loc = er.where;
+
+                   f = mac_window_to_frame (window_ptr);
+                   /* convert to local coordinates of new window */
+                   SetPortWindowPort (window_ptr);
+
+                   GlobalToLocal (&mouse_loc);
 #if TARGET_API_MAC_CARBON
-              SetPort (GetWindowPort (window_ptr));
+                   ch = FindControlUnderMouse (mouse_loc, window_ptr,
+                                               &control_part_code);
 #else
-              SetPort (window_ptr);
+                   control_part_code = FindControl (mouse_loc, window_ptr,
+                                                    &ch);
 #endif
 
-             GlobalToLocal (&mouse_loc);
-
 #if USE_CARBON_EVENTS
-             bufp->code = mac_get_mouse_btn (eventRef);
+                   inev.code = mac_get_mouse_btn (eventRef);
+                   inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
-             bufp->code = 0;  /* only one mouse button */
+                   inev.code = mac_get_emulated_btn (er.modifiers);
+                   inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
-              bufp->kind = SCROLL_BAR_CLICK_EVENT;
-              bufp->frame_or_window = tracked_scroll_bar->window;
-              bufp->part = scroll_bar_handle;
-#if USE_CARBON_EVENTS
-             bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+                   XSETINT (inev.x, mouse_loc.h);
+                   XSETINT (inev.y, mouse_loc.v);
+                   inev.timestamp = er.when * (1000 / 60);
+                   /* ticks to milliseconds */
+
+                   if (dpyinfo->grabbed && tracked_scroll_bar
+#if TARGET_API_MAC_CARBON
+                       || ch != 0
 #else
-             bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+                       || control_part_code != 0
 #endif
-              bufp->modifiers |= up_modifier;
-             bufp->timestamp = er.when * (1000 / 60);
-               /* ticks to milliseconds */
-
-              XSETINT (bufp->x, tracked_scroll_bar->left + 2);
-              XSETINT (bufp->y, mouse_loc.v - 24);
-              tracked_scroll_bar->dragging = Qnil;
-              mouse_tracking_in_progress = mouse_tracking_none;
-              tracked_scroll_bar = NULL;
-              count++;
-              break;
-            }
+                       )
+                     {
+                       struct scroll_bar *bar;
 
-         part_code = FindWindow (er.where, &window_ptr);
+                       if (dpyinfo->grabbed && tracked_scroll_bar)
+                         {
+                           bar = tracked_scroll_bar;
+                           control_part_code = kControlIndicatorPart;
+                         }
+                       else
+                         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)
+                         tracked_scroll_bar = bar;
+                       else
+                         tracked_scroll_bar = NULL;
+                     }
+                   else
+                     {
+                       Lisp_Object window;
+                       int x = mouse_loc.h;
+                       int y = mouse_loc.v;
 
-         switch (part_code)
-           {
-           case inMenuBar:
-              {
-                struct frame *f = ((mac_output *)
-                                  GetWRefCon (FrontWindow ()))->mFP;
-                saved_menu_event_location = er.where;
-                bufp->kind = MENU_BAR_ACTIVATE_EVENT;
-                XSETFRAME (bufp->frame_or_window, f);
-                count++;
-              }
-             break;
+                       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;
+                         }
+                     }
 
-           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
+                   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);
+                     }
+
+                   switch (er.what)
+                     {
+                     case mouseDown:
+                       inev.modifiers |= down_modifier;
+                       break;
+                     case mouseUp:
+                       inev.modifiers |= up_modifier;
+                       break;
+                     }
+                 }
+               break;
 
-                 GlobalToLocal (&mouse_loc);
+             case inDrag:
 #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
+               DragWindow (window_ptr, er.where, NULL);
+#else /* not TARGET_API_MAC_CARBON */
+               DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
+#endif /* not TARGET_API_MAC_CARBON */
+               /* Update the frame parameters.  */
+               {
+                 struct frame *f = mac_window_to_frame (window_ptr);
+
+                 if (f && !f->async_iconified)
+                   x_real_positions (f, &f->left_pos, &f->top_pos);
+               }
+               break;
+
+             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;
+
+               /* 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
-                 bufp->code = mac_get_mouse_btn (eventRef);
-#else
-                 bufp->code = 0;  /* only one mouse button */
-#endif
-                 XSETINT (bufp->x, mouse_loc.h);
-                 XSETINT (bufp->y, mouse_loc.v);
-                 bufp->timestamp = er.when * (1000 / 60);
-                   /* ticks to milliseconds */
-
-#if TARGET_API_MAC_CARBON
-                 if (ch != 0)
-#else
-                 if (control_part_code != 0)
+         if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+             != eventNotHandledErr)
+           break;
 #endif
-                   {
-                     struct scroll_bar *bar = (struct scroll_bar *)
-                       GetControlReference (ch);
-                     x_scroll_bar_handle_click (bar, control_part_code, &er,
-                                                bufp);
-                     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
-                   {
-                     bufp->kind = MOUSE_CLICK_EVENT;
-                     XSETFRAME (bufp->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;
-                   }
+         do_window_update ((WindowPtr) er.message);
+         break;
 
+       case osEvt:
 #if USE_CARBON_EVENTS
-                 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-                 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+         if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+             != eventNotHandledErr)
+           break;
 #endif
-
-                 switch (er.what)
-                   {
-                   case mouseDown:
-                     bufp->modifiers |= down_modifier;
-                     break;
-                   case mouseUp:
-                     bufp->modifiers |= up_modifier;
-                     break;
-                   }
-
-                 count++;
-               }
+         switch ((er.message >> 24) & 0x000000FF)
+           {
+           case suspendResumeMessage:
+             if ((er.message & resumeFlag) == 1)
+               do_app_resume ();
+             else
+               do_app_suspend ();
              break;
 
-           case inDrag:
-#if TARGET_API_MAC_CARBON
-             {
-               BitMap bm;
+           case mouseMovedMessage:
+             previous_help_echo_string = help_echo_string;
+             help_echo_string = help_echo_object = help_echo_window = Qnil;
+             help_echo_pos = -1;
 
-               GetQDGlobalsScreenBits (&bm);
-               DragWindow (window_ptr, er.where, &bm.bounds);
-             }
-#else /* not TARGET_API_MAC_CARBON */
-             DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
-#endif /* not TARGET_API_MAC_CARBON */
-             break;
+             do_mouse_moved (er.where, &f);
 
-           case inGoAway:
-             if (TrackGoAway (window_ptr, er.where))
-               {
-                 bufp->kind = DELETE_WINDOW_EVENT;
-                 XSETFRAME (bufp->frame_or_window,
-                            ((mac_output *) GetWRefCon (window_ptr))->mFP);
-                 count++;
-               }
+             /* 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;
 
-           /* window resize handling added --ben */
-           case inGrow:
-             do_grow_window(window_ptr, &er);
-             break;
+       case activateEvt:
+         {
+           WindowPtr window_ptr = (WindowPtr) er.message;
 
-           /* window zoom handling added --ben */
-           case inZoomIn:
-           case inZoomOut:
-             if (TrackBox (window_ptr, er.where, part_code))
-               do_zoom_window (window_ptr, part_code);
+#if USE_CARBON_EVENTS
+           if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+               != eventNotHandledErr)
              break;
+#endif
+           if (window_ptr == tip_window)
+             {
+               HideWindow (tip_window);
+               break;
+             }
 
-           default:
+           if (!is_emacs_window (window_ptr))
              break;
-           }
-       }
-       break;
 
-      case updateEvt:
-      case osEvt:
-      case activateEvt:
-#if USE_CARBON_EVENTS
-       if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
-#endif
-       do_events (&er);
-       break;
+           f = mac_window_to_frame (window_ptr);
 
-      case keyDown:
-      case autoKey:
-       {
-         int keycode = (er.message & keyCodeMask) >> 8;
-         int xkeysym;
+           if ((er.modifiers & activeFlag) != 0)
+             {
+               /* A window has been activated */
+               Point mouse_loc = er.where;
+
+               x_new_focus_frame (dpyinfo, f);
+               activate_scroll_bars (f);
+
+               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 */
+               dpyinfo->grabbed = 0;
 
-#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;
-           }
-#endif
+               if (f == dpyinfo->x_focus_frame)
+                 {
+                   x_new_focus_frame (dpyinfo, 0);
+                   deactivate_scroll_bars (f);
+                 }
 
-         if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
-           {
-             SysBeep (1);
-             UNBLOCK_INPUT;
-             return 0;
-           }
 
-         ObscureCursor ();
+               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;
+                 }
 
-         if (keycode_to_xkeysym (keycode, &xkeysym))
-           {
-             bufp->code = 0xff00 | xkeysym;
-             bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-           }
-         else
-           {
-             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;
-                 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
-                                            &some_state) & 0xff;
-               }
-             else
-               bufp->code = er.message & charCodeMask;
-             bufp->kind = ASCII_KEYSTROKE_EVENT;
-           }
-       }
+               /* 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;
 
-       /* 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
-           && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
+       case keyDown:
+       case autoKey:
          {
-           static TECObjectRef converter = NULL;
-           OSStatus the_err = noErr;
-           OSStatus convert_status = noErr;
+           int keycode = (er.message & keyCodeMask) >> 8;
+           int xkeysym;
+
+#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)))
+             if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
+                 != eventNotHandledErr)
+               break;
+#endif
 
-           if (converter ==  NULL)
+#if TARGET_API_MAC_CARBON
+           if (!IsValidWindowPtr (front_emacs_window ()))
              {
-               the_err = TECCreateConverter (&converter,
-                                             kTextEncodingMacRoman,
-                                             mac_keyboard_text_encoding);
-               current_mac_keyboard_text_encoding
-                 = mac_keyboard_text_encoding;
+               SysBeep (1);
+               break;
              }
-           else if (mac_keyboard_text_encoding
-                    != current_mac_keyboard_text_encoding)
+#endif
+
+           ObscureCursor ();
+
+           if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
              {
-               /* 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;
+               clear_mouse_face (dpyinfo);
+               dpyinfo->mouse_face_hidden = 1;
              }
 
-           if (the_err == noErr)
+           if (keycode_to_xkeysym (keycode, &xkeysym))
+             {
+               inev.code = 0xff00 | xkeysym;
+               inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+             }
+           else
              {
-               unsigned char ch = bufp->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)
-                 bufp->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
-       bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
-#else
-       bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
-#endif
+         /* 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;
 
-       {
-         mac_output *mwp
-           = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
-         XSETFRAME (bufp->frame_or_window, mwp->mFP);
-       }
+             if (converter ==  NULL)
+               {
+                 the_err = TECCreateConverter (&converter,
+                                               kTextEncodingMacRoman,
+                                               mac_keyboard_text_encoding);
+                 current_mac_keyboard_text_encoding
+                   = mac_keyboard_text_encoding;
+               }
+             else if (mac_keyboard_text_encoding
+                      != current_mac_keyboard_text_encoding)
+               {
+                 /* Free the converter for the current encoding
+                    before creating a new one.  */
+                 TECDisposeConverter (converter);
+                 the_err = TECCreateConverter (&converter,
+                                               kTextEncodingMacRoman,
+                                               mac_keyboard_text_encoding);
+                 current_mac_keyboard_text_encoding
+                   = mac_keyboard_text_encoding;
+               }
 
-       bufp->timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
+             if (the_err == noErr)
+               {
+                 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;
+               }
+           }
 
-       count++;
-       break;
+#if USE_CARBON_EVENTS
+         inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+         inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+         XSETFRAME (inev.frame_or_window,
+                    mac_window_to_frame (front_emacs_window ()));
+         inev.timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
+         break;
 
-      case kHighLevelEvent:
-        drag_and_drop_file_list = Qnil;
+       case kHighLevelEvent:
+         drag_and_drop_file_list = Qnil;
 
-        AEProcessAppleEvent(&er);
+         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;
+         /* 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 ();
+             wp = front_emacs_window ();
 
-           if (!wp)
-             {
-               struct frame *f = XFRAME (XCAR (Vframe_list));
-               CollapseWindow (FRAME_MAC_WINDOW (f), false);
-               wp = FrontNonFloatingWindow ();
-             }
+             if (!wp)
+               {
+                 struct frame *f = XFRAME (XCAR (Vframe_list));
+                 CollapseWindow (FRAME_MAC_WINDOW (f), false);
+                 wp = front_emacs_window ();
+               }
 
-            if (wp && is_emacs_window(wp))
-               f = ((mac_output *) GetWRefCon (wp))->mFP;
+             if (wp)
+               f = mac_window_to_frame (wp);
 
-            bufp->kind = DRAG_N_DROP_EVENT;
-            bufp->code = 0;
-            bufp->timestamp = er.when * (1000 / 60);
+             inev.kind = DRAG_N_DROP_EVENT;
+             inev.code = 0;
+             inev.timestamp = er.when * (1000 / 60);
              /* ticks to milliseconds */
 #if USE_CARBON_EVENTS
-           bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+             inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
-           bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+             inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
 
-            XSETINT (bufp->x, 0);
-            XSETINT (bufp->y, 0);
+             XSETINT (inev.x, 0);
+             XSETINT (inev.y, 0);
 
-            XSETFRAME (frame, f);
-            bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
+             XSETFRAME (frame, f);
+             inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
 
-            /* Regardless of whether Emacs was suspended or in the
-               foreground, ask it to redraw its entire screen.
-               Otherwise parts of the screen can be left in an
-               inconsistent state.  */
-            if (wp)
+             /* 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;
+               {
+                 Rect r;
 
-               GetWindowPortBounds (wp, &r);
-               InvalWindowRect (wp, &r);
-             }
+                 GetWindowPortBounds (wp, &r);
+                 InvalWindowRect (wp, &r);
+               }
 #else /* not TARGET_API_MAC_CARBON */
-              InvalRect (&(wp->portRect));
+                InvalRect (&(wp->portRect));
 #endif /* not TARGET_API_MAC_CARBON */
-
-            count++;
-          }
-      default:
-       break;
-      }
+           }
+       default:
+         break;
+       }
 #if USE_CARBON_EVENTS
       ReleaseEvent (eventRef);
-    }
 #endif
 
+      if (inev.kind != NO_EVENT)
+       {
+         kbd_buffer_store_event_hold (&inev, hold_quit);
+         count++;
+       }
+
+      if (do_help
+         && !(hold_quit && hold_quit->kind != NO_EVENT))
+       {
+         Lisp_Object frame;
+
+         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++;
+       }
+
+    }
+
   /* If the focus was just given to an autoraising frame,
      raise it now.  */
   /* ??? This ought to be able to handle more than one such frame.  */
@@ -10633,54 +8751,7 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
   check_alarm ();  /* simulate the handling of a SIGALRM */
 #endif
 
-  {
-    static Point old_mouse_pos = { -1, -1 };
-
-    if (app_is_suspended)
-      {
-        old_mouse_pos.h = -1;
-        old_mouse_pos.v = -1;
-      }
-    else
-      {
-        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
-
-           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);
-
-               old_mouse_pos = mouse_pos;
-             }
-         }
-      }
-  }
-
   UNBLOCK_INPUT;
-
   return count;
 }
 
@@ -10708,7 +8779,7 @@ __convert_from_newlines (unsigned char * p, size_t * n)
    ROWS Macintosh window, using font with name FONTNAME and size
    FONTSIZE.  */
 void
-NewMacWindow (FRAME_PTR fp)
+make_mac_frame (FRAME_PTR fp)
 {
   mac_output *mwp;
 #if TARGET_API_MAC_CARBON
@@ -10719,6 +8790,7 @@ NewMacWindow (FRAME_PTR fp)
 
   mwp = fp->output_data.mac;
 
+  BLOCK_INPUT;
   if (making_terminal_window)
     {
       if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
@@ -10727,80 +8799,70 @@ NewMacWindow (FRAME_PTR fp)
       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 */
-
+    {
 #if TARGET_API_MAC_CARBON
-  SetPort (GetWindowPort (mwp->mWP));
+      Rect r;
+
+      SetRect (&r, 0, 0, 1, 1);
+      if (CreateNewWindow (kDocumentWindowClass,
+                          kWindowStandardDocumentAttributes
+                          /* | kWindowToolbarButtonAttribute */,
+                          &r, &mwp->mWP) != noErr)
 #else
-  SetPort (mwp->mWP);
+      if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
 #endif
+       abort ();
+    }
 
-  mwp->fontset = -1;
-
-  SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
-  ShowWindow (mwp->mWP);
+  SetWRefCon (mwp->mWP, (long) mwp);
+    /* so that update events can find this mac_output struct */
+  mwp->mFP = fp;  /* point back to emacs frame */
 
+  SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
+  UNBLOCK_INPUT;
 }
 
 
 void
-make_mac_frame (struct frame *f)
+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));
+
+  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;
 
   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->fontset = -1;
-  f->output_data.mac->scroll_bar_foreground_pixel = -1;
-  f->output_data.mac->scroll_bar_background_pixel = -1;
-  f->output_data.mac->left_pos = 4;
-  f->output_data.mac->top_pos = 4;
-  f->output_data.mac->border_width = 0;
+  FRAME_FONTSET (f) = -1;
   f->output_data.mac->explicit_parent = 0;
+  f->left_pos = 4;
+  f->top_pos = 4;
+  f->border_width = 0;
 
-  f->output_data.mac->internal_border_width = 0;
-
-  f->output_method = output_mac;
+  f->internal_border_width = 0;
 
   f->auto_raise = 1;
   f->auto_lower = 1;
 
-  f->new_width = 0;
-  f->new_height = 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));
-  f->output_data.mac->fontset = -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);
-
-  f->width = 96;
-  f->height = 4;
+  f->new_text_cols = 0;
+  f->new_text_lines = 0;
 
   make_mac_frame (f);
 
@@ -10818,6 +8880,8 @@ make_mac_terminal_frame (struct frame *f)
   Fmodify_frame_parameters (frame,
                             Fcons (Fcons (Qbackground_color,
                                           build_string ("white")), Qnil));
+
+  ShowWindow (f->output_data.mac->mWP);
 }
 
 \f
@@ -10825,74 +8889,6 @@ make_mac_terminal_frame (struct frame *f)
                            Initialization
  ***********************************************************************/
 
-#ifdef USE_X_TOOLKIT
-static XrmOptionDescRec emacs_options[] = {
-  {"-geometry",        ".geometry", XrmoptionSepArg, NULL},
-  {"-iconic",  ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
-
-  {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
-     XrmoptionSepArg, NULL},
-  {"-ib",      "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
-
-  {"-T",       "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
-  {"-wn",      "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
-  {"-title",   "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
-  {"-iconname",        "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
-  {"-in",      "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
-  {"-mc",      "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
-  {"-cr",      "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
-};
-#endif /* USE_X_TOOLKIT */
-
-#ifdef MULTI_KBOARD
-/* Test whether two display-name strings agree up to the dot that separates
-   the screen number from the server number.  */
-static int
-same_x_server (name1, name2)
-     char *name1, *name2;
-{
-  int seen_colon = 0;
-  unsigned char *system_name = SDATA (Vsystem_name);
-  int system_name_length = strlen (system_name);
-  int length_until_period = 0;
-
-  while (system_name[length_until_period] != 0
-        && system_name[length_until_period] != '.')
-    length_until_period++;
-
-  /* Treat `unix' like an empty host name.  */
-  if (! strncmp (name1, "unix:", 5))
-    name1 += 4;
-  if (! strncmp (name2, "unix:", 5))
-    name2 += 4;
-  /* Treat this host's name like an empty host name.  */
-  if (! strncmp (name1, system_name, system_name_length)
-      && name1[system_name_length] == ':')
-    name1 += system_name_length;
-  if (! strncmp (name2, system_name, system_name_length)
-      && name2[system_name_length] == ':')
-    name2 += system_name_length;
-  /* Treat this host's domainless name like an empty host name.  */
-  if (! strncmp (name1, system_name, length_until_period)
-      && name1[length_until_period] == ':')
-    name1 += length_until_period;
-  if (! strncmp (name2, system_name, length_until_period)
-      && name2[length_until_period] == ':')
-    name2 += length_until_period;
-
-  for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
-    {
-      if (*name1 == ':')
-       seen_colon++;
-      if (seen_colon && *name1 == '.')
-       return 1;
-    }
-  return (seen_colon
-         && (*name1 == '.' || *name1 == '\0')
-         && (*name2 == '.' || *name2 == '\0'));
-}
-#endif
-
 int mac_initialized = 0;
 
 void
@@ -10925,17 +8921,42 @@ mac_initialize_display_info ()
   dpyinfo->reference_count = 0;
   dpyinfo->resx = 75.0;
   dpyinfo->resy = 75.0;
-  dpyinfo->n_planes = 1;
-  dpyinfo->n_cbits = 16;
+  dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
+#ifdef MAC_OSX
+  /* HasDepth returns true if it is possible to have a 32 bit display,
+     but this may not be what is actually used.  Mac OSX can do better.
+     CGMainDisplayID is only available on OSX 10.2 and higher, but the
+     header for CGGetActiveDisplayList says that the first display returned
+     is the active one, so we use that.  */
+  {
+    CGDirectDisplayID disp_id[1];
+    CGDisplayCount disp_count;
+    CGDisplayErr error_code;
+
+    error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
+    if (error_code != 0)
+      error ("No display found, CGGetActiveDisplayList error %d", error_code);
+
+    dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
+  }
+#else
+  for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
+    if (HasDepth (main_device_handle, dpyinfo->n_planes,
+                 gdDevType, dpyinfo->color_p))
+      break;
+#endif
   dpyinfo->height = (**main_device_handle).gdRect.bottom;
   dpyinfo->width = (**main_device_handle).gdRect.right;
   dpyinfo->grabbed = 0;
   dpyinfo->root_window = NULL;
+  dpyinfo->image_cache = make_image_cache ();
 
   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
   dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
   dpyinfo->mouse_face_window = Qnil;
+  dpyinfo->mouse_face_overlay = Qnil;
+  dpyinfo->mouse_face_hidden = 0;
 }
 
 struct mac_display_info *
@@ -11062,34 +9083,49 @@ quit_char_comp (EventRef inEvent, void *inCompData)
 }
 
 void
-mac_check_for_quit_char()
+mac_check_for_quit_char ()
 {
   EventRef event;
-  /* If windows are not initialized, return immediately (keep it bouncin')*/
+  static EMACS_TIME last_check_time = { 0, 0 };
+  static EMACS_TIME one_second = { 1, 0 };
+  EMACS_TIME now, t;
+
+  /* If windows are not initialized, return immediately (keep it bouncin').  */
   if (!mac_quit_char_modifiers)
     return;
 
+  /* Don't check if last check is less than a second ago.  */
+  EMACS_GET_TIME (now);
+  EMACS_SUB_TIME (t, now, last_check_time);
+  if (EMACS_TIME_LT (t, one_second))
+    return;
+  last_check_time = now;
+
   /* Redetermine modifiers because they are based on lisp variables */
-  mac_determine_quit_char_modifiers();
+  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);
+  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);
+      e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
+      XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
       /* Remove event from queue to prevent looping. */
-      RemoveEventFromQueue(GetMainEventQueue(), event);
-      ReleaseEvent(event);
-      kbd_buffer_store_event(&e);
+      RemoveEventFromQueue (GetMainEventQueue (), event);
+      ReleaseEvent (event);
+      kbd_buffer_store_event (&e);
     }
 }
 
@@ -11097,8 +9133,11 @@ mac_check_for_quit_char()
 
 /* Set up use of X before we make the first connection.  */
 
+extern frame_parm_handler mac_frame_parm_handlers[];
+
 static struct redisplay_interface x_redisplay_interface =
 {
+  mac_frame_parm_handlers,
   x_produce_glyphs,
   x_write_glyphs,
   x_insert_glyphs,
@@ -11107,16 +9146,24 @@ static struct redisplay_interface x_redisplay_interface =
   x_after_update_window_line,
   x_update_window_begin,
   x_update_window_end,
-  XTcursor_to,
+  x_cursor_to,
   x_flush,
-  x_clear_mouse_face,
+  x_flush,
+  x_clear_window_mouse_face,
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
   x_draw_fringe_bitmap,
+  0, /* define_fringe_bitmap */
+  0, /* destroy_fringe_bitmap */
   mac_per_char_metric,
   mac_encode_char,
   NULL, /* mac_compute_glyph_string_overhangs */
-  x_draw_glyph_string
+  x_draw_glyph_string,
+  mac_define_frame_cursor,
+  mac_clear_frame_area,
+  mac_draw_window_cursor,
+  mac_draw_vertical_window_border,
+  mac_shift_glyphs_for_insert
 };
 
 void
@@ -11144,8 +9191,6 @@ mac_initialize ()
   redeem_scroll_bar_hook = XTredeem_scroll_bar;
   judge_scroll_bars_hook = XTjudge_scroll_bars;
 
-  estimate_mode_line_height_hook = x_estimate_mode_line_height;
-
   scroll_region_ok = 1;         /* we'll scroll partial frames */
   char_ins_del_ok = 1;
   line_ins_del_ok = 1;          /* we'll just blt 'em */
@@ -11197,6 +9242,7 @@ mac_initialize ()
   signal (SIGPIPE, x_connection_signal);
 #endif
 
+  BLOCK_INPUT;
   mac_initialize_display_info ();
 
 #if TARGET_API_MAC_CARBON
@@ -11215,6 +9261,7 @@ mac_initialize ()
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
+  UNBLOCK_INPUT;
 }
 
 
@@ -11226,8 +9273,19 @@ 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));
+
   Fprovide (intern ("mac-carbon"), Qnil);
 
+  staticpro (&Qreverse);
+  Qreverse = intern ("reverse");
+
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
 
@@ -11243,39 +9301,33 @@ syms_of_macterm ()
   Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
   staticpro (&Qmac_ready_for_drag_n_drop);
 
-  help_echo = Qnil;
-  staticpro (&help_echo);
-  help_echo_object = Qnil;
-  staticpro (&help_echo_object);
-  help_echo_window = Qnil;
-  staticpro (&help_echo_window);
-  previous_help_echo = Qnil;
-  staticpro (&previous_help_echo);
-  help_echo_pos = -1;
+  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_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
-    doc: /* *Non-nil means draw block 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.  */);
-  x_stretch_cursor_p = 0;
+  DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
+              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
+  Vx_toolkit_scroll_bars = Qt;
 
-#if 0 /* TODO: Setting underline position from font properties.  */
   DEFVAR_BOOL ("x-use-underline-position-properties",
-              &x_use_underline_position_properties,
-    doc: /* *Non-nil means make use of UNDERLINE_POSITION font 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 = 1;
-#endif
-
-  DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
-              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
-  Vx_toolkit_scroll_bars = Qt;
+  x_use_underline_position_properties = 0;
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
@@ -11285,11 +9337,28 @@ 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.  */);
   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. */);
+  Vmac_emulate_three_button_mouse = Qnil;
+
 #if USE_CARBON_EVENTS
   DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
    doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
@@ -11323,3 +9392,6 @@ command, this enables the Mac keyboard to be used to enter non-ASCII
 characters directly.  */);
   mac_keyboard_text_encoding = kTextEncodingMacRoman;
 }
+
+/* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
+   (do not change this comment) */