Merged in changes from CVS HEAD
[bpt/emacs.git] / src / xdisp.c
index 5665720..675aa69 100644 (file)
@@ -1,5 +1,5 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985,86,87,88,93,94,95,97,98,99, 2000, 2001, 2002, 2003
+   Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -179,6 +179,7 @@ Boston, MA 02111-1307, USA.  */
 #include "charset.h"
 #include "indent.h"
 #include "commands.h"
+#include "keymap.h"
 #include "macros.h"
 #include "disptab.h"
 #include "termhooks.h"
@@ -187,6 +188,7 @@ Boston, MA 02111-1307, USA.  */
 #include "process.h"
 #include "region-cache.h"
 #include "fontset.h"
+#include "blockinput.h"
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
@@ -196,6 +198,12 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #ifdef MAC_OS
 #include "macterm.h"
+
+Cursor No_Cursor;
+#endif
+
+#ifndef FRAME_X_OUTPUT
+#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
 #endif
 
 #define INFINITY 10000000
@@ -219,6 +227,7 @@ extern Lisp_Object Voverriding_local_map;
 extern Lisp_Object Voverriding_local_map_menu_flag;
 extern Lisp_Object Qmenu_item;
 extern Lisp_Object Qwhen;
+extern Lisp_Object Qhelp_echo;
 
 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
@@ -233,6 +242,9 @@ Lisp_Object Qbuffer_position, Qposition, Qobject;
 /* Cursor shapes */
 Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
 
+/* Pointer shapes */
+Lisp_Object Qarrow, Qhand, Qtext;
+
 Lisp_Object Qrisky_local_variable;
 
 /* Holds the list (error).  */
@@ -243,6 +255,10 @@ Lisp_Object list_of_error;
 Lisp_Object Vfontification_functions;
 Lisp_Object Qfontification_functions;
 
+/* Non-zero means automatically select any window when the mouse
+   cursor moves into it.  */
+int mouse_autoselect_window;
+
 /* Non-zero means draw tool bar buttons raised when the mouse moves
    over them.  */
 
@@ -261,6 +277,12 @@ EMACS_INT tool_bar_button_relief;
 
 int auto_resize_tool_bars_p;
 
+/* 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-nil means don't actually do any redisplay.  */
 
 Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
@@ -271,21 +293,29 @@ int inhibit_eval_during_redisplay;
 
 /* Names of text properties relevant for redisplay.  */
 
-Lisp_Object Qdisplay, Qrelative_width, Qalign_to;
+Lisp_Object Qdisplay;
 extern Lisp_Object Qface, Qinvisible, Qwidth;
 
 /* Symbols used in text property values.  */
 
+Lisp_Object Vdisplay_pixels_per_inch;
 Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
 Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
-Lisp_Object Qmargin;
+Lisp_Object Qmargin, Qpointer;
 extern Lisp_Object Qheight;
 extern Lisp_Object QCwidth, QCheight, QCascent;
+extern Lisp_Object Qscroll_bar;
 
 /* Non-nil means highlight trailing whitespace.  */
 
 Lisp_Object Vshow_trailing_whitespace;
 
+/* Non-nil means show the text cursor in void text areas
+   i.e. in blank areas after eol and eob.  This used to be
+   the default in 21.3.  */
+
+Lisp_Object Vvoid_text_area_pointer;
+
 /* Name of the face used to highlight trailing whitespace.  */
 
 Lisp_Object Qtrailing_whitespace;
@@ -295,6 +325,10 @@ Lisp_Object Qtrailing_whitespace;
 
 Lisp_Object Qimage;
 
+/* The image map types.  */
+Lisp_Object QCmap, QCpointer;
+Lisp_Object Qrect, Qcircle, Qpoly;
+
 /* Non-zero means print newline to stdout before next mini-buffer
    message.  */
 
@@ -405,8 +439,8 @@ static EMACS_INT scroll_conservatively;
 
 /* Recenter the window whenever point gets within this many lines of
    the top or bottom of the window.  This value is translated into a
-   pixel value by multiplying it with CANON_Y_UNIT, which means that
-   there is really a fixed pixel height scroll margin.  */
+   pixel value by multiplying it with FRAME_LINE_HEIGHT, which means
+   that there is really a fixed pixel height scroll margin.  */
 
 EMACS_INT scroll_margin;
 
@@ -708,10 +742,6 @@ enum move_it_result
 #define CLEAR_FACE_CACHE_COUNT 500
 static int clear_face_cache_count;
 
-/* Record the previous terminal frame we displayed.  */
-
-static struct frame *previous_terminal_frame;
-
 /* Non-zero while redisplay_internal is in progress.  */
 
 int redisplaying_p;
@@ -723,6 +753,19 @@ int redisplaying_p;
 int inhibit_free_realized_faces;
 Lisp_Object Qinhibit_free_realized_faces;
 
+/* If a string, XTread_socket generates an event to display that string.
+   (The display is done in read_char.)  */
+
+Lisp_Object help_echo_string;
+Lisp_Object help_echo_window;
+Lisp_Object help_echo_object;
+int help_echo_pos;
+
+/* Temporary variable for XTread_socket.  */
+
+Lisp_Object previous_help_echo_string;
+
+
 \f
 /* Function prototypes.  */
 
@@ -740,6 +783,7 @@ static int invisible_text_between_p P_ ((struct it *, int, int));
 
 static int next_element_from_ellipsis P_ ((struct it *));
 static void pint2str P_ ((char *, int, int));
+static void pint2hrstr P_ ((char *, int, int));
 static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
                                                        struct text_pos));
 static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
@@ -781,6 +825,7 @@ static int message_log_check_duplicate P_ ((int, int, int, int));
 static void push_it P_ ((struct it *));
 static void pop_it P_ ((struct it *));
 static void sync_frame_with_window_matrix_rows P_ ((struct window *));
+static void select_frame_for_redisplay P_ ((Lisp_Object));
 static void redisplay_internal P_ ((int));
 static int echo_area_display P_ ((int));
 static void redisplay_windows P_ ((Lisp_Object));
@@ -857,6 +902,11 @@ static void update_tool_bar P_ ((struct frame *, int));
 static void build_desired_tool_bar_string P_ ((struct frame *f));
 static int redisplay_tool_bar P_ ((struct frame *));
 static void display_tool_bar_line P_ ((struct it *));
+static void notice_overwritten_cursor P_ ((struct window *,
+                                          enum glyph_row_area,
+                                          int, int, int, int));
+
+
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -875,15 +925,13 @@ INLINE int
 window_text_bottom_y (w)
      struct window *w;
 {
-  struct frame *f = XFRAME (w->frame);
-  int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+  int height = WINDOW_TOTAL_HEIGHT (w);
 
   if (WINDOW_WANTS_MODELINE_P (w))
     height -= CURRENT_MODE_LINE_HEIGHT (w);
   return height;
 }
 
-
 /* Return the pixel width of display area AREA of window W.  AREA < 0
    means return the total width of W, not including fringes to
    the left and right of the window.  */
@@ -893,29 +941,36 @@ window_box_width (w, area)
      struct window *w;
      int area;
 {
-  struct frame *f = XFRAME (w->frame);
-  int width = XFASTINT (w->width);
+  int cols = XFASTINT (w->total_cols);
+  int pixels = 0;
 
   if (!w->pseudo_window_p)
     {
-      width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FRINGE_COLS (f);
+      cols -= WINDOW_SCROLL_BAR_COLS (w);
 
       if (area == TEXT_AREA)
        {
-         if (INTEGERP (w->left_margin_width))
-           width -= XFASTINT (w->left_margin_width);
-         if (INTEGERP (w->right_margin_width))
-           width -= XFASTINT (w->right_margin_width);
+         if (INTEGERP (w->left_margin_cols))
+           cols -= XFASTINT (w->left_margin_cols);
+         if (INTEGERP (w->right_margin_cols))
+           cols -= XFASTINT (w->right_margin_cols);
+         pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
        }
       else if (area == LEFT_MARGIN_AREA)
-       width = (INTEGERP (w->left_margin_width)
-                ? XFASTINT (w->left_margin_width) : 0);
+       {
+         cols = (INTEGERP (w->left_margin_cols)
+                  ? XFASTINT (w->left_margin_cols) : 0);
+         pixels = 0;
+       }
       else if (area == RIGHT_MARGIN_AREA)
-       width = (INTEGERP (w->right_margin_width)
-                ? XFASTINT (w->right_margin_width) : 0);
+       {
+         cols = (INTEGERP (w->right_margin_cols)
+                  ? XFASTINT (w->right_margin_cols) : 0);
+         pixels = 0;
+       }
     }
 
-  return width * CANON_X_UNIT (f);
+  return cols * WINDOW_FRAME_COLUMN_WIDTH (w) + pixels;
 }
 
 
@@ -927,7 +982,7 @@ window_box_height (w)
      struct window *w;
 {
   struct frame *f = XFRAME (w->frame);
-  int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+  int height = WINDOW_TOTAL_HEIGHT (w);
 
   xassert (height >= 0);
 
@@ -966,6 +1021,51 @@ window_box_height (w)
   return max (0, height);
 }
 
+/* Return the window-relative coordinate of the left edge of display
+   area AREA of window W.  AREA < 0 means return the left edge of the
+   whole window, to the right of the left fringe of W.  */
+
+INLINE int
+window_box_left_offset (w, area)
+     struct window *w;
+     int area;
+{
+  int x;
+
+  if (w->pseudo_window_p)
+    return 0;
+
+  x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
+
+  if (area == TEXT_AREA)
+    x += (WINDOW_LEFT_FRINGE_WIDTH (w)
+         + window_box_width (w, LEFT_MARGIN_AREA));
+  else if (area == RIGHT_MARGIN_AREA)
+    x += (WINDOW_LEFT_FRINGE_WIDTH (w)
+         + window_box_width (w, LEFT_MARGIN_AREA)
+         + window_box_width (w, TEXT_AREA)
+         + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+            ? 0
+            : WINDOW_RIGHT_FRINGE_WIDTH (w)));
+  else if (area == LEFT_MARGIN_AREA
+          && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
+    x += WINDOW_LEFT_FRINGE_WIDTH (w);
+
+  return x;
+}
+
+
+/* Return the window-relative coordinate of the right edge of display
+   area AREA of window W.  AREA < 0 means return the left edge of the
+   whole window, to the left of the right fringe of W.  */
+
+INLINE int
+window_box_right_offset (w, area)
+     struct window *w;
+     int area;
+{
+  return window_box_left_offset (w, area) + window_box_width (w, area);
+}
 
 /* Return the frame-relative coordinate of the left edge of display
    area AREA of window W.  AREA < 0 means return the left edge of the
@@ -977,19 +1077,13 @@ window_box_left (w, area)
      int area;
 {
   struct frame *f = XFRAME (w->frame);
-  int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
+  int x;
 
-  if (!w->pseudo_window_p)
-    {
-      x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
-           + FRAME_LEFT_FRINGE_WIDTH (f));
+  if (w->pseudo_window_p)
+    return FRAME_INTERNAL_BORDER_WIDTH (f);
 
-      if (area == TEXT_AREA)
-       x += window_box_width (w, LEFT_MARGIN_AREA);
-      else if (area == RIGHT_MARGIN_AREA)
-       x += (window_box_width (w, LEFT_MARGIN_AREA)
-             + window_box_width (w, TEXT_AREA));
-    }
+  x = (WINDOW_LEFT_EDGE_X (w)
+       + window_box_left_offset (w, area));
 
   return x;
 }
@@ -1007,7 +1101,6 @@ window_box_right (w, area)
   return window_box_left (w, area) + window_box_width (w, area);
 }
 
-
 /* Get the bounding box of the display area AREA of window W, without
    mode lines, in frame-relative coordinates.  AREA < 0 means the
    whole window, not including the left and right fringes of
@@ -1021,15 +1114,18 @@ window_box (w, area, box_x, box_y, box_width, box_height)
      int area;
      int *box_x, *box_y, *box_width, *box_height;
 {
-  struct frame *f = XFRAME (w->frame);
-
-  *box_width = window_box_width (w, area);
-  *box_height = window_box_height (w);
-  *box_x = window_box_left (w, area);
-  *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
-           + XFASTINT (w->top) * CANON_Y_UNIT (f));
-  if (WINDOW_WANTS_HEADER_LINE_P (w))
-    *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
+  if (box_width)
+    *box_width = window_box_width (w, area);
+  if (box_height)
+    *box_height = window_box_height (w);
+  if (box_x)
+    *box_x = window_box_left (w, area);
+  if (box_y)
+    {
+      *box_y = WINDOW_TOP_EDGE_Y (w);
+      if (WINDOW_WANTS_HEADER_LINE_P (w))
+       *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
+    }
 }
 
 
@@ -1147,7 +1243,7 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
     {
       int top_y = it.current_y;
       int bottom_y = line_bottom_y (&it);
-      int window_top_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
 
       if (top_y < window_top_y)
        visible_p = bottom_y > window_top_y;
@@ -1332,6 +1428,351 @@ compute_string_pos (newpos, pos, string)
     BYTEPOS (*newpos) = CHARPOS (*newpos);
 }
 
+/* EXPORT:
+   Return an estimation of the pixel height of mode or top lines on
+   frame F.  FACE_ID specifies what line's height to estimate.  */
+
+int
+estimate_mode_line_height (f, face_id)
+     struct frame *f;
+     enum face_id face_id;
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (f))
+    {
+      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;
+    }
+#endif
+
+  return 1;
+}
+
+/* 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;
+     int *x, *y;
+     NativeRectangle *bounds;
+     int noclip;
+{
+
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (f))
+    {
+      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to round down
+        even for negative values.  */
+      if (pix_x < 0)
+       pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
+      if (pix_y < 0)
+       pix_y -= FRAME_LINE_HEIGHT (f) - 1;
+
+      pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
+      pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
+
+      if (bounds)
+       STORE_NATIVE_RECT (*bounds,
+                          FRAME_COL_TO_PIXEL_X (f, pix_x),
+                          FRAME_LINE_TO_PIXEL_Y (f, pix_y),
+                          FRAME_COLUMN_WIDTH (f) - 1,
+                          FRAME_LINE_HEIGHT (f) - 1);
+
+      if (!noclip)
+       {
+         if (pix_x < 0)
+           pix_x = 0;
+         else if (pix_x > FRAME_TOTAL_COLS (f))
+           pix_x = FRAME_TOTAL_COLS (f);
+
+         if (pix_y < 0)
+           pix_y = 0;
+         else if (pix_y > FRAME_LINES (f))
+           pix_y = FRAME_LINES (f);
+       }
+    }
+#endif
+
+  *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;
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))))
+    {
+      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]);
+
+         hpos = row->x;
+         vpos = row->y;
+         while (glyph < end)
+           {
+             hpos += glyph->pixel_width;
+             ++glyph;
+           }
+
+         /* If first glyph is partially visible, its first visible position is still 0.  */
+         if (hpos < 0)
+           hpos = 0;
+
+         success_p = 1;
+       }
+      else
+       {
+         hpos = vpos = 0;
+         success_p = 0;
+       }
+
+      *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, hpos);
+      *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, vpos);
+      return success_p;
+    }
+#endif
+
+  *frame_x = hpos;
+  *frame_y = vpos;
+  return 1;
+}
+
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* 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, dx, dy, area)
+     struct window *w;
+     int x, y;
+     int *hpos, *vpos, *dx, *dy, *area;
+{
+  struct glyph *glyph, *end;
+  struct glyph_row *row = NULL;
+  int x0, i;
+
+  /* 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
+    {
+      if (x < window_box_left_offset (w, TEXT_AREA))
+       {
+         *area = LEFT_MARGIN_AREA;
+         x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
+       }
+      else if (x < window_box_right_offset (w, TEXT_AREA))
+       {
+         *area = TEXT_AREA;
+         x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
+       }
+      else
+       {
+         *area = RIGHT_MARGIN_AREA;
+         x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
+       }
+    }
+
+  /* Find glyph containing X.  */
+  glyph = row->glyphs[*area];
+  end = glyph + row->used[*area];
+  x -= x0;
+  while (glyph < end && x >= glyph->pixel_width)
+    {
+      x -= glyph->pixel_width;
+      ++glyph;
+    }
+
+  if (glyph == end)
+    return NULL;
+
+  if (dx)
+    {
+      *dx = x;
+      *dy = y - (row->y + row->ascent - glyph->ascent);
+    }
+
+  *hpos = glyph - row->glyphs[*area];
+  return glyph;
+}
+
+
+/* EXPORT:
+   Convert frame-relative x/y to coordinates relative to window W.
+   Takes pseudo-windows into account.  */
+
+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 (f);
+      *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
+    }
+  else
+    {
+      *x -= WINDOW_LEFT_EDGE_X (w);
+      *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
+    }
+}
+
+/* EXPORT:
+   Return in *R the clipping rectangle for glyph string S.  */
+
+void
+get_glyph_string_clip_rect (s, nr)
+     struct glyph_string *s;
+     NativeRectangle *nr;
+{
+  XRectangle r;
+
+  if (s->row->full_width_p)
+    {
+      /* Draw full-width.  X coordinates are relative to S->w->left_col.  */
+      r.x = WINDOW_LEFT_EDGE_X (s->w);
+      r.width = WINDOW_TOTAL_WIDTH (s->w);
+
+      /* 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.x = window_box_left (s->w, s->area);
+      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.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
+      r.height = window_text_bottom_y (s->w) - r.y;
+    }
+  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.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
+      else
+       r.y = 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.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
+    }
+
+  r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
+
+  /* If drawing the cursor, don't let glyph draw outside its
+     advertised boundaries. Cleartype does this under some circumstances.  */
+  if (s->hl == DRAW_CURSOR)
+    {
+      struct glyph *glyph = s->first_glyph;
+      int height;
+
+      if (s->x > r.x)
+       {
+         r.width -= s->x - r.x;
+         r.x = s->x;
+       }
+      r.width = min (r.width, glyph->pixel_width);
+
+      /* Don't draw cursor glyph taller than our actual glyph.  */
+      height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
+      if (height < r.height)
+       {
+         r.y = s->ybase + glyph->descent - height;
+         r.height = height;
+       }
+    }
+
+#ifdef CONVERT_FROM_XRECT
+  CONVERT_FROM_XRECT (r, *nr);
+#else
+  *nr = r;
+#endif
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
 
 \f
 /***********************************************************************
@@ -1566,7 +2007,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   XSETWINDOW (it->window, w);
   it->w = w;
   it->f = XFRAME (w->frame);
-
+  
   /* Extra space between lines (on window systems only).  */
   if (base_face_id == DEFAULT_FACE_ID
       && FRAME_WINDOW_P (it->f))
@@ -1579,13 +2020,9 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
 
   /* If realized faces have been removed, e.g. because of face
      attribute changes of named faces, recompute them.  When running
-     in batch mode, the face cache of Vterminal_frame is null.  If
+     in batch mode, the face cache of the initial frame is null.  If
      we happen to get called, make a dummy face cache.  */
-  if (
-#ifndef WINDOWSNT
-      noninteractive &&
-#endif
-      FRAME_FACE_CACHE (it->f) == NULL)
+  if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
     init_frame_faces (it->f);
   if (FRAME_FACE_CACHE (it->f)->used == 0)
     recompute_basic_faces (it->f);
@@ -1703,12 +2140,12 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
     {
       /* Mode lines, menu bar in terminal frames.  */
       it->first_visible_x = 0;
-      it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
+      it->last_visible_x = WINDOW_TOTAL_WIDTH (w);
     }
   else
     {
       it->first_visible_x
-       = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
+       = XFASTINT (it->w->hscroll) * FRAME_COLUMN_WIDTH (it->f);
       it->last_visible_x = (it->first_visible_x
                            + window_box_width (w, TEXT_AREA));
 
@@ -1725,7 +2162,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
        }
 
       it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
-      it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
+      it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
     }
 
   /* Leave room for a border glyph.  */
@@ -1764,6 +2201,8 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
       else
        IT_BYTEPOS (*it) = bytepos;
 
+      it->start = it->current;
+
       /* Compute faces etc.  */
       reseat (it, it->current.pos, 1);
     }
@@ -1785,6 +2224,7 @@ start_display (it, w, pos)
 
   row = w->desired_matrix->rows + first_vpos;
   init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
+  it->first_vpos = first_vpos;
 
   if (!it->truncate_lines_p)
     {
@@ -2026,6 +2466,7 @@ init_to_row_start (it, w, row)
      struct glyph_row *row;
 {
   init_from_display_pos (it, w, &row->start);
+  it->start = row->start;
   it->continuation_lines_width = row->continuation_lines_width;
   CHECK_IT (it);
 }
@@ -3182,7 +3623,9 @@ single_display_prop_intangible_p (prop)
        return 0;
     }
 
-  return CONSP (prop) && EQ (XCAR (prop), Qimage);
+  return (CONSP (prop)
+         && (EQ (XCAR (prop), Qimage)
+             || EQ (XCAR (prop), Qspace)));
 }
 
 
@@ -3566,7 +4009,8 @@ load_overlay_strings (it, charpos)
      int charpos;
 {
   extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
-  Lisp_Object ov, overlay, window, str, invisible;
+  Lisp_Object overlay, window, str, invisible;
+  struct Lisp_Overlay *ov;
   int start, end;
   int size = 20;
   int n = 0, i, j, invis_p;
@@ -3606,9 +4050,9 @@ load_overlay_strings (it, charpos)
   while (0)
 
   /* Process overlay before the overlay center.  */
-  for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
+  for (ov = current_buffer->overlays_before; ov; ov = ov->next)
     {
-      overlay = XCAR (ov);
+      XSETMISC (overlay, ov);
       xassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -3646,9 +4090,9 @@ load_overlay_strings (it, charpos)
     }
 
   /* Process overlays after the overlay center.  */
-  for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
+  for (ov = current_buffer->overlays_after; ov; ov = ov->next)
     {
-      overlay = XCAR (ov);
+      XSETMISC (overlay, ov);
       xassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -4116,6 +4560,13 @@ reseat_1 (it, pos, set_stop_p)
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
   it->method = next_element_from_buffer;
+  /* RMS: I added this to fix a bug in move_it_vertically_backward
+     where it->area continued to relate to the starting point
+     for the backward motion.  Bug report from
+     Nick Roberts <nick@nick.uklinux.net> on 19 May 2003.
+     However, I am not sure whether reseat still does the right thing
+     in general after this change.  */
+  it->area = TEXT_AREA;
   it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
   it->sp = 0;
   it->face_before_selective_p = 0;
@@ -5410,7 +5861,7 @@ move_it_vertically_backward (it, dy)
   xassert (dy >= 0);
 
   /* Estimate how many newlines we must move back.  */
-  nlines = max (1, dy / CANON_Y_UNIT (it->f));
+  nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
 
   /* Set the iterator's position that many lines back.  */
   while (nlines-- && IT_CHARPOS (*it) > BEGV)
@@ -5439,10 +5890,14 @@ move_it_vertically_backward (it, dy)
 
   move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
   xassert (IT_CHARPOS (*it) >= BEGV);
+  /* H is the actual vertical distance from the position in *IT
+     and the starting position.  */
   h = it2.current_y - it->current_y;
+  /* NLINES is the distance in number of lines.  */
   nlines = it2.vpos - it->vpos;
 
-  /* Correct IT's y and vpos position.  */
+  /* Correct IT's y and vpos position
+     so that they are relative to the starting point.  */
   it->vpos -= nlines;
   it->current_y -= h;
 
@@ -5454,10 +5909,10 @@ move_it_vertically_backward (it, dy)
        move_it_by_lines (it, nlines, 1);
       xassert (IT_CHARPOS (*it) <= start_pos);
     }
-  else if (nlines)
+  else
     {
-      /* The y-position we try to reach.  Note that h has been
-         subtracted in front of the if-statement.  */
+      /* The y-position we try to reach, relative to *IT.
+        Note that H has been subtracted in front of the if-statement.  */
       int target_y = it->current_y + h - dy;
       int y0 = it3.current_y;
       int y1 = line_bottom_y (&it3);
@@ -5872,9 +6327,9 @@ message_dolog (m, nbytes, nlflag, multibyte)
                          XMARKER (oldpoint)->bytepos);
 
       UNGCPRO;
-      unchain_marker (oldpoint);
-      unchain_marker (oldbegv);
-      unchain_marker (oldzv);
+      unchain_marker (XMARKER (oldpoint));
+      unchain_marker (XMARKER (oldbegv));
+      unchain_marker (XMARKER (oldzv));
 
       tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
       set_buffer_internal (oldbuf);
@@ -6002,8 +6457,8 @@ message2_nolog (m, nbytes, multibyte)
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (frame_up_to_date_hook != 0 && ! gc_in_progress)
-       (*frame_up_to_date_hook) (f);
+      if (FRAME_DISPLAY (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+       (*FRAME_DISPLAY (f)->frame_up_to_date_hook) (f);
     }
 }
 
@@ -6088,8 +6543,8 @@ message3_nolog (m, nbytes, multibyte)
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (frame_up_to_date_hook != 0 && ! gc_in_progress)
-       (*frame_up_to_date_hook) (f);
+      if (FRAME_DISPLAY (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+       (*FRAME_DISPLAY (f)->frame_up_to_date_hook) (f);
     }
 }
 
@@ -6710,16 +7165,16 @@ resize_mini_window (w, exact_p)
 
   /* Nil means don't try to resize.  */
   if (NILP (Vresize_mini_windows)
-      || (FRAME_X_P (f) && f->output_data.x == NULL))
+      || (FRAME_X_P (f) && FRAME_X_OUTPUT (f) == NULL))
     return 0;
 
   if (!FRAME_MINIBUF_ONLY_P (f))
     {
       struct it it;
       struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
-      int total_height = XFASTINT (root->height) + XFASTINT (w->height);
+      int total_height = WINDOW_TOTAL_LINES (root) + WINDOW_TOTAL_LINES (w);
       int height, max_height;
-      int unit = CANON_Y_UNIT (f);
+      int unit = FRAME_LINE_HEIGHT (f);
       struct text_pos start;
       struct buffer *old_current_buffer = NULL;
 
@@ -6733,7 +7188,7 @@ resize_mini_window (w, exact_p)
 
       /* Compute the max. number of lines specified by the user.  */
       if (FLOATP (Vmax_mini_window_height))
-       max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_HEIGHT (f);
+       max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_LINES (f);
       else if (INTEGERP (Vmax_mini_window_height))
        max_height = XINT (Vmax_mini_window_height);
       else
@@ -6774,45 +7229,45 @@ resize_mini_window (w, exact_p)
        {
          /* Let it grow only, until we display an empty message, in which
             case the window shrinks again.  */
-         if (height > XFASTINT (w->height))
+         if (height > WINDOW_TOTAL_LINES (w))
            {
-             int old_height = XFASTINT (w->height);
+             int old_height = WINDOW_TOTAL_LINES (w);
              freeze_window_starts (f, 1);
-             grow_mini_window (w, height - XFASTINT (w->height));
-             window_height_changed_p = XFASTINT (w->height) != old_height;
+             grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
+             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
-         else if (height < XFASTINT (w->height)
+         else if (height < WINDOW_TOTAL_LINES (w)
                   && (exact_p || BEGV == ZV))
            {
-             int old_height = XFASTINT (w->height);
+             int old_height = WINDOW_TOTAL_LINES (w);
              freeze_window_starts (f, 0);
              shrink_mini_window (w);
-             window_height_changed_p = XFASTINT (w->height) != old_height;
+             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
        }
       else
        {
          /* Always resize to exact size needed.  */
-         if (height > XFASTINT (w->height))
+         if (height > WINDOW_TOTAL_LINES (w))
            {
-             int old_height = XFASTINT (w->height);
+             int old_height = WINDOW_TOTAL_LINES (w);
              freeze_window_starts (f, 1);
-             grow_mini_window (w, height - XFASTINT (w->height));
-             window_height_changed_p = XFASTINT (w->height) != old_height;
+             grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
+             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
-         else if (height < XFASTINT (w->height))
+         else if (height < WINDOW_TOTAL_LINES (w))
            {
-             int old_height = XFASTINT (w->height);
+             int old_height = WINDOW_TOTAL_LINES (w);
              freeze_window_starts (f, 0);
              shrink_mini_window (w);
 
              if (height)
                {
                  freeze_window_starts (f, 1);
-                 grow_mini_window (w, height - XFASTINT (w->height));
+                 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
                }
 
-             window_height_changed_p = XFASTINT (w->height) != old_height;
+             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
        }
 
@@ -7112,11 +7567,11 @@ clear_garbaged_frames ()
     {
       Lisp_Object tail, frame;
       int changed_count = 0;
-
+      
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
-
+         
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
              if (f->resized_p)
@@ -7127,7 +7582,7 @@ clear_garbaged_frames ()
              f->resized_p = 0;
            }
        }
-
+      
       frame_garbaged = 0;
       if (changed_count)
        ++windows_or_buffers_changed;
@@ -7160,11 +7615,11 @@ echo_area_display (update_frame_p)
 /* The terminal frame is used as the first Emacs frame on the Mac OS.  */
 #ifndef MAC_OS8
 #ifdef HAVE_WINDOW_SYSTEM
-  /* When Emacs starts, selected_frame may be a visible terminal
-     frame, even if we run under a window system.  If we let this
-     through, a message would be displayed on the terminal.  */
-  if (EQ (selected_frame, Vterminal_frame)
-      && !NILP (Vwindow_system))
+  /* When Emacs starts, selected_frame may be the initial terminal
+     frame.  If we let this through, a message would be displayed on
+     the terminal.  */
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame))
+      && FRAME_TTY (XFRAME (selected_frame))->type == NULL)
     return 0;
 #endif /* HAVE_WINDOW_SYSTEM */
 #endif
@@ -7215,7 +7670,7 @@ echo_area_display (update_frame_p)
                 Can do with a display update of the echo area,
                 unless we displayed some mode lines.  */
              update_single_window (w, 1);
-             rif->flush_display (f);
+             FRAME_RIF (f)->flush_display (f);
            }
          else
            update_frame (f, 1, 1);
@@ -7613,46 +8068,130 @@ update_menu_bar (f, save_match_data)
 
 \f
 /***********************************************************************
-                              Tool-bars
+                           Output Cursor
  ***********************************************************************/
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-/* Update the tool-bar item list for frame F.  This has to be done
-   before we start to fill in any display lines.  Called from
-   prepare_menu_bars.  If SAVE_MATCH_DATA is non-zero, we must save
-   and restore it here.  */
+/* EXPORT:
+   Nominal cursor position -- where to draw output.
+   HPOS and VPOS are window relative glyph matrix coordinates.
+   X and Y are window relative pixel coordinates.  */
 
-static void
-update_tool_bar (f, save_match_data)
-     struct frame *f;
-     int save_match_data;
+struct cursor_pos output_cursor;
+
+
+/* EXPORT:
+   Set the global variable output_cursor to CURSOR.  All cursor
+   positions are relative to updated_window.  */
+
+void
+set_output_cursor (cursor)
+    struct cursor_pos *cursor;
 {
-#ifdef USE_GTK
-  int do_update = FRAME_EXTERNAL_TOOL_BAR(f);
-#else
-  int do_update = WINDOWP (f->tool_bar_window)
-    && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0;
-#endif
+  output_cursor.hpos = cursor->hpos;
+  output_cursor.vpos = cursor->vpos;
+  output_cursor.x = cursor->x;
+  output_cursor.y = cursor->y;
+}
 
-  if (do_update)
-    {
-      Lisp_Object window;
-      struct window *w;
 
-      window = FRAME_SELECTED_WINDOW (f);
-      w = XWINDOW (window);
+/* EXPORT for RIF:
+   Set a nominal cursor position.
 
-      /* If the user has switched buffers or windows, we need to
-        recompute to reflect the new bindings.  But we'll
-        recompute when update_mode_lines is set too; that means
-        that people can use force-mode-line-update to request
-        that the menu bar be recomputed.  The adverse effect on
-        the rest of the redisplay algorithm is about the same as
-        windows_or_buffers_changed anyway.  */
-      if (windows_or_buffers_changed
-         || !NILP (w->update_mode_line)
-         || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
+   HPOS and VPOS are column/row positions in a window glyph matrix.  X
+   and Y are window text area relative pixel positions.
+
+   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.  */
+
+void
+x_cursor_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;
+      display_and_set_cursor (w, 1, hpos, vpos, x, y);
+      if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
+       FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ());
+      UNBLOCK_INPUT;
+    }
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+\f
+/***********************************************************************
+                              Tool-bars
+ ***********************************************************************/
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Where the mouse was last time we reported a mouse event.  */
+
+FRAME_PTR last_mouse_frame;
+
+/* Tool-bar item index of the item on which a mouse button was pressed
+   or -1.  */
+
+int last_tool_bar_item;
+
+
+/* Update the tool-bar item list for frame F.  This has to be done
+   before we start to fill in any display lines.  Called from
+   prepare_menu_bars.  If SAVE_MATCH_DATA is non-zero, we must save
+   and restore it here.  */
+
+static void
+update_tool_bar (f, save_match_data)
+     struct frame *f;
+     int save_match_data;
+{
+#ifdef USE_GTK
+  int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
+#else
+  int do_update = WINDOWP (f->tool_bar_window)
+    && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
+#endif
+
+  if (do_update)
+    {
+      Lisp_Object window;
+      struct window *w;
+
+      window = FRAME_SELECTED_WINDOW (f);
+      w = XWINDOW (window);
+
+      /* If the user has switched buffers or windows, we need to
+        recompute to reflect the new bindings.  But we'll
+        recompute when update_mode_lines is set too; that means
+        that people can use force-mode-line-update to request
+        that the menu bar be recomputed.  The adverse effect on
+        the rest of the redisplay algorithm is about the same as
+        windows_or_buffers_changed anyway.  */
+      if (windows_or_buffers_changed
+         || !NILP (w->update_mode_line)
+         || update_mode_lines
+         || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
               < BUF_MODIFF (XBUFFER (w->buffer)))
              != !NILP (w->last_had_star))
          || ((!NILP (Vtransient_mark_mode)
@@ -7661,6 +8200,8 @@ update_tool_bar (f, save_match_data)
        {
          struct buffer *prev = current_buffer;
          int count = SPECPDL_INDEX ();
+         Lisp_Object old_tool_bar;
+         struct gcpro gcpro1;
 
          /* Set current_buffer to the buffer of the selected
             window of the frame, so that we get the right local
@@ -7678,12 +8219,20 @@ update_tool_bar (f, save_match_data)
              specbind (Qoverriding_local_map, Qnil);
            }
 
+         old_tool_bar = f->tool_bar_items;
+         GCPRO1 (old_tool_bar);
+
          /* Build desired tool-bar items from keymaps.  */
+          BLOCK_INPUT;
          f->tool_bar_items
            = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
+          UNBLOCK_INPUT;
 
-         /* Redisplay the tool-bar in case we changed it.  */
-         w->update_mode_line = Qt;
+         /* Redisplay the tool-bar if we changed it.  */
+         if (! NILP (Fequal (old_tool_bar, f->tool_bar_items)))
+           w->update_mode_line = Qt;
+         
+         UNGCPRO;
 
          unbind_to (count, Qnil);
          set_buffer_internal_1 (prev);
@@ -7739,7 +8288,7 @@ build_desired_tool_bar_string (f)
       int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
       int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
       int hmargin, vmargin, relief, idx, end;
-      extern Lisp_Object QCrelief, QCmargin, QCconversion, Qimage;
+      extern Lisp_Object QCrelief, QCmargin, QCconversion;
 
       /* If image is a vector, choose the image according to the
         button state.  */
@@ -7956,7 +8505,7 @@ tool_bar_lines_needed (f)
      F->desired_tool_bar_string in the tool-bar window of frame F.  */
   init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
-  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
 
   while (!ITERATOR_AT_END_P (&it))
@@ -7966,7 +8515,7 @@ tool_bar_lines_needed (f)
       display_tool_bar_line (&it);
     }
 
-  return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
+  return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
 }
 
 
@@ -7988,7 +8537,7 @@ DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
 
   if (WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
-         XFASTINT (w->height) > 0))
+         WINDOW_TOTAL_LINES (w) > 0))
     {
       update_tool_bar (f, 1);
       if (f->n_tool_bar_items)
@@ -8015,7 +8564,7 @@ redisplay_tool_bar (f)
   int change_height_p = 0;
 
 #ifdef USE_GTK
-  if (FRAME_EXTERNAL_TOOL_BAR(f))
+  if (FRAME_EXTERNAL_TOOL_BAR (f))
     update_frame_tool_bar (f);
   return 0;
 #endif
@@ -8026,13 +8575,13 @@ redisplay_tool_bar (f)
      can turn off tool-bars by specifying tool-bar-lines zero.  */
   if (!WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
-          XFASTINT (w->height) == 0))
+          WINDOW_TOTAL_LINES (w) == 0))
     return 0;
 
   /* Set up an iterator for the tool-bar window.  */
   init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
-  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
   row = it.glyph_row;
 
   /* Build a string that represents the contents of the tool-bar.  */
@@ -8059,10 +8608,10 @@ redisplay_tool_bar (f)
 
       /* If there are blank lines at the end, except for a partially
         visible blank line at the end that is smaller than
-        CANON_Y_UNIT, change the tool-bar's height.  */
+        FRAME_LINE_HEIGHT, change the tool-bar's height.  */
       row = it.glyph_row - 1;
       if (!row->displays_text_p
-         && row->height >= CANON_Y_UNIT (f))
+         && row->height >= FRAME_LINE_HEIGHT (f))
        change_height_p = 1;
 
       /* If row displays tool-bar items, but is partially visible,
@@ -8075,11 +8624,11 @@ redisplay_tool_bar (f)
         frame parameter.  */
       if (change_height_p
          && (nlines = tool_bar_lines_needed (f),
-             nlines != XFASTINT (w->height)))
+             nlines != WINDOW_TOTAL_LINES (w)))
        {
          extern Lisp_Object Qtool_bar_lines;
          Lisp_Object frame;
-         int old_height = XFASTINT (w->height);
+         int old_height = WINDOW_TOTAL_LINES (w);
 
          XSETFRAME (frame, f);
          clear_glyph_matrix (w->desired_matrix);
@@ -8087,7 +8636,7 @@ redisplay_tool_bar (f)
                                    Fcons (Fcons (Qtool_bar_lines,
                                                  make_number (nlines)),
                                           Qnil));
-         if (XFASTINT (w->height) != old_height)
+         if (WINDOW_TOTAL_LINES (w) != old_height)
            fonts_changed_p = 1;
        }
     }
@@ -8101,7 +8650,7 @@ redisplay_tool_bar (f)
    properties start in F->tool_bar_items.  Value is zero if
    GLYPH doesn't display a tool-bar item.  */
 
-int
+static int
 tool_bar_item_info (f, glyph, prop_idx)
      struct frame *f;
      struct glyph *glyph;
@@ -8133,6 +8682,209 @@ tool_bar_item_info (f, glyph, prop_idx)
   return success_p;
 }
 
+\f
+/* 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->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
+get_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;
+{
+  Display_Info *dpyinfo = FRAME_X_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, 0, 0, &area);
+  if (*glyph == NULL)
+    return -1;
+
+  /* Get the start of this tool-bar item's properties in
+     f->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;
+}
+
+
+/* EXPORT:
+   Handle mouse button event on the tool-bar of frame F, at
+   frame-relative coordinates X/Y.  DOWN_P is 1 for a button press,
+   0 for button release.  MODIFIERS is event modifiers for button
+   release.  */
+
+void
+handle_tool_bar_click (f, x, y, down_p, modifiers)
+     struct frame *f;
+     int x, y, down_p;
+     unsigned int modifiers;
+{
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct window *w = XWINDOW (f->tool_bar_window);
+  int hpos, vpos, prop_idx;
+  struct glyph *glyph;
+  Lisp_Object enabled_p;
+
+  /* If not on the highlighted tool-bar item, return.  */
+  frame_to_window_pixel_xy (w, &x, &y);
+  if (get_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 (down_p)
+    {
+      /* 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;
+      EVENT_INIT (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 = 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);
+  Display_Info *dpyinfo = FRAME_X_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 = get_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 in 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_string 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_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
+  if (NILP (help_echo_string))
+    help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
+}
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 
@@ -8225,41 +8977,46 @@ draw_fringe_bitmap (w, row, which, left_p)
   p.bx = -1;
   if (left_p)
     {
-      if (p.wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
-       p.wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
-      p.x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-            - p.wd
-            - (FRAME_X_LEFT_FRINGE_WIDTH (f) - p.wd) / 2);
-      if (p.wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > p.h)
+      int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
+      int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                                  ? LEFT_MARGIN_AREA
+                                  : TEXT_AREA));
+      if (p.wd > wd)
+       p.wd = wd;
+      p.x = x - p.wd - (wd - p.wd) / 2;
+
+      if (p.wd < wd || row->height > p.h)
        {
          /* If W has a vertical border to its left, don't draw over it.  */
-         int border = ((XFASTINT (w->left) > 0
-                        && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-                       ? 1 : 0);
-         p.bx = (window_box_left (w, -1)
-                 - FRAME_X_LEFT_FRINGE_WIDTH (f)
-                 + border);
-         p.nx = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
+         wd -= ((!WINDOW_LEFTMOST_P (w)
+                 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+                ? 1 : 0);
+         p.bx = x - wd;
+         p.nx = wd;
        }
     }
   else
     {
-      if (p.wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
-       p.wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
-      p.x = (window_box_right (w, -1)
-            + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - p.wd) / 2);
+      int x = window_box_right (w,
+                               (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                                ? RIGHT_MARGIN_AREA
+                                : TEXT_AREA));
+      int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
+      if (p.wd > wd)
+       p.wd = wd;
+      p.x = x + (wd - p.wd) / 2;
       /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
         the fringe.  */
-      if (p.wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > p.h)
+      if (p.wd < wd || row->height > p.h)
        {
-         p.bx = window_box_right (w, -1);
-         p.nx = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+         p.bx = x;
+         p.nx = wd;
        }
     }
 
   if (p.bx >= 0)
     {
-      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
 
       p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
       p.ny = row->visible_height;
@@ -8268,7 +9025,7 @@ draw_fringe_bitmap (w, row, which, left_p)
   /* Adjust y to the offset in the row to start drawing the bitmap.  */
   p.y += (row->height - p.h) / 2;
 
-  rif->draw_fringe_bitmap (w, row, &p);
+  FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
 }
 
 /* Draw fringe bitmaps for glyph row ROW on window W.  Call this
@@ -8279,7 +9036,6 @@ draw_row_fringe_bitmaps (w, row)
      struct window *w;
      struct glyph_row *row;
 {
-  struct frame *f = XFRAME (w->frame);
   enum fringe_bitmap_type bitmap;
 
   xassert (interrupt_input_blocked);
@@ -8289,7 +9045,7 @@ draw_row_fringe_bitmaps (w, row)
   if (row->visible_height <= 0)
     return;
 
-  if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
+  if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
     {
       /* Decide which bitmap to draw in the left fringe.  */
       if (row->overlay_arrow_p)
@@ -8306,14 +9062,14 @@ draw_row_fringe_bitmaps (w, row)
       draw_fringe_bitmap (w, row, bitmap, 1);
     }
 
-  if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
+  if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
     {
       /* Decide which bitmap to draw in the right fringe.  */
       if (row->truncated_on_right_p)
        bitmap = RIGHT_TRUNCATION_BITMAP;
       else if (row->continued_p)
        bitmap = CONTINUED_LINE_BITMAP;
-      else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
+      else if (row->indicate_empty_line_p && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
        bitmap = ZV_LINE_BITMAP;
       else
        bitmap = NO_FRINGE_BITMAP;
@@ -8323,16 +9079,31 @@ draw_row_fringe_bitmaps (w, row)
 }
 
 
-/* Compute actual fringe widths */
+/* Compute actual fringe widths for frame F.  
+
+   If REDRAW is 1, redraw F if the fringe settings was actually
+   modified and F is visible.
+
+   Since the combined left and right fringe must occupy an integral
+   number of columns, we may need to add some pixels to each fringe.
+   Typically, we add an equal amount (+/- 1 pixel) to each fringe,
+   but a negative width value is taken literally (after negating it).
+
+   We never make the fringes narrower than specified.  It is planned
+   to make fringe bitmaps customizable and expandable, and at that
+   time, the user will typically specify the minimum number of pixels
+   needed for his bitmaps, so we shouldn't select anything less than
+   what is specified.
+*/
 
 void
 compute_fringe_widths (f, redraw)
      struct frame *f;
      int redraw;
 {
-  int o_left = FRAME_X_LEFT_FRINGE_WIDTH (f);
-  int o_right = FRAME_X_RIGHT_FRINGE_WIDTH (f);
-  int o_cols = FRAME_X_FRINGE_COLS (f);
+  int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
+  int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
+  int o_cols = FRAME_FRINGE_COLS (f);
 
   Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
   Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
@@ -8353,7 +9124,7 @@ compute_fringe_widths (f, redraw)
       int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
       int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
       int conf_wid = left_wid + right_wid;
-      int font_wid = FONT_WIDTH (FRAME_FONT (f));
+      int font_wid = FRAME_COLUMN_WIDTH (f);
       int cols = (left_wid + right_wid + font_wid-1) / font_wid;
       int real_wid = cols * font_wid;
       if (left_wid && right_wid)
@@ -8361,14 +9132,14 @@ compute_fringe_widths (f, redraw)
          if (left_fringe_width < 0)
            {
              /* Left fringe width is fixed, adjust right fringe if necessary */
-             FRAME_X_LEFT_FRINGE_WIDTH (f) = left_wid;
-             FRAME_X_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
+             FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
+             FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
            }
          else if (right_fringe_width < 0)
            {
              /* Right fringe width is fixed, adjust left fringe if necessary */
-             FRAME_X_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
-             FRAME_X_RIGHT_FRINGE_WIDTH (f) = right_wid;
+             FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
+             FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
            }
          else
            {
@@ -8376,35 +9147,33 @@ compute_fringe_widths (f, redraw)
                 Note that we are doing integer arithmetic here, so don't
                 lose a pixel if the total width is an odd number.  */
              int fill = real_wid - conf_wid;
-             FRAME_X_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
-             FRAME_X_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
+             FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
+             FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
            }
        }
       else if (left_fringe_width)
        {
-         FRAME_X_LEFT_FRINGE_WIDTH (f) = real_wid;
-         FRAME_X_RIGHT_FRINGE_WIDTH (f) = 0;
+         FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
+         FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
        }
       else
        {
-         FRAME_X_LEFT_FRINGE_WIDTH (f) = 0;
-         FRAME_X_RIGHT_FRINGE_WIDTH (f) = real_wid;
+         FRAME_LEFT_FRINGE_WIDTH (f) = 0;
+         FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
        }
-      FRAME_X_FRINGE_COLS (f) = cols;
-      FRAME_X_FRINGE_WIDTH (f) = real_wid;
+      FRAME_FRINGE_COLS (f) = cols;
     }
   else
     {
-      FRAME_X_LEFT_FRINGE_WIDTH (f) = 0;
-      FRAME_X_RIGHT_FRINGE_WIDTH (f) = 0;
-      FRAME_X_FRINGE_COLS (f) = 0;
-      FRAME_X_FRINGE_WIDTH (f) = 0;
+      FRAME_LEFT_FRINGE_WIDTH (f) = 0;
+      FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
+      FRAME_FRINGE_COLS (f) = 0;
     }
 
   if (redraw && FRAME_VISIBLE_P (f))
-    if (o_left != FRAME_X_LEFT_FRINGE_WIDTH (f) ||
-       o_right != FRAME_X_RIGHT_FRINGE_WIDTH (f) ||
-       o_cols != FRAME_X_FRINGE_COLS (f))
+    if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
+       o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
+       o_cols != FRAME_FRINGE_COLS (f))
       redraw_frame (f);
 }
 
@@ -8462,8 +9231,8 @@ hscroll_window_tree (window)
        hscrolled_p |= hscroll_window_tree (w->vchild);
       else if (w->cursor.vpos >= 0)
        {
-         int h_margin, text_area_x, text_area_y;
-         int text_area_width, text_area_height;
+         int h_margin;
+         int text_area_width;
          struct glyph_row *current_cursor_row
            = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
          struct glyph_row *desired_cursor_row
@@ -8473,11 +9242,10 @@ hscroll_window_tree (window)
               ? desired_cursor_row
               : current_cursor_row);
 
-         window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
-                     &text_area_width, &text_area_height);
+         text_area_width = window_box_width (w, TEXT_AREA);
 
          /* Scroll when cursor is inside this scroll margin.  */
-         h_margin = hscroll_margin * CANON_X_UNIT (XFRAME (w->frame));
+         h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
 
          if ((XFASTINT (w->hscroll)
               && w->cursor.x <= h_margin)
@@ -8514,7 +9282,7 @@ hscroll_window_tree (window)
              /* Position cursor in window.  */
              if (!hscroll_relative_p && hscroll_step_abs == 0)
                hscroll = max (0, it.current_x - text_area_width / 2)
-                         / CANON_X_UNIT (it.f);
+                         / FRAME_COLUMN_WIDTH (it.f);
              else if (w->cursor.x >= text_area_width - h_margin)
                {
                  if (hscroll_relative_p)
@@ -8522,10 +9290,10 @@ hscroll_window_tree (window)
                               - h_margin;
                  else
                    wanted_x = text_area_width
-                              - hscroll_step_abs * CANON_X_UNIT (it.f)
+                              - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
                               - h_margin;
                  hscroll
-                   = max (0, it.current_x - wanted_x) / CANON_X_UNIT (it.f);
+                   = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
                }
              else
                {
@@ -8533,10 +9301,10 @@ hscroll_window_tree (window)
                    wanted_x = text_area_width * hscroll_step_rel
                               + h_margin;
                  else
-                   wanted_x = hscroll_step_abs * CANON_X_UNIT (it.f)
+                   wanted_x = hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
                               + h_margin;
                  hscroll
-                   = max (0, it.current_x - wanted_x) / CANON_X_UNIT (it.f);
+                   = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
                }
              hscroll = max (hscroll, XFASTINT (w->min_hscroll));
 
@@ -8800,6 +9568,44 @@ reconsider_clip_changes (w, b)
     }
 }
 \f
+
+/* Select FRAME to forward the values of frame-local variables into C
+   variables so that the redisplay routines can access those values
+   directly.  */
+
+static void
+select_frame_for_redisplay (frame)
+     Lisp_Object frame;
+{
+  Lisp_Object tail, sym, val;
+  Lisp_Object old = selected_frame;
+
+  selected_frame = frame;
+
+  for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
+    if (CONSP (XCAR (tail))
+       && (sym = XCAR (XCAR (tail)),
+           SYMBOLP (sym))
+       && (sym = indirect_variable (sym),
+           val = SYMBOL_VALUE (sym),
+           (BUFFER_LOCAL_VALUEP (val)
+            || SOME_BUFFER_LOCAL_VALUEP (val)))
+       && XBUFFER_LOCAL_VALUE (val)->check_frame)
+      Fsymbol_value (sym);
+
+  for (tail = XFRAME (old)->param_alist; CONSP (tail); tail = XCDR (tail))
+    if (CONSP (XCAR (tail))
+       && (sym = XCAR (XCAR (tail)),
+           SYMBOLP (sym))
+       && (sym = indirect_variable (sym),
+           val = SYMBOL_VALUE (sym),
+           (BUFFER_LOCAL_VALUEP (val)
+            || SOME_BUFFER_LOCAL_VALUEP (val)))
+       && XBUFFER_LOCAL_VALUE (val)->check_frame)
+      Fsymbol_value (sym);
+}
+
+
 #define STOP_POLLING                                   \
 do { if (! polling_stopped_here) stop_polling ();      \
        polling_stopped_here = 1; } while (0)
@@ -8865,7 +9671,8 @@ redisplay_internal (preserve_echo_area)
   /* Record a function that resets redisplaying_p to its old value
      when we leave this function.  */
   count = SPECPDL_INDEX ();
-  record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
+  record_unwind_protect (unwind_redisplay,
+                        Fcons (make_number (redisplaying_p), selected_frame));
   ++redisplaying_p;
   specbind (Qinhibit_free_realized_faces, Qnil);
 
@@ -8888,17 +9695,16 @@ redisplay_internal (preserve_echo_area)
   if (face_change_count)
     ++windows_or_buffers_changed;
 
-  if (! FRAME_WINDOW_P (sf)
-      && previous_terminal_frame != sf)
+  if (FRAME_TERMCAP_P (sf)
+      && FRAME_TTY (sf)->previous_terminal_frame != sf)
     {
-      /* Since frames on an ASCII terminal share the same display
-        area, displaying a different frame means redisplay the whole
-        thing.  */
+      /* Since frames on a single ASCII terminal share the same
+        display area, displaying a different frame means redisplay
+        the whole thing.  */
       windows_or_buffers_changed++;
       SET_FRAME_GARBAGED (sf);
-      XSETFRAME (Vterminal_frame, sf);
+      FRAME_TTY (sf)->previous_terminal_frame = sf;
     }
-  previous_terminal_frame = sf;
 
   /* Set the visible flags for all frames.  Do this before checking
      for resized or garbaged frames; they want to know if their frames
@@ -8920,6 +9726,7 @@ redisplay_internal (preserve_echo_area)
       }
   }
 
+  
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
 
@@ -9185,7 +9992,7 @@ redisplay_internal (preserve_echo_area)
               /* Make sure the cursor was last displayed
                  in this window.  Otherwise we have to reposition it.  */
               && 0 <= w->cursor.vpos
-              && XINT (w->height) > w->cursor.vpos)
+              && WINDOW_TOTAL_LINES (w) > w->cursor.vpos)
        {
          if (!must_finish)
            {
@@ -9277,8 +10084,13 @@ redisplay_internal (preserve_echo_area)
        {
          struct frame *f = XFRAME (frame);
 
-         if (FRAME_WINDOW_P (f) || f == sf)
+         if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
+             if (! EQ (frame, selected_frame))
+               /* Select the frame, for the sake of frame-local
+                  variables.  */
+               select_frame_for_redisplay (frame);
+
 #ifdef HAVE_WINDOW_SYSTEM
              if (clear_face_cache_count % 50 == 0
                  && FRAME_WINDOW_P (f))
@@ -9287,16 +10099,16 @@ redisplay_internal (preserve_echo_area)
 
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
-             if (condemn_scroll_bars_hook)
-               condemn_scroll_bars_hook (f);
+             if (FRAME_DISPLAY (f)->condemn_scroll_bars_hook)
+               FRAME_DISPLAY (f)->condemn_scroll_bars_hook (f);
 
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                redisplay_windows (FRAME_ROOT_WINDOW (f));
 
              /* Any scroll bars which redisplay_windows should have
                 nuked should now go away.  */
-             if (judge_scroll_bars_hook)
-               judge_scroll_bars_hook (f);
+             if (FRAME_DISPLAY (f)->judge_scroll_bars_hook)
+               FRAME_DISPLAY (f)->judge_scroll_bars_hook (f);
 
              /* If fonts changed, display again.  */
              /* ??? rms: I suspect it is a mistake to jump all the way
@@ -9321,8 +10133,10 @@ redisplay_internal (preserve_echo_area)
                  /* Update the display.  */
                  set_window_update_flags (XWINDOW (f->root_window), 1);
                  pause |= update_frame (f, 0, 0);
+#if 0  /* Exiting the loop can leave the wrong value for buffer_shared.  */
                  if (pause)
                    break;
+#endif
 
                  if (n == size)
                    {
@@ -9337,15 +10151,18 @@ redisplay_internal (preserve_echo_area)
            }
        }
 
-      /* Do the mark_window_display_accurate after all windows have
-        been redisplayed because this call resets flags in buffers
-        which are needed for proper redisplay.  */
-      for (i = 0; i < n; ++i)
+      if (!pause)
        {
-         struct frame *f = updated[i];
-         mark_window_display_accurate (f->root_window, 1);
-         if (frame_up_to_date_hook)
-           frame_up_to_date_hook (f);
+         /* Do the mark_window_display_accurate after all windows have
+            been redisplayed because this call resets flags in buffers
+            which are needed for proper redisplay.  */
+         for (i = 0; i < n; ++i)
+           {
+             struct frame *f = updated[i];
+             mark_window_display_accurate (f->root_window, 1);
+             if (FRAME_DISPLAY (f)->frame_up_to_date_hook)
+               FRAME_DISPLAY (f)->frame_up_to_date_hook (f);
+           }
        }
     }
   else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
@@ -9433,8 +10250,8 @@ redisplay_internal (preserve_echo_area)
          last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
          last_arrow_string = Voverlay_arrow_string;
 
-         if (frame_up_to_date_hook != 0)
-           frame_up_to_date_hook (sf);
+         if (FRAME_DISPLAY (sf)->frame_up_to_date_hook != 0)
+           FRAME_DISPLAY (sf)->frame_up_to_date_hook (sf);
        }
 
       update_mode_lines = 0;
@@ -9526,13 +10343,20 @@ redisplay_preserve_echo_area (from_where)
 /* Function registered with record_unwind_protect in
    redisplay_internal.  Reset redisplaying_p to the value it had
    before redisplay_internal was called, and clear
-   prevent_freeing_realized_faces_p.  */
+   prevent_freeing_realized_faces_p.  It also selects the previously
+   selected frame.  */
 
 static Lisp_Object
-unwind_redisplay (old_redisplaying_p)
-     Lisp_Object old_redisplaying_p;
+unwind_redisplay (val)
+     Lisp_Object val;
 {
+  Lisp_Object old_redisplaying_p, old_frame;
+
+  old_redisplaying_p = XCAR (val);
   redisplaying_p = XFASTINT (old_redisplaying_p);
+  old_frame = XCDR (val);
+  if (! EQ (old_frame, selected_frame))
+    select_frame_for_redisplay (old_frame);
   return Qnil;
 }
 
@@ -9587,7 +10411,7 @@ mark_window_display_accurate_1 (w, accurate_p)
       w->window_end_valid = w->buffer;
 #if 0 /* This is incorrect with variable-height lines.  */
       xassert (XINT (w->window_end_vpos)
-              < (XINT (w->height)
+              < (WINDOW_TOTAL_LINES (w)
                  - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
 #endif
       w->update_mode_line = Qnil;
@@ -10050,8 +10874,8 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
      within this distance from the top or bottom of the window.  */
   if (scroll_margin > 0)
     {
-      this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
-      this_scroll_margin *= CANON_Y_UNIT (f);
+      this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+      this_scroll_margin *= FRAME_LINE_HEIGHT (f);
     }
   else
     this_scroll_margin = 0;
@@ -10069,7 +10893,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
     scroll_max = 10;
   else
     scroll_max = 0;
-  scroll_max *= CANON_Y_UNIT (f);
+  scroll_max *= FRAME_LINE_HEIGHT (f);
 
   /* Decide whether we have to scroll down.  Start at the window end
      and move this_scroll_margin up to find the position of the scroll
@@ -10120,15 +10944,14 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
        /* Set AMOUNT_TO_SCROLL to at least one line,
           and at most scroll_conservatively lines.  */
        amount_to_scroll
-         = min (max (dy, CANON_Y_UNIT (f)),
-                CANON_Y_UNIT (f) * scroll_conservatively);
+         = min (max (dy, FRAME_LINE_HEIGHT (f)),
+                FRAME_LINE_HEIGHT (f) * scroll_conservatively);
       else if (scroll_step || temp_scroll_step)
        amount_to_scroll = scroll_max;
       else
        {
          aggressive = current_buffer->scroll_up_aggressively;
-         height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
-                   - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
+         height = WINDOW_BOX_TEXT_HEIGHT (w);
          if (NUMBERP (aggressive))
            amount_to_scroll = XFLOATINT (aggressive) * height;
        }
@@ -10180,14 +11003,13 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
          if (scroll_conservatively)
            amount_to_scroll =
-             max (dy, CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step));
+             max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
          else if (scroll_step || temp_scroll_step)
            amount_to_scroll = scroll_max;
          else
            {
              aggressive = current_buffer->scroll_down_aggressively;
-             height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
-                       - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
+             height = WINDOW_BOX_TEXT_HEIGHT (w);
              if (NUMBERP (aggressive))
                amount_to_scroll = XFLOATINT (aggressive) * height;
            }
@@ -10277,7 +11099,7 @@ compute_window_start_on_continuation_line (w)
       /* If the line start is "too far" away from the window start,
          say it takes too much time to compute a new window start.  */
       if (CHARPOS (start_pos) - IT_CHARPOS (it)
-         < XFASTINT (w->height) * XFASTINT (w->width))
+         < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
        {
          int min_distance, distance;
 
@@ -10395,8 +11217,8 @@ try_cursor_movement (window, startp, scroll_step)
       /* Scroll if point within this distance from the top or bottom
         of the window.  This is a pixel value.  */
       this_scroll_margin = max (0, scroll_margin);
-      this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
-      this_scroll_margin *= CANON_Y_UNIT (f);
+      this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+      this_scroll_margin *= FRAME_LINE_HEIGHT (f);
 
       /* Start with the row the cursor was displayed during the last
         not paused redisplay.  Give up if that row is not valid.  */
@@ -10534,6 +11356,43 @@ try_cursor_movement (window, startp, scroll_step)
   return rc;
 }
 
+void
+set_vertical_scroll_bar (w)
+     struct window *w;
+{
+  int start, end, whole;
+
+  /* Calculate the start and end positions for the current window.
+     At some point, it would be nice to choose between scrollbars
+     which reflect the whole buffer size, with special markers
+     indicating narrowing, and scrollbars which reflect only the
+     visible region.
+     
+     Note that mini-buffers sometimes aren't displaying any text.  */
+  if (!MINI_WINDOW_P (w)
+      || (w == XWINDOW (minibuf_window)
+         && NILP (echo_area_buffer[0])))
+    {
+      struct buffer *buf = XBUFFER (w->buffer);
+      whole = BUF_ZV (buf) - BUF_BEGV (buf);
+      start = marker_position (w->start) - BUF_BEGV (buf);
+      /* I don't think this is guaranteed to be right.  For the
+        moment, we'll pretend it is.  */
+      end = BUF_Z (buf) - XFASTINT (w->window_end_pos) - BUF_BEGV (buf);
+      
+      if (end < start)
+       end = start;
+      if (whole < (end - start))
+       whole = end - start;
+    }
+  else
+    start = end = whole = 0;
+
+  /* Indicate what this scroll bar ought to be displaying now.  */
+  if (FRAME_DISPLAY (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+    (*FRAME_DISPLAY (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
+      (w, end - start, whole, start);
+}
 
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
    selected_window is redisplayed.
@@ -10600,6 +11459,8 @@ redisplay_window (window, just_this_one_p)
        }
       else if ((w != XWINDOW (minibuf_window)
                || minibuf_level == 0)
+              /* When buffer is nonempty, redisplay window normally. */
+              && BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer))
               /* Quail displays non-mini buffers in minibuffer window.
                  In that case, redisplay the window normally.  */
               && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
@@ -10745,6 +11606,11 @@ redisplay_window (window, just_this_one_p)
                  MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
       if (IT_CHARPOS (it) == PT)
        w->force_start = Qt;
+      /* IT may overshoot PT if text at PT is invisible.  */
+      else if (IT_CHARPOS (it) > PT && CHARPOS (startp) <= PT)
+       w->force_start = Qt;
+
+
     }
 
   /* Handle case where place to start displaying has been specified,
@@ -11105,7 +11971,7 @@ redisplay_window (window, just_this_one_p)
          clear_glyph_matrix (w->desired_matrix);
          goto recenter;
        }
-      
+
       /* If centering point failed to make the whole line visible,
         put point at the top instead.  That has to make the whole line
         visible, if it can be done.  */
@@ -11219,41 +12085,15 @@ redisplay_window (window, just_this_one_p)
   ;
  finish_scroll_bars:
 
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
     {
-      int start, end, whole;
-
-      /* Calculate the start and end positions for the current window.
-        At some point, it would be nice to choose between scrollbars
-        which reflect the whole buffer size, with special markers
-        indicating narrowing, and scrollbars which reflect only the
-        visible region.
-
-        Note that mini-buffers sometimes aren't displaying any text.  */
-      if (!MINI_WINDOW_P (w)
-         || (w == XWINDOW (minibuf_window)
-             && NILP (echo_area_buffer[0])))
-       {
-         whole = ZV - BEGV;
-         start = marker_position (w->start) - BEGV;
-         /* I don't think this is guaranteed to be right.  For the
-            moment, we'll pretend it is.  */
-         end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
-
-         if (end < start)
-           end = start;
-         if (whole < (end - start))
-           whole = end - start;
-       }
-      else
-       start = end = whole = 0;
-
-      /* Indicate what this scroll bar ought to be displaying now.  */
-      set_vertical_scroll_bar_hook (w, end - start, whole, start);
+      /* Set the thumb's position and size.  */
+      set_vertical_scroll_bar (w);
 
       /* Note that we actually used the scroll bar attached to this
         window, so it shouldn't be deleted at the end of redisplay.  */
-      redeem_scroll_bar_hook (w);
+      if (FRAME_DISPLAY (f)->redeem_scroll_bar_hook)
+        (*FRAME_DISPLAY (f)->redeem_scroll_bar_hook) (w);
     }
 
   /* Restore current_buffer and value of point in it.  */
@@ -11320,8 +12160,9 @@ try_window (window, pos)
     }
   else
     {
-      w->window_end_bytepos = 0;
-      w->window_end_pos = w->window_end_vpos = make_number (0);
+      w->window_end_bytepos = Z_BYTE - ZV_BYTE;
+      w->window_end_pos = make_number (Z - ZV);
+      w->window_end_vpos = make_number (0);
     }
 
   /* But that is not valid info until redisplay finishes.  */
@@ -11461,10 +12302,10 @@ try_window_reusing_current_matrix (w)
          if (run.height > 0 && run.current_y != run.desired_y)
            {
              update_begin (f);
-             rif->update_window_begin_hook (w);
-             rif->clear_mouse_face (w);
-             rif->scroll_run_hook (w, &run);
-             rif->update_window_end_hook (w, 0, 0);
+             FRAME_RIF (f)->update_window_begin_hook (w);
+             FRAME_RIF (f)->clear_window_mouse_face (w);
+             FRAME_RIF (f)->scroll_run_hook (w, &run);
+             FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
              update_end (f);
            }
 
@@ -11480,7 +12321,7 @@ try_window_reusing_current_matrix (w)
            (start_row + i)->enabled_p = 0;
 
          /* Re-compute Y positions.  */
-         min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+         min_y = WINDOW_HEADER_LINE_HEIGHT (w);
          max_y = it.last_visible_y;
          for (row = start_row + nrows_scrolled;
               row < bottom_row;
@@ -11534,8 +12375,9 @@ try_window_reusing_current_matrix (w)
       else
        {
          /* This window must be completely empty.  */
-         w->window_end_bytepos = 0;
-         w->window_end_pos = w->window_end_vpos = make_number (0);
+         w->window_end_bytepos = Z_BYTE - ZV_BYTE;
+         w->window_end_pos = make_number (Z - ZV);
+         w->window_end_vpos = make_number (0);
        }
       w->window_end_valid = Qnil;
 
@@ -11594,7 +12436,7 @@ try_window_reusing_current_matrix (w)
       it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
                 - nrows_scrolled);
       it.current_y = (first_row_to_display->y - first_reusable_row->y
-                     + WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
+                     + WINDOW_HEADER_LINE_HEIGHT (w));
 
       /* Display lines beginning with first_row_to_display in the
          desired matrix.  Set last_text_row to the last row displayed
@@ -11625,7 +12467,7 @@ try_window_reusing_current_matrix (w)
 
       /* Scroll the display.  */
       run.current_y = first_reusable_row->y;
-      run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w);
       run.height = it.last_visible_y - run.current_y;
       dy = run.current_y - run.desired_y;
 
@@ -11633,16 +12475,16 @@ try_window_reusing_current_matrix (w)
        {
          struct frame *f = XFRAME (WINDOW_FRAME (w));
          update_begin (f);
-         rif->update_window_begin_hook (w);
-         rif->clear_mouse_face (w);
-         rif->scroll_run_hook (w, &run);
-         rif->update_window_end_hook (w, 0, 0);
+         FRAME_RIF (f)->update_window_begin_hook (w);
+         FRAME_RIF (f)->clear_window_mouse_face (w);
+         FRAME_RIF (f)->scroll_run_hook (w, &run);
+         FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
          update_end (f);
        }
 
       /* Adjust Y positions of reused rows.  */
       bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
-      min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      min_y = WINDOW_HEADER_LINE_HEIGHT (w);
       max_y = it.last_visible_y;
       for (row = first_reusable_row; row < first_row_to_display; ++row)
        {
@@ -11894,7 +12736,7 @@ sync_frame_with_window_matrix_rows (w)
      marginal areas (see build_frame_matrix).  */
   window_row = w->current_matrix->rows;
   window_row_end = window_row + w->current_matrix->nrows;
-  frame_row = f->current_matrix->rows + XFASTINT (w->top);
+  frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
   while (window_row < window_row_end)
     {
       struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
@@ -12059,7 +12901,7 @@ try_window_id (w)
 
   /* Window must either use window-based redisplay or be full width.  */
   if (!FRAME_WINDOW_P (f)
-      && (!line_ins_del_ok
+      && (!FRAME_LINE_INS_DEL_OK (f)
          || !WINDOW_FULL_WIDTH_P (w)))
     GIVE_UP (4);
 
@@ -12150,7 +12992,10 @@ try_window_id (w)
         the window end again, since its offset from Z hasn't changed.  */
       r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
       if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
-         && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes)
+         && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes
+         /* PT must not be in a partially visible line.  */
+         && !(PT >= MATRIX_ROW_START_CHARPOS (row) + delta
+              && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
        {
          /* Adjust positions in the glyph matrix.  */
          if (delta || delta_bytes)
@@ -12195,7 +13040,10 @@ try_window_id (w)
         as is, without changing glyph positions since no text has
         been added/removed in front of the window end.  */
       r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
-      if (TEXT_POS_EQUAL_P (start, r0->start.pos))
+      if (TEXT_POS_EQUAL_P (start, r0->start.pos)
+         /* PT must not be in a partially visible line.  */
+         && !(PT >= MATRIX_ROW_START_CHARPOS (row)
+              && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
        {
          /* We have to compute the window end anew since text
             can have been added/removed after it.  */
@@ -12277,8 +13125,9 @@ try_window_id (w)
   else
     {
       /* There are no reusable lines at the start of the window.
-        Start displaying in the first line.  */
+        Start displaying in the first text line.  */
       start_display (&it, w, start);
+      it.vpos = it.first_vpos;
       start_pos = it.current.pos;
     }
 
@@ -12435,9 +13284,8 @@ try_window_id (w)
     int this_scroll_margin, cursor_height;
 
     this_scroll_margin = max (0, scroll_margin);
-    this_scroll_margin = min (this_scroll_margin,
-                             XFASTINT (w->height) / 4);
-    this_scroll_margin *= CANON_Y_UNIT (it.f);
+    this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+    this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
     cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
 
     if ((w->cursor.y < this_scroll_margin
@@ -12461,10 +13309,10 @@ try_window_id (w)
 
       if (FRAME_WINDOW_P (f))
        {
-         rif->update_window_begin_hook (w);
-         rif->clear_mouse_face (w);
-         rif->scroll_run_hook (w, &run);
-         rif->update_window_end_hook (w, 0, 0);
+         FRAME_RIF (f)->update_window_begin_hook (w);
+         FRAME_RIF (f)->clear_window_mouse_face (w);
+         FRAME_RIF (f)->scroll_run_hook (w, &run);
+         FRAME_RIF (f)->update_window_end_hook (w, 0, 0);
        }
       else
        {
@@ -12472,8 +13320,8 @@ try_window_id (w)
             lines to scroll by; dvpos < 0 means scroll up.  */
          int first_unchanged_at_end_vpos
            = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
-         int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
-         int end = (XFASTINT (w->top)
+         int from = WINDOW_TOP_EDGE_LINE (w) + first_unchanged_at_end_vpos;
+         int end = (WINDOW_TOP_EDGE_LINE (w)
                     + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
                     + window_internal_height (w));
 
@@ -12486,7 +13334,7 @@ try_window_id (w)
 
              /* On dumb terminals delete dvpos lines at the end
                 before inserting dvpos empty lines.  */
-             if (!scroll_region_ok)
+             if (!FRAME_SCROLL_REGION_OK (f))
                ins_del_lines (end - dvpos, -dvpos);
 
              /* Insert dvpos empty lines in front of
@@ -12507,7 +13355,7 @@ try_window_id (w)
 
              /* On a dumb terminal insert dvpos empty lines at the
                  end.  */
-             if (!scroll_region_ok)
+             if (!FRAME_SCROLL_REGION_OK (f))
                ins_del_lines (end + dvpos, -dvpos);
            }
 
@@ -13163,7 +14011,7 @@ compute_line_metrics (it)
       if (row->height == 0)
        {
          if (it->max_ascent + it->max_descent == 0)
-           it->max_descent = it->max_phys_descent = CANON_Y_UNIT (it->f);
+           it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
          row->ascent = it->max_ascent;
          row->height = it->max_ascent + it->max_descent;
          row->phys_ascent = it->max_phys_ascent;
@@ -13194,8 +14042,8 @@ compute_line_metrics (it)
       /* Compute how much of the line is visible.  */
       row->visible_height = row->height;
 
-      min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
-      max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
+      min_y = WINDOW_HEADER_LINE_HEIGHT (it->w);
+      max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
 
       if (row->y < min_y)
        row->visible_height -= min_y - row->y;
@@ -13514,7 +14362,7 @@ display_line (it)
   prepare_desired_row (row);
 
   row->y = it->current_y;
-  row->start = it->current;
+  row->start = it->start;
   row->continuation_lines_width = it->continuation_lines_width;
   row->displays_text_p = 1;
   row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
@@ -13905,6 +14753,7 @@ display_line (it)
   it->current_y += row->height;
   ++it->vpos;
   ++it->glyph_row;
+  it->start = it->current;
   return row->displays_text_p;
 }
 
@@ -13951,7 +14800,7 @@ display_menu_bar (w)
   xassert (!FRAME_WINDOW_P (f));
   init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
   it.first_visible_x = 0;
-  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
 #else /* not USE_X_TOOLKIT */
   if (FRAME_WINDOW_P (f))
     {
@@ -13963,7 +14812,7 @@ display_menu_bar (w)
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
-      it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+      it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
     }
   else
     {
@@ -13972,7 +14821,7 @@ display_menu_bar (w)
       init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
-      it.last_visible_x = FRAME_WIDTH (f);
+      it.last_visible_x = FRAME_COLS (f);
     }
 #endif /* not USE_X_TOOLKIT */
 
@@ -14229,8 +15078,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
   int literal = 0;
 
  tail_recurse:
-  if (depth > 10)
-    goto invalid;
+  if (depth > 100)
+    elt = build_string ("*too-deep*");
 
   depth++;
 
@@ -14585,14 +15434,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
 
     default:
     invalid:
-      if (frame_title_ptr)
-       n += store_frame_title ("*invalid*", 0, precision - n);
-      else if (!NILP (mode_line_string_list))
-       n += store_mode_line_string ("*invalid*", Qnil, 0, 0, precision - n, Qnil);
-      else
-       n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
-                            precision - n, 0, 0);
-      return n;
+      elt = build_string ("*invalid*");
+      goto tail_recurse;
     }
 
   /* Pad to FIELD_WIDTH.  */
@@ -14842,6 +15685,117 @@ pint2str (buf, width, d)
     }
 }
 
+/* Write a null-terminated, right justified decimal and "human
+   readable" representation of the nonnegative integer D to BUF using
+   a minimal field width WIDTH.         D should be smaller than 999.5e24. */
+
+static const char power_letter[] =
+  {
+    0,  /* not used */
+    'k', /* kilo */
+    'M', /* mega */
+    'G', /* giga */
+    'T', /* tera */
+    'P', /* peta */
+    'E', /* exa */
+    'Z', /* zetta */
+    'Y'         /* yotta */
+  };
+
+static void
+pint2hrstr (buf, width, d)
+     char *buf;
+     int width;
+     int d;
+{
+  /* We aim to represent the nonnegative integer D as
+     QUOTIENT.TENTHS * 10 ^ (3 * EXPONENT). */
+  int quotient = d;
+  int remainder = 0;
+  /* -1 means: do not use TENTHS. */
+  int tenths = -1;
+  int exponent = 0;
+
+  /* Length of QUOTIENT.TENTHS as a string. */
+  int length;
+
+  char * psuffix;
+  char * p;
+
+  if (1000 <= quotient)
+    {
+      /* Scale to the appropriate EXPONENT. */
+      do
+       {
+         remainder = quotient % 1000;
+         quotient /= 1000;
+         exponent++;
+       }
+      while (1000 <= quotient);
+
+      /* Round to nearest and decide whether to use TENTHS or not. */
+      if (quotient <= 9)
+       {
+         tenths = remainder / 100;
+         if (50 <= remainder % 100)
+           if (tenths < 9)
+             tenths++;
+           else
+             {
+               quotient++;
+               if (quotient == 10)
+                 tenths = -1;
+               else
+                 tenths = 0;
+             }
+       }
+      else
+       if (500 <= remainder)
+         if (quotient < 999)
+           quotient++;
+         else
+           {
+             quotient = 1;
+             exponent++;
+             tenths = 0;
+           }
+    }
+
+  /* Calculate the LENGTH of QUOTIENT.TENTHS as a string. */
+  if (tenths == -1 && quotient <= 99)
+    if (quotient <= 9)
+      length = 1;
+    else
+      length = 2;
+  else
+    length = 3;
+  p = psuffix = buf + max (width, length);
+
+  /* Print EXPONENT. */
+  if (exponent)
+    *psuffix++ = power_letter[exponent];
+  *psuffix = '\0';
+
+  /* Print TENTHS. */
+  if (tenths >= 0)
+    {
+      *--p = '0' + tenths;
+      *--p = '.';
+    }
+
+  /* Print QUOTIENT. */
+  do
+    {
+      int digit = quotient % 10;
+      *--p =  '0' + digit;
+    }
+  while ((quotient /= 10) != 0);
+
+  /* Print leading spaces. */
+  while (buf < p)
+    *--p = ' ';
+}
+
 /* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
    If EOL_FLAG is 1, set also a mnemonic character for end-of-line
    type of CODING_SYSTEM.  Return updated pointer into BUF.  */
@@ -15044,13 +15998,27 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
       obj = b->filename;
       break;
 
+    case 'i':
+      {
+       int size = ZV - BEGV;
+       pint2str (decode_mode_spec_buf, field_width, size);
+       return decode_mode_spec_buf;
+      }
+
+    case 'I':
+      {
+       int size = ZV - BEGV;
+       pint2hrstr (decode_mode_spec_buf, field_width, size);
+       return decode_mode_spec_buf;
+      }
+
     case 'l':
       {
        int startpos = XMARKER (w->start)->charpos;
        int startpos_byte = marker_byte_position (w->start);
        int line, linepos, linepos_byte, topline;
        int nlines, junk;
-       int height = XFASTINT (w->height);
+       int height = WINDOW_TOTAL_LINES (w);
 
        /* If we decided that this buffer isn't suitable for line numbers,
           don't forget that too fast.  */
@@ -15245,6 +16213,14 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
       return "T";
 #endif
 
+    case 'T':
+      /* %T is the frame name on a termcap frame, the empty string otherwise. */
+      if (! FRAME_TERMCAP_P (f))
+        return "";
+      if (!NILP (f->title))
+       return (char *) SDATA (f->title);
+      return (char *) SDATA (f->name);
+
     case 'z':
       /* coding-system (not including end-of-line format) */
     case 'Z':
@@ -15664,6 +16640,8 @@ invisible_p (propval, list)
                             Glyph Display
  ***********************************************************************/
 
+#ifdef HAVE_WINDOW_SYSTEM
+
 #if GLYPH_DEBUG
 
 void
@@ -15847,7 +16825,7 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
            = FONT_INFO_FROM_ID (f, face->font_info_id);
          if (font_info)
            glyph->font_type
-             = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
+             = FRAME_RIF (f)->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
        }
     }
 
@@ -16077,7 +17055,7 @@ x_get_glyph_overhangs (glyph, f, left, right)
       font = face->font;
       font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
       if (font  /* ++KFS: Should this be font_info ?  */
-         && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
+         && (pcm = FRAME_RIF (f)->per_char_metric (font, &char2b, glyph->font_type)))
        {
          if (pcm->rbearing > pcm->width)
            *right = pcm->rbearing - pcm->width;
@@ -16245,7 +17223,7 @@ get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
          struct font_info *font_info
            = FONT_INFO_FROM_ID (f, face->font_info_id);
          if (font_info)
-           rif->encode_char (c, char2b, font_info, 0);
+           FRAME_RIF (f)->encode_char (c, char2b, font_info, 0);
        }
     }
 
@@ -16312,8 +17290,8 @@ compute_overhangs_and_x (s, x, backward_p)
     {
       while (s)
        {
-         if (rif->compute_glyph_string_overhangs)
-           rif->compute_glyph_string_overhangs (s);
+         if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
+           FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
          x -= s->width;
          s->x = x;
          s = s->prev;
@@ -16323,8 +17301,8 @@ compute_overhangs_and_x (s, x, backward_p)
     {
       while (s)
        {
-         if (rif->compute_glyph_string_overhangs)
-           rif->compute_glyph_string_overhangs (s);
+         if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
+           FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
          s->x = x;
          x += s->width;
          s = s->next;
@@ -16334,7 +17312,7 @@ compute_overhangs_and_x (s, x, backward_p)
 
 
 
-/* The following macros are only called from x_draw_glyphs below.
+/* The following macros are only called from draw_glyphs below.
    They reference the following parameters of that function directly:
      `w', `row', `area', and `overlap_p'
    as well as the following local variables:
@@ -16484,7 +17462,7 @@ compute_overhangs_and_x (s, x, backward_p)
    x-positions of the drawing area.
 
    This is an ugly monster macro construct because we must use alloca
-   to allocate glyph strings (because x_draw_glyphs can be called
+   to allocate glyph strings (because draw_glyphs can be called
    asynchronously).  */
 
 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)        \
@@ -16543,8 +17521,8 @@ compute_overhangs_and_x (s, x, backward_p)
 
    Value is the x-position reached, relative to AREA of W.  */
 
-int
-x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
+static int
+draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
      struct window *w;
      int x;
      struct glyph_row *row;
@@ -16574,30 +17552,15 @@ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
     {
       /* X is relative to the left edge of W, without scroll bars
         or fringes.  */
-      int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
-
-      x += window_left_x;
-      area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
-      last_x = window_left_x + area_width;
-
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-       {
-         int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
-         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-           last_x += width;
-         else
-           x -= width;
-       }
-
-      x += FRAME_INTERNAL_BORDER_WIDTH (f);
-      /* ++KFS: W32 and MAC versions had -= in next line (bug??)  */
-      last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
+      x += WINDOW_LEFT_EDGE_X (w);
+      last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
     }
   else
     {
-      x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
+      int area_left = window_box_left (w, area);
+      x += area_left;
       area_width = window_box_width (w, area);
-      last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
+      last_x = area_left + area_width;
     }
 
   /* Build a doubly-linked list of glyph_string structures between
@@ -16620,9 +17583,9 @@ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       struct glyph_string *h, *t;
 
       /* Compute overhangs for all glyph strings.  */
-      if (rif->compute_glyph_string_overhangs)
+      if (FRAME_RIF (f)->compute_glyph_string_overhangs)
        for (s = head; s; s = s->next)
-         rif->compute_glyph_string_overhangs (s);
+         FRAME_RIF (f)->compute_glyph_string_overhangs (s);
 
       /* Prepend glyph strings for glyphs in front of the first glyph
         string that are overwritten because of the first glyph
@@ -16690,7 +17653,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
 
   /* Draw all strings.  */
   for (s = head; s; s = s->next)
-    rif->draw_glyph_string (s);
+    FRAME_RIF (f)->draw_glyph_string (s);
 
   if (area == TEXT_AREA
       && !row->full_width_p
@@ -16702,38 +17665,20 @@ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       int x0 = head ? head->x : x;
       int x1 = tail ? tail->x + tail->background_width : x;
 
-      x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
-      x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
-
-      /* ++KFS: W32 and MAC versions had following test here:
-        if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
-      */
+      int text_left = window_box_left (w, TEXT_AREA);
+      x0 -= text_left;
+      x1 -= text_left;
 
-      if (XFASTINT (w->left_margin_width) != 0)
-       {
-         int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
-         x0 -= left_area_width;
-         x1 -= left_area_width;
-       }
-
-      notice_overwritten_cursor (w, area, x0, x1,
+      notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
                                 row->y, MATRIX_ROW_BOTTOM_Y (row));
     }
 
   /* Value is the x-position up to which drawn, relative to AREA of W.
      This doesn't include parts drawn because of overhangs.  */
-  x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
-  if (!row->full_width_p)
-    {
-      /* ++KFS: W32 and MAC versions only had this test here:
-        if (area > LEFT_MARGIN_AREA)
-      */
-
-      if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
-       x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
-      if (area > TEXT_AREA)
-       x_reached -= window_box_width (w, TEXT_AREA);
-    }
+  if (row->full_width_p)
+    x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
+  else
+    x_reached -= window_box_left (w, area);
 
   RELEASE_HDC (hdc, f);
 
@@ -16760,6 +17705,8 @@ append_glyph (it)
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
       glyph->pixel_width = it->pixel_width;
+      glyph->ascent = it->ascent;
+      glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = CHAR_GLYPH;
       glyph->multibyte_p = it->multibyte_p;
@@ -16794,6 +17741,8 @@ append_composite_glyph (it)
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
       glyph->pixel_width = it->pixel_width;
+      glyph->ascent = it->ascent;
+      glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = COMPOSITE_GLYPH;
       glyph->multibyte_p = it->multibyte_p;
@@ -16842,6 +17791,7 @@ produce_image_glyph (it)
 {
   struct image *img;
   struct face *face;
+  int face_ascent, glyph_ascent;
 
   xassert (it->what == IT_IMAGE);
 
@@ -16853,10 +17803,15 @@ produce_image_glyph (it)
   PREPARE_FACE_FOR_DISPLAY (it->f, face);
   prepare_image_for_display (it->f, img);
 
-  it->ascent = it->phys_ascent = image_ascent (img, face);
+  it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face);
   it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
   it->pixel_width = img->width + 2 * img->hmargin;
 
+  /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent.  */
+  face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
+  if (face_ascent > it->ascent)
+    it->ascent = it->phys_ascent = face_ascent;
+
   it->nglyphs = 1;
 
   if (face->box != FACE_NO_BOX)
@@ -16886,6 +17841,8 @@ produce_image_glyph (it)
          glyph->charpos = CHARPOS (it->position);
          glyph->object = it->object;
          glyph->pixel_width = it->pixel_width;
+         glyph->ascent = glyph_ascent;
+         glyph->descent = it->descent;
          glyph->voffset = it->voffset;
          glyph->type = IMAGE_GLYPH;
          glyph->multibyte_p = it->multibyte_p;
@@ -16905,20 +17862,19 @@ produce_image_glyph (it)
 
 /* Append a stretch glyph to IT->glyph_row.  OBJECT is the source
    of the glyph, WIDTH and HEIGHT are the width and height of the
-   stretch.  ASCENT is the percentage/100 of HEIGHT to use for the
-   ascent of the glyph (0 <= ASCENT <= 1).  */
+   stretch.  ASCENT is the ascent of the glyph (0 <= ASCENT <= HEIGHT).  */
 
 static void
 append_stretch_glyph (it, object, width, height, ascent)
      struct it *it;
      Lisp_Object object;
      int width, height;
-     double ascent;
+     int ascent;
 {
   struct glyph *glyph;
   enum glyph_row_area area = it->area;
 
-  xassert (ascent >= 0 && ascent <= 1);
+  xassert (ascent >= 0 && ascent <= height);
 
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
@@ -16926,6 +17882,8 @@ append_stretch_glyph (it, object, width, height, ascent)
       glyph->charpos = CHARPOS (it->position);
       glyph->object = object;
       glyph->pixel_width = width;
+      glyph->ascent = ascent;
+      glyph->descent = height - ascent;
       glyph->voffset = it->voffset;
       glyph->type = STRETCH_GLYPH;
       glyph->multibyte_p = it->multibyte_p;
@@ -16935,7 +17893,7 @@ append_stretch_glyph (it, object, width, height, ascent)
       glyph->padding_p = 0;
       glyph->glyph_not_available_p = 0;
       glyph->face_id = it->face_id;
-      glyph->u.stretch.ascent = height * ascent;
+      glyph->u.stretch.ascent = ascent;
       glyph->u.stretch.height = height;
       glyph->font_type = FONT_TYPE_UNKNOWN;
       ++it->glyph_row->used[area];
@@ -16943,51 +17901,250 @@ append_stretch_glyph (it, object, width, height, ascent)
 }
 
 
-/* Produce a stretch glyph for iterator IT.  IT->object is the value
-   of the glyph property displayed.  The value must be a list
-   `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
-   being recognized:
+/* Calculate a width or height in pixels from a specification using
+   the following elements:
 
-   1. `:width WIDTH' specifies that the space should be WIDTH *
-   canonical char width wide.  WIDTH may be an integer or floating
-   point number.
+   SPEC ::= 
+     NUM      - a (fractional) multiple of the default font width/height
+     (NUM)    - specifies exactly NUM pixels
+     UNIT     - a fixed number of pixels, see below.
+     ELEMENT  - size of a display element in pixels, see below.
+     (NUM . SPEC) - equals NUM * SPEC
+     (+ SPEC SPEC ...)  - add pixel values
+     (- SPEC SPEC ...)  - subtract pixel values
+     (- SPEC)           - negate pixel value
 
-   2. `:relative-width FACTOR' specifies that the width of the stretch
-   should be computed from the width of the first character having the
-   `glyph' property, and should be FACTOR times that width.
+   NUM ::= 
+     INT or FLOAT   - a number constant
+     SYMBOL         - use symbol's (buffer local) variable binding.
 
-   3. `:align-to HPOS' specifies that the space should be wide enough
-   to reach HPOS, a value in canonical character units.
+   UNIT ::=
+     in       - pixels per inch  *)
+     mm       - pixels per 1/1000 meter  *)
+     cm       - pixels per 1/100 meter   *)
+     width    - width of current font in pixels.
+     height   - height of current font in pixels.
 
-   Exactly one of the above pairs must be present.
+     *) using the ratio(s) defined in display-pixels-per-inch.
 
-   4. `:height HEIGHT' specifies that the height of the stretch produced
-   should be HEIGHT, measured in canonical character units.
+   ELEMENT ::=
 
-   5. `:relative-height FACTOR' specifies that the height of the
-   stretch should be FACTOR times the height of the characters having
-   the glyph property.
+     left-fringe         - left fringe width in pixels
+     (left-fringe . nil) - left fringe width if inside margins, else 0
+     (left-fringe . t)   - left fringe width if outside margins, else 0
 
-   Either none or exactly one of 4 or 5 must be present.
+     right-fringe         - right fringe width in pixels
+     (right-fringe . nil) - right fringe width if inside margins, else 0
+     (right-fringe . t)   - right fringe width if outside margins, else 0
 
-   6. `:ascent ASCENT'  specifies that ASCENT percent of the height
-   of the stretch should be used for the ascent of the stretch.
-   ASCENT must be in the range 0 <= ASCENT <= 100.  */
+     left-margin          - left margin width in pixels
+     right-margin         - right margin width in pixels
+
+     scroll-bar           - scroll-bar area width in pixels
+     (scroll-bar . left)  - scroll-bar width if on left, else 0
+     (scroll-bar . right) - scroll-bar width if on right, else 0
+
+   Examples:
+
+   Pixels corresponding to 5 inches:
+     (5 . in)     
+               
+   Total width of non-text areas on left side of window:
+     (+ left-fringe left-margin (scroll-bar . left))
+
+   Total width of fringes if inside display margins:
+     (+ (left-fringe) (right-fringe))
+
+   Width of left margin minus width of 1 character in the default font:
+     (- left-margin 1)
+
+   Width of left margin minus width of 2 characters in the current font:
+     (- left-margin (2 . width))
+
+   Width of left fringe plus left margin minus one pixel:
+     (- (+ left-fringe left-margin) (1))
+     (+ left-fringe left-margin (- (1)))
+     (+ left-fringe left-margin (-1))
+
+*/
 
 #define NUMVAL(X)                              \
      ((INTEGERP (X) || FLOATP (X))             \
       ? XFLOATINT (X)                          \
       : - 1)
 
+static int
+calc_pixel_width_or_height (res, it, prop, font, width_p)
+     double *res;
+     struct it *it;
+     Lisp_Object prop;
+     XFontStruct *font;
+     int width_p;
+{
+  double pixels;
+
+#define OK_PIXELS(val) ((*res = (val)), 1)
+
+  if (SYMBOLP (prop))
+    {
+      if (SCHARS (SYMBOL_NAME (prop)) == 2)
+       {
+         char *unit =  SDATA (SYMBOL_NAME (prop));
+
+         if (unit[0] == 'i' && unit[1] == 'n')
+           pixels = 1.0;
+         else if (unit[0] == 'm' && unit[1] == 'm')
+           pixels = 25.4;
+         else if (unit[0] == 'c' && unit[1] == 'm')
+           pixels = 2.54;
+         else
+           pixels = 0;
+         if (pixels > 0)
+           {
+             double ppi;
+             if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
+                 || (CONSP (Vdisplay_pixels_per_inch)
+                     && (ppi = (width_p
+                                ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
+                                : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
+                         ppi > 0)))
+               return OK_PIXELS (ppi / pixels);
+
+             return 0;
+           }
+       }
+
+      if (EQ (prop, Qheight))
+       return OK_PIXELS (font ? FONT_HEIGHT (font) : FRAME_LINE_HEIGHT (it->f));
+      if (EQ (prop, Qwidth))
+       return OK_PIXELS (font ? FONT_WIDTH (font) : FRAME_COLUMN_WIDTH (it->f));
+      if (EQ (prop, Qleft_fringe))
+       return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
+      if (EQ (prop, Qright_fringe))
+       return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
+      if (EQ (prop, Qleft_margin))
+       return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
+      if (EQ (prop, Qright_margin))
+       return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
+      if (EQ (prop, Qscroll_bar))
+       return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
+
+      prop = Fbuffer_local_value (prop, it->w->buffer);
+    }
+
+  if (INTEGERP (prop) || FLOATP (prop))
+    {
+      int base_unit = (width_p
+                      ? FRAME_COLUMN_WIDTH (it->f)
+                      : FRAME_LINE_HEIGHT (it->f));
+      return OK_PIXELS (XFLOATINT (prop) * base_unit);
+    }
+
+  if (CONSP (prop))
+    {
+      Lisp_Object car = XCAR (prop);
+      Lisp_Object cdr = XCDR (prop);
+
+      if (SYMBOLP (car))
+       {
+         if (EQ (car, Qplus) || EQ (car, Qminus))
+           {
+             int first = 1;
+             double px;
+
+             pixels = 0;
+             while (CONSP (cdr))
+               {
+                 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr), font, width_p))
+                   return 0;
+                 if (first)
+                   pixels = (EQ (car, Qplus) ? px : -px), first = 0;
+                 else
+                   pixels += px;
+                 cdr = XCDR (cdr);
+               }
+             if (EQ (car, Qminus))
+               pixels = -pixels;
+             return OK_PIXELS (pixels);
+           }
+
+         if (EQ (car, Qleft_fringe))
+           return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+                              == !NILP (cdr))
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : 0);
+         if (EQ (car, Qright_fringe))
+           return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+                              == !NILP (cdr))
+                             ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+                             : 0);
+         if (EQ (car, Qscroll_bar))
+           return OK_PIXELS ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
+                               == EQ (cdr, Qleft))
+                              ? WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)
+                              : 0);
+
+         car = Fbuffer_local_value (car, it->w->buffer);
+       }
+
+      if (INTEGERP (car) || FLOATP (car))
+       {
+         double fact;
+         pixels = XFLOATINT (car);
+         if (NILP (cdr))
+           return OK_PIXELS (pixels);
+         if (calc_pixel_width_or_height (&fact, it, cdr, font, width_p))
+           return OK_PIXELS (pixels * fact);
+         return 0;
+       }
+
+      return 0;
+    }
+
+  return 0;
+}
+
+/* Produce a stretch glyph for iterator IT.  IT->object is the value
+   of the glyph property displayed.  The value must be a list
+   `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
+   being recognized:
+
+   1. `:width WIDTH' specifies that the space should be WIDTH *
+   canonical char width wide.  WIDTH may be an integer or floating
+   point number.
+
+   2. `:relative-width FACTOR' specifies that the width of the stretch
+   should be computed from the width of the first character having the
+   `glyph' property, and should be FACTOR times that width.
+
+   3. `:align-to HPOS' specifies that the space should be wide enough
+   to reach HPOS, a value in canonical character units.
+
+   Exactly one of the above pairs must be present.
+
+   4. `:height HEIGHT' specifies that the height of the stretch produced
+   should be HEIGHT, measured in canonical character units.
+
+   5. `:relative-height FACTOR' specifies that the height of the
+   stretch should be FACTOR times the height of the characters having
+   the glyph property.
+
+   Either none or exactly one of 4 or 5 must be present.
+
+   6. `:ascent ASCENT'  specifies that ASCENT percent of the height
+   of the stretch should be used for the ascent of the stretch.
+   ASCENT must be in the range 0 <= ASCENT <= 100.  */
 
 static void
 produce_stretch_glyph (it)
      struct it *it;
 {
-  /* (space :width WIDTH :height HEIGHT.  */
+  /* (space :width WIDTH :height HEIGHT ...)  */
   Lisp_Object prop, plist;
   int width = 0, height = 0;
-  double ascent = 0;
+  int zero_width_ok_p = 0, zero_height_ok_p = 0;
+  int ascent = 0;
+  double tem;
   struct face *face = FACE_FROM_ID (it->f, it->face_id);
   XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
 
@@ -16998,10 +18155,13 @@ produce_stretch_glyph (it)
   plist = XCDR (it->object);
 
   /* Compute the width of the stretch.  */
-  if (prop = Fplist_get (plist, QCwidth),
-      NUMVAL (prop) > 0)
-    /* Absolute width `:width WIDTH' specified and valid.  */
-    width = NUMVAL (prop) * CANON_X_UNIT (it->f);
+  if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
+      && calc_pixel_width_or_height (&tem, it, prop, font, 1))
+    {
+      /* Absolute width `:width WIDTH' specified and valid.  */
+      zero_width_ok_p = 1;
+      width = (int)tem;
+    }
   else if (prop = Fplist_get (plist, QCrelative_width),
           NUMVAL (prop) > 0)
     {
@@ -17026,38 +18186,48 @@ produce_stretch_glyph (it)
       x_produce_glyphs (&it2);
       width = NUMVAL (prop) * it2.pixel_width;
     }
-  else if (prop = Fplist_get (plist, QCalign_to),
-          NUMVAL (prop) > 0)
-    width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
+  else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
+          && calc_pixel_width_or_height (&tem, it, prop, font, 1))
+    {
+      width = max (0, (int)tem - it->current_x);
+      zero_width_ok_p = 1;
+    }
   else
     /* Nothing specified -> width defaults to canonical char width.  */
-    width = CANON_X_UNIT (it->f);
+    width = FRAME_COLUMN_WIDTH (it->f);
+
+  if (width <= 0 && (width < 0 || !zero_width_ok_p))
+    width = 1;
 
   /* Compute height.  */
-  if (prop = Fplist_get (plist, QCheight),
-      NUMVAL (prop) > 0)
-    height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
+  if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
+      && calc_pixel_width_or_height (&tem, it, prop, font, 0))
+    {
+      height = (int)tem;
+      zero_height_ok_p = 1;
+    }
   else if (prop = Fplist_get (plist, QCrelative_height),
           NUMVAL (prop) > 0)
     height = FONT_HEIGHT (font) * NUMVAL (prop);
   else
     height = FONT_HEIGHT (font);
 
+  if (height <= 0 && (height < 0 || !zero_height_ok_p))
+    height = 1;
+
   /* Compute percentage of height used for ascent.  If
      `:ascent ASCENT' is present and valid, use that.  Otherwise,
      derive the ascent from the font in use.  */
   if (prop = Fplist_get (plist, QCascent),
       NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
-    ascent = NUMVAL (prop) / 100.0;
+    ascent = height * NUMVAL (prop) / 100.0;
+  else if (!NILP (prop)
+          && calc_pixel_width_or_height (&tem, it, prop, font, 0))
+    ascent = min (max (0, (int)tem), height);
   else
-    ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
+    ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
 
-  if (width <= 0)
-    width = 1;
-  if (height <= 0)
-    height = 1;
-
-  if (it->glyph_row)
+  if (width > 0 && height > 0 && it->glyph_row)
     {
       Lisp_Object object = it->stack[it->sp - 1].string;
       if (!STRINGP (object))
@@ -17066,11 +18236,11 @@ produce_stretch_glyph (it)
     }
 
   it->pixel_width = width;
-  it->ascent = it->phys_ascent = height * ascent;
+  it->ascent = it->phys_ascent = ascent;
   it->descent = it->phys_descent = height - it->ascent;
-  it->nglyphs = 1;
+  it->nglyphs = width > 0 && height > 0 ? 1 : 0;
 
-  if (face->box != FACE_NO_BOX)
+  if (width > 0 && height > 0 && face->box != FACE_NO_BOX)
     {
       if (face->box_line_width > 0)
        {
@@ -17171,8 +18341,8 @@ x_produce_glyphs (it)
 
          it->nglyphs = 1;
 
-         pcm = rif->per_char_metric (font, &char2b,
-                                     FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
+         pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                    FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
          it->ascent = FONT_BASE (font) + boff;
          it->descent = FONT_DESCENT (font) - boff;
 
@@ -17231,8 +18401,8 @@ x_produce_glyphs (it)
                {
                  /* Translate a space with a `space-width' property
                     into a stretch glyph.  */
-                 double ascent = (double) FONT_BASE (font)
-                                / FONT_HEIGHT (font);
+                 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
+                               / FONT_HEIGHT (font));
                  append_stretch_glyph (it, it->object, it->pixel_width,
                                        it->ascent + it->descent, ascent);
                }
@@ -17263,14 +18433,14 @@ x_produce_glyphs (it)
        }
       else if (it->char_to_display == '\t')
        {
-         int tab_width = it->tab_width * CANON_X_UNIT (it->f);
+         int tab_width = it->tab_width * FRAME_COLUMN_WIDTH (it->f);
          int x = it->current_x + it->continuation_lines_width;
          int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
 
          /* If the distance from the current position to the next tab
             stop is less than a canonical character width, use the
             tab stop after that.  */
-         if (next_tab_x - x < CANON_X_UNIT (it->f))
+         if (next_tab_x - x < FRAME_COLUMN_WIDTH (it->f))
            next_tab_x += tab_width;
 
          it->pixel_width = next_tab_x - x;
@@ -17280,9 +18450,8 @@ x_produce_glyphs (it)
 
          if (it->glyph_row)
            {
-             double ascent = (double) it->ascent / (it->ascent + it->descent);
              append_stretch_glyph (it, it->object, it->pixel_width,
-                                   it->ascent + it->descent, ascent);
+                                   it->ascent + it->descent, it->ascent);
            }
        }
       else
@@ -17297,15 +18466,15 @@ x_produce_glyphs (it)
             from the charset width; this is what old redisplay code
             did.  */
 
-         pcm = rif->per_char_metric (font, &char2b,
-                                     FONT_TYPE_FOR_MULTIBYTE (font, it->c));
+         pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                    FONT_TYPE_FOR_MULTIBYTE (font, it->c));
 
          if (font_not_found_p || !pcm)
            {
              int charset = CHAR_CHARSET (it->char_to_display);
 
              it->glyph_not_available_p = 1;
-             it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
+             it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
                                 * CHARSET_WIDTH (charset));
              it->phys_ascent = FONT_BASE (font) + boff;
              it->phys_descent = FONT_DESCENT (font) - boff;
@@ -17429,8 +18598,8 @@ x_produce_glyphs (it)
 
          /* Initialize the bounding box.  */
          if (font_info
-             && (pcm = rif->per_char_metric (font, &char2b,
-                                             FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
+             && (pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                            FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
            {
              width = pcm->width;
              ascent = pcm->ascent;
@@ -17475,7 +18644,7 @@ x_produce_glyphs (it)
              if (font == NULL)
                {
                  font = FRAME_FONT (it->f);
-                 boff = it->f->output_data.x->baseline_offset;
+                 boff = FRAME_BASELINE_OFFSET (it->f);
                  font_info = NULL;
                }
              else
@@ -17488,8 +18657,8 @@ x_produce_glyphs (it)
                }
 
              if (font_info
-                 && (pcm = rif->per_char_metric (font, &char2b, 
-                                                 FONT_TYPE_FOR_MULTIBYTE (font, ch))))
+                 && (pcm = FRAME_RIF (it->f)->per_char_metric (font, &char2b,
+                                                                FONT_TYPE_FOR_MULTIBYTE (font, ch))))
                {
                  width = pcm->width;
                  ascent = pcm->ascent;
@@ -17645,8 +18814,175 @@ x_produce_glyphs (it)
   it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
 }
 
+/* EXPORT for RIF:
+   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.  */
+
+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 = draw_glyphs (updated_window, output_cursor.x,
+                  updated_row, updated_area,
+                  hpos, hpos + len,
+                  DRAW_NORMAL_TEXT, 0);
+
+  /* Invalidate old phys cursor if the glyph at its hpos is redrawn.  */
+  if (updated_area == TEXT_AREA
+      && updated_window->phys_cursor_on_p
+      && updated_window->phys_cursor.vpos == output_cursor.vpos
+      && updated_window->phys_cursor.hpos >= hpos
+      && updated_window->phys_cursor.hpos < hpos + len)
+    updated_window->phys_cursor_on_p = 0;
+
+  UNBLOCK_INPUT;
+
+  /* Advance the output cursor.  */
+  output_cursor.hpos += len;
+  output_cursor.x = x;
+}
+
+
+/* EXPORT for RIF:
+   Insert LEN glyphs from START at the nominal cursor position.   */
+
+void
+x_insert_glyphs (start, len)
+     struct glyph *start;
+     int len;
+{
+  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);
+
+  FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
+                                          line_height, shift_by_width);
+
+  /* Write the glyphs.  */
+  hpos = start - row->glyphs[updated_area];
+  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;
+}
+
+
+/* EXPORT for RIF:
+   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.  */
+
+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 = WINDOW_TOTAL_WIDTH (w);
+  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
+    {
+      int area_left = window_box_left (w, updated_area);
+      from_x += area_left;
+      to_x += area_left;
+    }
 
+  min_y = WINDOW_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;
+      FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
+                                       to_x - from_x, to_y - from_y);
+      UNBLOCK_INPUT;
+    }
+}
 
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 \f
@@ -17658,7 +18994,7 @@ x_produce_glyphs (it)
    ARG.  If type is BAR_CURSOR, return in *WIDTH the specified width
    of the bar cursor.  */
 
-enum text_cursor_kinds
+static enum text_cursor_kinds
 get_specified_cursor_type (arg, width)
      Lisp_Object arg;
      int *width;
@@ -17749,9 +19085,10 @@ set_frame_cursor_types (f, arg)
    setting of cursor-type.  If explicitly marked off, draw no cursor.
    In all other cases, we want a hollow box cursor.  */
 
-enum text_cursor_kinds
-get_window_cursor_type (w, width, active_cursor)
+static enum text_cursor_kinds
+get_window_cursor_type (w, glyph, width, active_cursor)
      struct window *w;
+     struct glyph *glyph;
      int *width;
      int *active_cursor;
 {
@@ -17815,7 +19152,13 @@ get_window_cursor_type (w, width, active_cursor)
 
   /* Use normal cursor if not blinked off.  */
   if (!w->cursor_off_p)
-    return cursor_type;
+    {
+      if (glyph->type == IMAGE_GLYPH) {
+       if (cursor_type == FILLED_BOX_CURSOR)
+         cursor_type = HOLLOW_BOX_CURSOR;
+      }
+      return cursor_type;
+    }
 
   /* Cursor is blinked off, so determine how to "toggle" it.  */
 
@@ -17830,6 +19173,11 @@ get_window_cursor_type (w, width, active_cursor)
       return FRAME_BLINK_OFF_CURSOR (f);
     }
 
+#if 0
+  /* Some people liked having a permanently visible blinking cursor,
+     while others had very strong opinions against it.  So it was
+     decided to remove it.  KFS 2003-09-03 */
+
   /* Finally perform built-in cursor blinking:
        filled box      <->   hollow box
        wide [h]bar     <->   narrow [h]bar
@@ -17844,11 +19192,14 @@ get_window_cursor_type (w, width, active_cursor)
       *width = 1;
       return cursor_type;
     }
+#endif
 
   return NO_CURSOR;
 }
 
 
+#ifdef HAVE_WINDOW_SYSTEM
+
 /* Notice when the text cursor of window W has been completely
    overwritten by a drawing operation that outputs glyphs in AREA
    starting at X0 and ending at X1 in the line starting at Y0 and
@@ -17856,22 +19207,12 @@ get_window_cursor_type (w, width, active_cursor)
    the rest of the line after X0 has been written.  Y coordinates
    are window-relative.  */
 
-void
+static void
 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
      struct window *w;
      enum glyph_row_area area;
      int x0, y0, x1, y1;
 {
-#ifdef HAVE_CARBON
-  /* ++KFS:  Why is there a special version of this for the mac ? */
-  if (area == TEXT_AREA
-      && w->phys_cursor_on_p
-      && y0 <= w->phys_cursor.y
-      && y1 >= w->phys_cursor.y + w->phys_cursor_height
-      && x0 <= w->phys_cursor.x
-      && (x1 < 0 || x1 > w->phys_cursor.x))
-    w->phys_cursor_on_p = 0;
-#else
   if (area == TEXT_AREA && w->phys_cursor_on_p)
     {
       int cx0 = w->phys_cursor.x;
@@ -17902,86 +19243,2189 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
            w->phys_cursor_on_p = 0;
        }
     }
-#endif
 }
 
+#endif /* HAVE_WINDOW_SYSTEM */
+
 \f
-/***********************************************************************
-                           Initialization
- ***********************************************************************/
+/************************************************************************
+                             Mouse Face
+ ************************************************************************/
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* EXPORT for RIF:
+   Fix the display of area AREA of overlapping row ROW in window W.  */
 
 void
-syms_of_xdisp ()
+x_fix_overlapping_area (w, row, area)
+     struct window *w;
+     struct glyph_row *row;
+     enum glyph_row_area area;
 {
-  Vwith_echo_area_save_vector = Qnil;
-  staticpro (&Vwith_echo_area_save_vector);
+  int i, x;
 
-  Vmessage_stack = Qnil;
-  staticpro (&Vmessage_stack);
+  BLOCK_INPUT;
 
-  Qinhibit_redisplay = intern ("inhibit-redisplay");
-  staticpro (&Qinhibit_redisplay);
+  x = 0;
+  for (i = 0; i < row->used[area];)
+    {
+      if (row->glyphs[area][i].overlaps_vertically_p)
+       {
+         int start = i, start_x = x;
 
-  message_dolog_marker1 = Fmake_marker ();
-  staticpro (&message_dolog_marker1);
-  message_dolog_marker2 = Fmake_marker ();
-  staticpro (&message_dolog_marker2);
-  message_dolog_marker3 = Fmake_marker ();
-  staticpro (&message_dolog_marker3);
+         do
+           {
+             x += row->glyphs[area][i].pixel_width;
+             ++i;
+           }
+         while (i < row->used[area]
+                && row->glyphs[area][i].overlaps_vertically_p);
 
-#if GLYPH_DEBUG
-  defsubr (&Sdump_frame_glyph_matrix);
-  defsubr (&Sdump_glyph_matrix);
-  defsubr (&Sdump_glyph_row);
-  defsubr (&Sdump_tool_bar_row);
-  defsubr (&Strace_redisplay);
-  defsubr (&Strace_to_stderr);
-#endif
-#ifdef HAVE_WINDOW_SYSTEM
-  defsubr (&Stool_bar_lines_needed);
-#endif
-  defsubr (&Sformat_mode_line);
+         draw_glyphs (w, start_x, row, area,
+                      start, i,
+                      DRAW_NORMAL_TEXT, 1);
+       }
+      else
+       {
+         x += row->glyphs[area][i].pixel_width;
+         ++i;
+       }
+    }
 
-  staticpro (&Qmenu_bar_update_hook);
-  Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
+  UNBLOCK_INPUT;
+}
 
-  staticpro (&Qoverriding_terminal_local_map);
-  Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
 
-  staticpro (&Qoverriding_local_map);
-  Qoverriding_local_map = intern ("overriding-local-map");
+/* EXPORT:
+   Draw the cursor glyph of window W in glyph row ROW.  See the
+   comment of draw_glyphs for the meaning of HL.  */
 
-  staticpro (&Qwindow_scroll_functions);
-  Qwindow_scroll_functions = intern ("window-scroll-functions");
+void
+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;
+      int x1;
+      x1 = 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;
+
+      if (hl == DRAW_CURSOR)
+       w->phys_cursor_width = x1 - w->phys_cursor.x;
+      /* When we erase the cursor, and ROW is overlapped by other
+        rows, make sure that these overlapping parts of other rows
+        are redrawn.  */
+      else 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);
+       }
+    }
+}
 
-  staticpro (&Qredisplay_end_trigger_functions);
-  Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
 
-  staticpro (&Qinhibit_point_motion_hooks);
-  Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
+/* EXPORT:
+   Erase the image of a cursor of window W from the screen.  */
 
-  QCdata = intern (":data");
-  staticpro (&QCdata);
-  Qdisplay = intern ("display");
-  staticpro (&Qdisplay);
-  Qspace_width = intern ("space-width");
-  staticpro (&Qspace_width);
-  Qraise = intern ("raise");
-  staticpro (&Qraise);
-  Qspace = intern ("space");
-  staticpro (&Qspace);
-  Qmargin = intern ("margin");
-  staticpro (&Qmargin);
-  Qleft_margin = intern ("left-margin");
-  staticpro (&Qleft_margin);
-  Qright_margin = intern ("right-margin");
-  staticpro (&Qright_margin);
-  Qalign_to = intern ("align-to");
-  staticpro (&Qalign_to);
-  QCalign_to = intern (":align-to");
+void
+erase_phys_cursor (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (w->frame);
+  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 can happen if cursor is at top of a 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 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, y;
+      int header_line_height = WINDOW_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);
+      y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
+
+      FRAME_RIF (f)->clear_frame_area (f, x, y,
+                                       cursor_glyph->pixel_width, cursor_row->visible_height);
+    }
+
+  /* Erase the cursor by redrawing the character underneath it.  */
+  if (mouse_face_here_p)
+    hl = DRAW_MOUSE_FACE;
+  else
+    hl = DRAW_NORMAL_TEXT;
+  draw_phys_cursor_glyph (w, cursor_row, hl);
+
+ mark_cursor_off:
+  w->phys_cursor_on_p = 0;
+  w->phys_cursor_type = NO_CURSOR;
+}
+
+
+/* EXPORT:
+   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
+display_and_set_cursor (w, on, hpos, vpos, x, y)
+     struct window *w;
+     int on, hpos, vpos, x, y;
+{
+  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;
+
+  /* If cursor is off and we want it off, return quickly.  */
+  if (!on && !w->phys_cursor_on_p)
+    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)
+    {
+      w->phys_cursor_on_p = 0;
+      return;
+    }
+
+  xassert (interrupt_input_blocked);
+
+  /* Set new_cursor_type to the cursor we want to be displayed.  */
+  new_cursor_type = get_window_cursor_type (w, glyph,
+                                           &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)))
+    erase_phys_cursor (w);
+
+  /* Don't check phys_cursor_on_p here because that flag is only set
+     to zero in some cases where we know that the cursor has been
+     completely erased, to avoid the extra work of erasing the cursor
+     twice.  In other words, phys_cursor_on_p can be 1 and the cursor
+     still not be visible, or it has only been partly erased.  */
+  if (on)
+    {
+      w->phys_cursor_ascent = glyph_row->ascent;
+      w->phys_cursor_height = glyph_row->height;
+
+      /* 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;
+    }
+
+  FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
+                                     new_cursor_type, new_cursor_width,
+                                     on, active_cursor);
+}
+
+
+/* Switch the display of W's cursor on or off, according to the value
+   of ON.  */
+
+static void
+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;
+      display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
+                             w->phys_cursor.x, w->phys_cursor.y);
+      UNBLOCK_INPUT;
+    }
+}
+
+
+/* Call update_window_cursor with parameter ON_P on all leaf windows
+   in the window tree rooted at W.  */
+
+static void
+update_cursor_in_window_tree (w, on_p)
+     struct window *w;
+     int on_p;
+{
+  while (w)
+    {
+      if (!NILP (w->hchild))
+       update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
+      else if (!NILP (w->vchild))
+       update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
+      else
+       update_window_cursor (w, on_p);
+
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
+    }
+}
+
+
+/* EXPORT:
+   Display the cursor on window W, or clear it, according to ON_P.
+   Don't change the cursor's position.  */
+
+void
+x_update_cursor (f, on_p)
+     struct frame *f;
+     int on_p;
+{
+  update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
+}
+
+
+/* EXPORT:
+   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.  */
+
+void
+x_clear_cursor (w)
+     struct window *w;
+{
+  if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
+    update_window_cursor (w, 0);
+}
+
+
+/* EXPORT:
+   Display the active region described by mouse_face_* according to DRAW.  */
+
+void
+show_mouse_face (dpyinfo, draw)
+     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)
+           {
+             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)
+       {
+         BLOCK_INPUT;
+         display_and_set_cursor (w, 1,
+                                 w->phys_cursor.hpos, w->phys_cursor.vpos,
+                                 w->phys_cursor.x, w->phys_cursor.y);
+         UNBLOCK_INPUT;
+       }
+    }
+
+  /* Change the mouse cursor.  */
+  if (draw == DRAW_NORMAL_TEXT)
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
+  else if (draw == DRAW_MOUSE_FACE)
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
+  else
+    FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
+}
+
+/* EXPORT:
+   Clear out the mouse-highlighted active region.
+   Redraw it un-highlighted first.  Value is non-zero if mouse
+   face was actually drawn unhighlighted.  */
+
+int
+clear_mouse_face (dpyinfo)
+     Display_Info *dpyinfo;
+{
+  int cleared = 0;
+
+  if (!NILP (dpyinfo->mouse_face_window))
+    {
+      show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
+      cleared = 1;
+    }
+
+  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;
+}
+
+
+/* EXPORT:
+   Non-zero if physical cursor of window W is within mouse face.  */
+
+int
+cursor_in_mouse_face_p (w)
+     struct window *w;
+{
+  Display_Info *dpyinfo = FRAME_X_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;
+}
+
+
+
+\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 1 /* 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 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 1 */
+
+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 1 */
+
+
+/* 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;
+}
+
+
+/* See if position X, Y is within a hot-spot of an image.  */
+
+static int
+on_hot_spot_p (hot_spot, x, y)
+     Lisp_Object hot_spot;
+     int x, y;
+{
+  if (!CONSP (hot_spot))
+    return 0;
+
+  if (EQ (XCAR (hot_spot), Qrect))
+    {
+      /* CDR is (Top-Left . Bottom-Right) = ((x0 . y0) . (x1 . y1))  */
+      Lisp_Object rect = XCDR (hot_spot);
+      Lisp_Object tem;
+      if (!CONSP (rect))
+       return 0;
+      if (!CONSP (XCAR (rect)))
+       return 0;
+      if (!CONSP (XCDR (rect)))
+       return 0;
+      if (!(tem = XCAR (XCAR (rect)), INTEGERP (tem) && x >= XINT (tem)))
+       return 0;
+      if (!(tem = XCDR (XCAR (rect)), INTEGERP (tem) && y >= XINT (tem)))
+       return 0;
+      if (!(tem = XCAR (XCDR (rect)), INTEGERP (tem) && x <= XINT (tem)))
+       return 0;
+      if (!(tem = XCDR (XCDR (rect)), INTEGERP (tem) && y <= XINT (tem)))
+       return 0;
+      return 1;
+    }
+  else if (EQ (XCAR (hot_spot), Qcircle))
+    {
+      /* CDR is (Center . Radius) = ((x0 . y0) . r) */
+      Lisp_Object circ = XCDR (hot_spot);
+      Lisp_Object lr, lx0, ly0;
+      if (CONSP (circ)
+         && CONSP (XCAR (circ))
+         && (lr = XCDR (circ), INTEGERP (lr) || FLOATP (lr))
+         && (lx0 = XCAR (XCAR (circ)), INTEGERP (lx0))
+         && (ly0 = XCDR (XCAR (circ)), INTEGERP (ly0)))
+       {
+         double r = XFLOATINT (lr);
+         double dx = XINT (lx0) - x;
+         double dy = XINT (ly0) - y;
+         return (dx * dx + dy * dy <= r * r);
+       }
+    }
+  else if (EQ (XCAR (hot_spot), Qpoly))
+    {
+      /* CDR is [x0 y0 x1 y1 x2 y2 ...x(n-1) y(n-1)] */
+      if (VECTORP (XCDR (hot_spot)))
+       {
+         struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
+         Lisp_Object *poly = v->contents;
+         int n = v->size;
+         int i;
+         int inside = 0;
+         Lisp_Object lx, ly;
+         int x0, y0;
+
+         /* Need an even number of coordinates, and at least 3 edges.  */
+         if (n < 6 || n & 1) 
+           return 0;
+
+         /* Count edge segments intersecting line from (X,Y) to (X,infinity).
+            If count is odd, we are inside polygon.  Pixels on edges
+            may or may not be included depending on actual geometry of the
+            polygon.  */
+         if ((lx = poly[n-2], !INTEGERP (lx))
+             || (ly = poly[n-1], !INTEGERP (lx)))
+           return 0;
+         x0 = XINT (lx), y0 = XINT (ly);
+         for (i = 0; i < n; i += 2)
+           {
+             int x1 = x0, y1 = y0;
+             if ((lx = poly[i], !INTEGERP (lx))
+                 || (ly = poly[i+1], !INTEGERP (ly)))
+               return 0;
+             x0 = XINT (lx), y0 = XINT (ly);
+
+             /* Does this segment cross the X line?  */
+             if (x0 >= x)
+               {
+                 if (x1 >= x)
+                   continue;
+               }
+             else if (x1 < x)
+               continue;
+             if (y > y0 && y > y1)
+               continue;
+             if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
+               inside = !inside;
+           }
+         return inside;
+       }
+    }
+  else
+    return 0;
+}
+
+Lisp_Object
+find_hot_spot (map, x, y)
+     Lisp_Object map;
+     int x, y;
+{
+  while (CONSP (map))
+    {
+      if (CONSP (XCAR (map))
+         && on_hot_spot_p (XCAR (XCAR (map)), x, y))
+       return XCAR (map);
+      map = XCDR (map);
+    }
+  
+  return Qnil;
+}
+
+DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
+       3, 3, 0,
+       doc: /* Lookup in image map MAP coordinates X and Y.  
+An image map is an alist where each element has the format (AREA ID PLIST).
+An AREA is specified as either a rectangle, a circle, or a polygon:
+A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the
+pixel coordinates of the upper left and bottom right corners.
+A circle is a cons (circle . ((x0 . y0) . r)) specifying the center
+and the radius of the circle; r may be a float or integer.
+A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the
+vector describes one corner in the polygon.
+Returns the alist element for the first matching AREA in MAP.  */)
+  (map, x, y)
+     Lisp_Object map;
+     Lisp_Object x, y;
+{
+  int ix, iy;
+  if (NILP (map))
+    return Qnil;
+
+  if (!INTEGERP (x))
+    wrong_type_argument (Qintegerp, x);
+  if (!INTEGERP (y))
+    wrong_type_argument (Qintegerp, y);
+
+  return find_hot_spot (map, XINT (x), XINT (y));
+}
+
+
+/* Display frame CURSOR, optionally using shape defined by POINTER.  */
+static void
+define_frame_cursor1 (f, cursor, pointer)
+     struct frame *f;
+     Cursor cursor;
+     Lisp_Object pointer;
+{
+  if (!NILP (pointer))
+    {
+      if (EQ (pointer, Qarrow))
+       cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+      else if (EQ (pointer, Qhand))
+       cursor = FRAME_X_OUTPUT (f)->hand_cursor;
+      else if (EQ (pointer, Qtext))
+       cursor = FRAME_X_OUTPUT (f)->text_cursor;
+      else if (EQ (pointer, intern ("hdrag")))
+       cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+#ifdef HAVE_X_WINDOWS
+      else if (EQ (pointer, intern ("vdrag")))
+       cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
+#endif
+      else if (EQ (pointer, intern ("hourglass")))
+       cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
+      else if (EQ (pointer, Qmodeline))
+       cursor = FRAME_X_OUTPUT (f)->modeline_cursor;
+      else
+       cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+    }
+
+#ifndef HAVE_CARBON
+  if (cursor != No_Cursor)
+#else
+  if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
+#endif
+    FRAME_RIF (f)->define_frame_cursor (f, cursor);
+}
+
+/* Take proper action when mouse has moved to the mode or header line
+   or marginal area AREA of window W, x-position X and y-position Y.
+   X is relative to the start of the text display area of W, so the
+   width of bitmap areas and scroll bars must be subtracted to get a
+   position relative to the start of the mode line.  */
+
+static void
+note_mode_line_or_margin_highlight (w, x, y, area)
+     struct window *w;
+     int x, y;
+     enum window_part area;
+{
+  struct frame *f = XFRAME (w->frame);
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+  Lisp_Object pointer = Qnil;
+  int charpos, dx, dy, width, height;
+  Lisp_Object string, object = Qnil;
+  Lisp_Object pos, help, image;
+
+  if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
+    string = mode_line_string (w, area, &x, &y, &charpos,
+                              &object, &dx, &dy, &width, &height);
+  else
+    {
+      x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
+      string = marginal_area_string (w, area, &x, &y, &charpos,
+                                    &object, &dx, &dy, &width, &height);
+    }
+
+  help = Qnil;
+
+  if (IMAGEP (object))
+    {
+      Lisp_Object image_map, hotspot;
+      if ((image_map = Fplist_get (XCDR (object), QCmap),
+          !NILP (image_map))
+         && (hotspot = find_hot_spot (image_map, dx, dy),
+             CONSP (hotspot))
+         && (hotspot = XCDR (hotspot), CONSP (hotspot)))
+       {
+         Lisp_Object area_id, plist;
+
+         area_id = XCAR (hotspot);
+         /* Could check AREA_ID to see if we enter/leave this hot-spot.
+            If so, we could look for mouse-enter, mouse-leave
+            properties in PLIST (and do something...).  */
+         if ((plist = XCDR (hotspot), CONSP (plist)))
+           {
+             pointer = Fplist_get (plist, Qpointer);
+             if (NILP (pointer))
+               pointer = Qhand;
+             help = Fplist_get (plist, Qhelp_echo);
+             if (!NILP (help))
+               {
+                 help_echo_string = help;
+                 /* Is this correct?  ++kfs */
+                 XSETWINDOW (help_echo_window, w);
+                 help_echo_object = w->buffer;
+                 help_echo_pos = charpos;
+               }
+           }
+         if (NILP (pointer))
+           pointer = Fplist_get (XCDR (object), QCpointer);
+       }
+    }
+
+  if (STRINGP (string))
+    {
+      pos = make_number (charpos);
+      /* 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_string to the help string.  */
+      help = Fget_text_property (pos, Qhelp_echo, string);
+      if (!NILP (help))
+       {
+         help_echo_string = help;
+         XSETWINDOW (help_echo_window, w);
+         help_echo_object = string;
+         help_echo_pos = charpos;
+       }
+
+      if (NILP (pointer))
+       pointer = Fget_text_property (pos, Qpointer, string);
+
+     /* Change the mouse pointer according to what is under X/Y.  */
+      if (NILP (pointer) && area == ON_MODE_LINE)
+       {
+         Lisp_Object map;
+         map = Fget_text_property (pos, Qlocal_map, string);
+         if (!KEYMAPP (map))
+           map = Fget_text_property (pos, Qkeymap, string);
+         if (!KEYMAPP (map))
+           cursor = dpyinfo->vertical_scroll_bar_cursor;
+       }
+    }
+
+  define_frame_cursor1 (f, cursor, pointer);
+}
+
+
+/* EXPORT:
+   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.  */
+
+void
+note_mouse_highlight (f, x, y)
+     struct frame *f;
+     int x, y;
+{
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  enum window_part part;
+  Lisp_Object window;
+  struct window *w;
+  Cursor cursor = No_Cursor;
+  Lisp_Object pointer = Qnil;  /* Takes precedence over cursor!  */
+  struct buffer *b;
+
+  /* When a menu is active, don't highlight because this looks odd.  */
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
+  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, &part, 0, 0, 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_string. It will get recomputed below.  */
+  help_echo_string = 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, header line or margin?  */
+  if (part == ON_MODE_LINE || part == ON_HEADER_LINE
+      || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
+    {
+      note_mode_line_or_margin_highlight (w, x, y, part);
+      return;
+    }
+
+  if (part == ON_VERTICAL_BORDER)
+    cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+  else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
+    cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+  else
+    cursor = FRAME_X_OUTPUT (f)->text_cursor;
+
+  /* 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 (part == ON_TEXT
+      && 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, dx, dy, 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, &dx, &dy, &area);
+
+      /* Look for :pointer property on image.  */
+      if (glyph != NULL && glyph->type == IMAGE_GLYPH)
+       {
+         struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
+         if (img != NULL && IMAGEP (img->spec))
+           {
+             Lisp_Object image_map, hotspot;
+             if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
+                  !NILP (image_map))
+                 && (hotspot = find_hot_spot (image_map, dx, dy),
+                     CONSP (hotspot))
+                 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
+               {
+                 Lisp_Object area_id, plist;
+
+                 area_id = XCAR (hotspot);
+                 /* Could check AREA_ID to see if we enter/leave this hot-spot.
+                    If so, we could look for mouse-enter, mouse-leave
+                    properties in PLIST (and do something...).  */
+                 if ((plist = XCDR (hotspot), CONSP (plist)))
+                   {
+                     pointer = Fplist_get (plist, Qpointer);
+                     if (NILP (pointer))
+                       pointer = Qhand;
+                     help_echo_string = Fplist_get (plist, Qhelp_echo);
+                     if (!NILP (help_echo_string))
+                       {
+                         help_echo_window = window;
+                         help_echo_object = glyph->object;
+                         help_echo_pos = glyph->charpos;
+                       }
+                   }
+               }
+             if (NILP (pointer))
+               pointer = Fplist_get (XCDR (img->spec), QCpointer);
+           }
+       }
+
+      /* Clear mouse face if X/Y not over text.  */
+      if (glyph == NULL
+         || area != TEXT_AREA
+         || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
+       {
+         if (clear_mouse_face (dpyinfo))
+           cursor = No_Cursor;
+         if (NILP (pointer))
+           {
+             if (area != TEXT_AREA)
+               cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+             else
+               pointer = Vvoid_text_area_pointer;
+           }
+         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));
+
+      if (same_region)
+       cursor = No_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 only 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.  */
+         if (clear_mouse_face (dpyinfo))
+           cursor = No_Cursor;
+
+         /* 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);
+             cursor = No_Cursor;
+           }
+         /* 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);
+             cursor = No_Cursor;
+           }
+         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);
+             cursor = No_Cursor;
+           }
+         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);
+                 cursor = No_Cursor;
+               }
+           }
+       }
+
+    check_help_echo:
+
+      /* Look for a `help-echo' property.  */
+      if (NILP (help_echo_string)) {
+       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_string = 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_string = help;
+               help_echo_window = window;
+               help_echo_object = object;
+               help_echo_pos = charpos;
+             }
+         }
+      }
+
+      /* Look for a `pointer' property.  */
+      if (NILP (pointer))
+       {
+         /* Check overlays first.  */
+         for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
+           pointer = Foverlay_get (overlay_vec[i], Qpointer);
+
+         if (NILP (pointer))
+           {
+             Lisp_Object object = glyph->object;
+             int charpos = glyph->charpos;
+
+             /* Try text properties.  */
+             if (STRINGP (object)
+                 && charpos >= 0
+                 && charpos < SCHARS (object))
+               {
+                 pointer = Fget_text_property (make_number (charpos),
+                                               Qpointer, object);
+                 if (NILP (pointer))
+                   {
+                     /* If the string itself doesn't specify a pointer,
+                        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)
+                       pointer = Fget_char_property (make_number (pos),
+                                                     Qpointer, w->buffer);
+                   }
+               }
+             else if (BUFFERP (object)
+                      && charpos >= BEGV
+                      && charpos < ZV)
+               pointer = Fget_text_property (make_number (charpos),
+                                             Qpointer, object);
+           }
+       }
+
+      BEGV = obegv;
+      ZV = ozv;
+      current_buffer = obuf;
+    }
+
+ set_cursor:
+
+  define_frame_cursor1 (f, cursor, pointer);
+}
+
+
+/* EXPORT for RIF:
+   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.  */
+
+void
+x_clear_window_mouse_face (w)
+     struct window *w;
+{
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+  Lisp_Object window;
+
+  BLOCK_INPUT;
+  XSETWINDOW (window, w);
+  if (EQ (window, dpyinfo->mouse_face_window))
+    clear_mouse_face (dpyinfo);
+  UNBLOCK_INPUT;
+}
+
+
+/* EXPORT:
+   Just discard the mouse face information for frame F, if any.
+   This is used when the size of F is changed.  */
+
+void
+cancel_mouse_face (f)
+     struct frame *f;
+{
+  Lisp_Object window;
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+  window = dpyinfo->mouse_face_window;
+  if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
+    {
+      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;
+    }
+}
+
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+\f
+/***********************************************************************
+                          Exposure Events
+ ***********************************************************************/
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* 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;
+     XRectangle *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.  */
+    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.  */
+      start_x = window_box_left_offset (w, area);
+      x = start_x;
+      if (area == TEXT_AREA)
+       x += row->x;
+
+      /* Find the first glyph that must be redrawn.  */
+      while (first < end
+            && x + first->pixel_width < r->x)
+       {
+         x += first->pixel_width;
+         ++first;
+       }
+
+      /* Find the last one.  */
+      last = first;
+      first_x = x;
+      while (last < end
+            && x < r->x + r->width)
+       {
+         x += last->pixel_width;
+         ++last;
+       }
+
+      /* Repaint.  */
+      if (last > first)
+       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;
+     XRectangle *r;
+{
+  xassert (row->enabled_p);
+
+  if (row->mode_line_p || w->pseudo_window_p)
+    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;
+}
+
+
+/* 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);
+      }
+}
+
+
+/* Return non-zero if W's cursor intersects rectangle R.  */
+
+static int
+phys_cursor_in_rect_p (w, r)
+     struct window *w;
+     XRectangle *r;
+{
+  XRectangle cr, result;
+  struct glyph *cursor_glyph;
+
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph)
+    {
+      /* r is relative to W's box, but w->phys_cursor.x is relative 
+        to left edge of W's TEXT area.  Adjust it.  */
+      cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
+      cr.y = w->phys_cursor.y;
+      cr.width = cursor_glyph->pixel_width;
+      cr.height = w->phys_cursor_height;
+      /* ++KFS: W32 version used W32-specific IntersectRect here, but 
+        I assume the effect is the same -- and this is portable.  */
+      return x_intersect_rectangles (&cr, r, &result);
+    }
+  else
+    return 0;
+}
+
+
+/* EXPORT:
+   Draw a vertical window border to the right of window W if W doesn't
+   have vertical scroll bars.  */
+
+void
+x_draw_vertical_border (w)
+     struct window *w;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  
+  /* We could do better, if we knew what type of scroll-bar the adjacent
+     windows (on either side) have...  But we don't :-( 
+     However, I think this works ok.  ++KFS 2003-04-25 */
+
+  /* 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)
+      && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
+    {
+      int x0, x1, y0, y1;
+
+      window_box_edges (w, -1, &x0, &y0, &x1, &y1);
+      y1 -= 1;
+
+      FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
+    }
+  else if (!WINDOW_LEFTMOST_P (w)
+          && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+    {
+      int x0, x1, y0, y1;
+
+      window_box_edges (w, -1, &x0, &y0, &x1, &y1);
+      y1 -= 1;
+
+      FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
+    }
+}
+
+
+/* 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;
+     XRectangle *fr;
+{
+  struct frame *f = XFRAME (w->frame);
+  XRectangle 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.x = WINDOW_LEFT_EDGE_X (w);
+  wr.y = WINDOW_TOP_EDGE_Y (w);
+  wr.width = WINDOW_TOTAL_WIDTH (w);
+  wr.height = WINDOW_TOTAL_HEIGHT (w);
+
+  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.x, r.y, r.width, r.height));
+
+      /* Convert to window coordinates.  */
+      r.x -= WINDOW_LEFT_EDGE_X (w);
+      r.y -= WINDOW_TOP_EDGE_Y (w);
+
+      /* Turn off the cursor.  */
+      if (!w->pseudo_window_p
+         && 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.y && y0 < r.y + r.height)
+             || (y1 > r.y && y1 < r.y + r.height)
+             || (r.y >= y0 && r.y < y1)
+             || (r.y + r.height > y0 && r.y + r.height < 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.y + r.height)
+       {
+         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)
+           update_window_cursor (w, 1);
+       }
+    }
+
+#ifdef HAVE_CARBON
+  /* Display scroll bar for this window.  */
+  if (!NILP (w->vertical_scroll_bar))
+    {
+      /* ++KFS:
+        If this doesn't work here (maybe some header files are missing),
+        make a function in macterm.c and call it to do the job! */
+      ControlHandle ch
+       = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
+
+      Draw1Control (ch);
+    }
+#endif
+
+  return mouse_face_overwritten_p;
+}
+
+
+
+/* Redraw (parts) of all windows in the window tree rooted at W that
+   intersect R.  R contains frame pixel coordinates.  Value is
+   non-zero if the exposure overwrites mouse-face.  */
+
+static int
+expose_window_tree (w, r)
+     struct window *w;
+     XRectangle *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;
+}
+
+
+/* EXPORT:
+   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.  */
+
+void
+expose_frame (f, x, y, w, h)
+     struct frame *f;
+     int x, y, w, h;
+{
+  XRectangle r;
+  int mouse_face_overwritten_p = 0;
+
+  TRACE ((stderr, "expose_frame "));
+
+  /* No need to redraw if frame will be redrawn soon.  */
+  if (FRAME_GARBAGED_P (f))
+    {
+      TRACE ((stderr, " garbaged\n"));
+      return;
+    }
+
+#ifdef HAVE_CARBON
+  /* 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);
+#endif
+
+  /* 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 (w == 0 || h == 0)
+    {
+      r.x = r.y = 0;
+      r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f);
+      r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f);
+    }
+  else
+    {
+      r.x = x;
+      r.y = y;
+      r.width = w;
+      r.height = h;
+    }
+
+  TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
+  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);
+
+#ifdef HAVE_X_WINDOWS
+#ifndef MSDOS
+#ifndef USE_X_TOOLKIT
+  if (WINDOWP (f->menu_bar_window))
+    mouse_face_overwritten_p
+      |= expose_window (XWINDOW (f->menu_bar_window), &r);
+#endif /* not USE_X_TOOLKIT */
+#endif
+#endif
+
+  /* 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))
+    {
+      Display_Info *dpyinfo = FRAME_X_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);
+       }
+    }
+}
+
+
+/* EXPORT:
+   Determine the intersection of two rectangles R1 and R2.  Return
+   the intersection in *RESULT.  Value is non-zero if RESULT is not
+   empty.  */
+
+int
+x_intersect_rectangles (r1, r2, result)
+     XRectangle *r1, *r2, *result;
+{
+  XRectangle *left, *right;
+  XRectangle *upper, *lower;
+  int intersection_p = 0;
+
+  /* Rearrange so that R1 is the left-most rectangle.  */
+  if (r1->x < r2->x)
+    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->x <= left->x + left->width)
+    {
+      result->x = right->x;
+
+      /* The right end of the intersection is the minimum of the
+        the right ends of left and right.  */
+      result->width = (min (left->x + left->width, right->x + right->width)
+                      - result->x);
+
+      /* Same game for Y.  */
+      if (r1->y < r2->y)
+       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->y <= upper->y + upper->height)
+       {
+         result->y = lower->y;
+
+         /* The lower end of the intersection is the minimum of the lower
+            ends of upper and lower.  */
+         result->height = (min (lower->y + lower->height,
+                                upper->y + upper->height)
+                           - result->y);
+         intersection_p = 1;
+       }
+    }
+
+  return intersection_p;
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+\f
+/***********************************************************************
+                           Initialization
+ ***********************************************************************/
+
+void
+syms_of_xdisp ()
+{
+  Vwith_echo_area_save_vector = Qnil;
+  staticpro (&Vwith_echo_area_save_vector);
+
+  Vmessage_stack = Qnil;
+  staticpro (&Vmessage_stack);
+
+  Qinhibit_redisplay = intern ("inhibit-redisplay");
+  staticpro (&Qinhibit_redisplay);
+
+  message_dolog_marker1 = Fmake_marker ();
+  staticpro (&message_dolog_marker1);
+  message_dolog_marker2 = Fmake_marker ();
+  staticpro (&message_dolog_marker2);
+  message_dolog_marker3 = Fmake_marker ();
+  staticpro (&message_dolog_marker3);
+
+#if GLYPH_DEBUG
+  defsubr (&Sdump_frame_glyph_matrix);
+  defsubr (&Sdump_glyph_matrix);
+  defsubr (&Sdump_glyph_row);
+  defsubr (&Sdump_tool_bar_row);
+  defsubr (&Strace_redisplay);
+  defsubr (&Strace_to_stderr);
+#endif
+#ifdef HAVE_WINDOW_SYSTEM
+  defsubr (&Stool_bar_lines_needed);
+  defsubr (&Slookup_image_map);
+#endif
+  defsubr (&Sformat_mode_line);
+
+  staticpro (&Qmenu_bar_update_hook);
+  Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
+
+  staticpro (&Qoverriding_terminal_local_map);
+  Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
+
+  staticpro (&Qoverriding_local_map);
+  Qoverriding_local_map = intern ("overriding-local-map");
+
+  staticpro (&Qwindow_scroll_functions);
+  Qwindow_scroll_functions = intern ("window-scroll-functions");
+
+  staticpro (&Qredisplay_end_trigger_functions);
+  Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
+
+  staticpro (&Qinhibit_point_motion_hooks);
+  Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
+
+  QCdata = intern (":data");
+  staticpro (&QCdata);
+  Qdisplay = intern ("display");
+  staticpro (&Qdisplay);
+  Qspace_width = intern ("space-width");
+  staticpro (&Qspace_width);
+  Qraise = intern ("raise");
+  staticpro (&Qraise);
+  Qspace = intern ("space");
+  staticpro (&Qspace);
+  Qmargin = intern ("margin");
+  staticpro (&Qmargin);
+  Qpointer = intern ("pointer");
+  staticpro (&Qpointer);
+  Qleft_margin = intern ("left-margin");
+  staticpro (&Qleft_margin);
+  Qright_margin = intern ("right-margin");
+  staticpro (&Qright_margin);
+  QCalign_to = intern (":align-to");
   staticpro (&QCalign_to);
-  Qrelative_width = intern ("relative-width");
-  staticpro (&Qrelative_width);
   QCrelative_width = intern (":relative-width");
   staticpro (&QCrelative_width);
   QCrelative_height = intern (":relative-height");
@@ -18000,6 +21444,16 @@ syms_of_xdisp ()
   staticpro (&Qtrailing_whitespace);
   Qimage = intern ("image");
   staticpro (&Qimage);
+  QCmap = intern (":map");
+  staticpro (&QCmap);
+  QCpointer = intern (":pointer");
+  staticpro (&QCpointer);
+  Qrect = intern ("rect");
+  staticpro (&Qrect);
+  Qcircle = intern ("circle");
+  staticpro (&Qcircle);
+  Qpoly = intern ("poly");
+  staticpro (&Qpoly);
   Qmessage_truncate_lines = intern ("message-truncate-lines");
   staticpro (&Qmessage_truncate_lines);
   Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
@@ -18024,6 +21478,12 @@ syms_of_xdisp ()
   staticpro (&Qbox);
   Qhollow = intern ("hollow");
   staticpro (&Qhollow);
+  Qhand = intern ("hand");
+  staticpro (&Qhand);
+  Qarrow = intern ("arrow");
+  staticpro (&Qarrow);
+  Qtext = intern ("text");
+  staticpro (&Qtext);
   Qrisky_local_variable = intern ("risky-local-variable");
   staticpro (&Qrisky_local_variable);
   Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
@@ -18054,11 +21514,35 @@ syms_of_xdisp ()
   mode_line_string_list = Qnil;
   staticpro (&mode_line_string_list);
 
+  help_echo_string = Qnil;
+  staticpro (&help_echo_string);
+  help_echo_object = Qnil;
+  staticpro (&help_echo_object);
+  help_echo_window = Qnil;
+  staticpro (&help_echo_window);
+  previous_help_echo_string = Qnil;
+  staticpro (&previous_help_echo_string);
+  help_echo_pos = -1;
+
+#ifdef HAVE_WINDOW_SYSTEM
+  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;
+#endif
+
   DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
     doc: /* Non-nil means highlight trailing whitespace.
 The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
+  DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
+    doc: /* The pointer shape to show in void text areas.
+Nil means to show the text pointer.  Other options are `arrow', `text',
+`hand', `vdrag', `hdrag', `modeline', and `hourglass'.  */); 
+  Vvoid_text_area_pointer = Qarrow;
+
   DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
     doc: /* Non-nil means don't actually do any redisplay.
 This is used for internal purposes.  */);
@@ -18097,6 +21581,11 @@ Recenter the window whenever point gets within this many lines
 of the top or bottom of the window.  */);
   scroll_margin = 0;
 
+  DEFVAR_LISP ("display-pixels-per-inch",  &Vdisplay_pixels_per_inch,
+    doc: /* Pixels per inch on current display.
+Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI).  */);
+  Vdisplay_pixels_per_inch = make_float (72.0);
+
 #if GLYPH_DEBUG
   DEFVAR_INT ("debug-end-pos", &debug_end_pos, doc: /* Don't ask.  */);
 #endif
@@ -18141,6 +21630,7 @@ This variable is not guaranteed to be accurate except while processing
 This variable has the same structure as `mode-line-format' (which see),
 and is used only on frames for which no explicit name has been set
 \(see `modify-frame-parameters').  */);
+
   DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
     doc: /* Template for displaying the title bar of an iconified frame.
 \(Assuming the window manager supports this feature.)
@@ -18179,6 +21669,10 @@ and its new display-start position.  Note that the value of `window-end'
 is not valid when these functions are called.  */);
   Vwindow_scroll_functions = Qnil;
 
+  DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
+    doc: /* *Non-nil means autoselect window with mouse pointer.  */);
+  mouse_autoselect_window = 0;
+
   DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
     doc: /* *Non-nil means automatically resize tool-bars.
 This increases a tool-bar's height if not all tool-bar items are visible.
@@ -18338,15 +21832,15 @@ init_xdisp ()
       struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
       int i;
 
-      XWINDOW (root_window)->top = make_number (FRAME_TOP_MARGIN (f));
+      XWINDOW (root_window)->top_line = make_number (FRAME_TOP_MARGIN (f));
       set_window_height (root_window,
-                        FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
+                        FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f),
                         0);
-      mini_w->top = make_number (FRAME_HEIGHT (f) - 1);
+      mini_w->top_line = make_number (FRAME_LINES (f) - 1);
       set_window_height (minibuf_window, 1, 0);
 
-      XWINDOW (root_window)->width = make_number (FRAME_WIDTH (f));
-      mini_w->width = make_number (FRAME_WIDTH (f));
+      XWINDOW (root_window)->total_cols = make_number (FRAME_COLS (f));
+      mini_w->total_cols = make_number (FRAME_COLS (f));
 
       scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
       scratch_glyph_row.glyphs[TEXT_AREA + 1]
@@ -18370,3 +21864,5 @@ init_xdisp ()
 }
 
 
+/* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b
+   (do not change this comment) */