* frame.c (x_mouse_grabbed): New function.
[bpt/emacs.git] / src / xdisp.c
index ec1dbc4..c4f7b20 100644 (file)
@@ -1,7 +1,6 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
-Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -299,19 +298,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "font.h"
 #include "fontset.h"
 #include "blockinput.h"
-
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#endif
-#ifdef HAVE_NTGUI
-#include "w32term.h"
-#endif
-#ifdef HAVE_NS
-#include "nsterm.h"
-#endif
-#ifdef USE_GTK
-#include "gtkutil.h"
-#endif
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
 
 #ifndef FRAME_X_OUTPUT
 #define FRAME_X_OUTPUT(f) ((f)->output_data.x)
@@ -522,10 +511,6 @@ int update_mode_lines;
 
 int windows_or_buffers_changed;
 
-/* Nonzero means a frame's cursor type has been changed.  */
-
-int cursor_type_changed;
-
 /* Nonzero after display_mode_line if %l was used and it displayed a
    line number.  */
 
@@ -583,12 +568,6 @@ static int last_height;
 
 int help_echo_showing_p;
 
-/* If >= 0, computed, exact values of mode-line and header-line height
-   to use in the macros CURRENT_MODE_LINE_HEIGHT and
-   CURRENT_HEADER_LINE_HEIGHT.  */
-
-int current_mode_line_height, current_header_line_height;
-
 /* The maximum distance to look ahead for text properties.  Values
    that are too small let us call compute_char_face and similar
    functions too often which is expensive.  Values that are too large
@@ -760,6 +739,8 @@ Lisp_Object previous_help_echo_string;
 
 /* Platform-independent portion of hourglass implementation. */
 
+#ifdef HAVE_WINDOW_SYSTEM
+
 /* Non-zero means an hourglass cursor is currently shown.  */
 int hourglass_shown_p;
 
@@ -767,6 +748,8 @@ int hourglass_shown_p;
    an hourglass cursor on all frames.  */
 struct atimer *hourglass_atimer;
 
+#endif /* HAVE_WINDOW_SYSTEM */
+
 /* Name of the face used to display glyphless characters.  */
 Lisp_Object Qglyphless_char;
 
@@ -776,14 +759,17 @@ static Lisp_Object Qglyphless_char_display;
 /* Method symbols for Vglyphless_char_display.  */
 static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width;
 
-/* Default pixel width of `thin-space' display method.  */
-#define THIN_SPACE_WIDTH 1
-
 /* Default number of seconds to wait before displaying an hourglass
    cursor.  */
 #define DEFAULT_HOURGLASS_DELAY 1
 
-\f
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Default pixel width of `thin-space' display method.  */
+#define THIN_SPACE_WIDTH 1
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
 /* Function prototypes.  */
 
 static void setup_for_ellipsis (struct it *, int);
@@ -804,7 +790,6 @@ static void pint2str (char *, int, ptrdiff_t);
 static void pint2hrstr (char *, int, ptrdiff_t);
 static struct text_pos run_window_scroll_functions (Lisp_Object,
                                                     struct text_pos);
-static void reconsider_clip_changes (struct window *, struct buffer *);
 static int text_outside_line_unchanged_p (struct window *,
                                          ptrdiff_t, ptrdiff_t);
 static void store_mode_line_noprop_char (char);
@@ -813,21 +798,20 @@ static void handle_stop (struct it *);
 static void handle_stop_backwards (struct it *, ptrdiff_t);
 static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
 static void ensure_echo_area_buffers (void);
-static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object);
+static void unwind_with_echo_area_buffer (Lisp_Object);
 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
 static int with_echo_area_buffer (struct window *, int,
                                   int (*) (ptrdiff_t, Lisp_Object),
                                   ptrdiff_t, Lisp_Object);
 static void clear_garbaged_frames (void);
 static int current_message_1 (ptrdiff_t, Lisp_Object);
-static void pop_message (void);
 static int truncate_message_1 (ptrdiff_t, Lisp_Object);
 static void set_message (Lisp_Object);
 static int set_message_1 (ptrdiff_t, Lisp_Object);
 static int display_echo_area (struct window *);
 static int display_echo_area_1 (ptrdiff_t, Lisp_Object);
 static int resize_mini_window_1 (ptrdiff_t, Lisp_Object);
-static Lisp_Object unwind_redisplay (Lisp_Object);
+static void unwind_redisplay (void);
 static int string_char_and_length (const unsigned char *, int *);
 static struct text_pos display_prop_end (struct it *, Lisp_Object,
                                          struct text_pos);
@@ -928,11 +912,8 @@ static int in_ellipses_for_invisible_text_p (struct display_pos *,
 #ifdef HAVE_WINDOW_SYSTEM
 
 static void x_consider_frame_title (Lisp_Object);
-static int tool_bar_lines_needed (struct frame *, int *);
 static void update_tool_bar (struct frame *, int);
-static void build_desired_tool_bar_string (struct frame *f);
 static int redisplay_tool_bar (struct frame *);
-static void display_tool_bar_line (struct it *, int);
 static void notice_overwritten_cursor (struct window *,
                                        enum glyph_row_area,
                                        int, int, int, int);
@@ -968,12 +949,12 @@ window_text_bottom_y (struct window *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.  */
+/* Return the pixel width of display area AREA of window W.
+   ANY_AREA means return the total width of W, not including
+   fringes to the left and right of the window.  */
 
 int
-window_box_width (struct window *w, int area)
+window_box_width (struct window *w, enum glyph_row_area area)
 {
   int cols = w->total_cols;
   int pixels = 0;
@@ -984,22 +965,18 @@ window_box_width (struct window *w, int area)
 
       if (area == TEXT_AREA)
        {
-         if (INTEGERP (w->left_margin_cols))
-           cols -= XFASTINT (w->left_margin_cols);
-         if (INTEGERP (w->right_margin_cols))
-           cols -= XFASTINT (w->right_margin_cols);
+         cols -= max (0, w->left_margin_cols);
+         cols -= max (0, w->right_margin_cols);
          pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
        }
       else if (area == LEFT_MARGIN_AREA)
        {
-         cols = (INTEGERP (w->left_margin_cols)
-                  ? XFASTINT (w->left_margin_cols) : 0);
+         cols = max (0, w->left_margin_cols);
          pixels = 0;
        }
       else if (area == RIGHT_MARGIN_AREA)
        {
-         cols = (INTEGERP (w->right_margin_cols)
-                  ? XFASTINT (w->right_margin_cols) : 0);
+         cols = max (0, w->right_margin_cols);
          pixels = 0;
        }
     }
@@ -1055,11 +1032,11 @@ window_box_height (struct window *w)
 }
 
 /* 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
+   area AREA of window W.  ANY_AREA means return the left edge of the
    whole window, to the right of the left fringe of W.  */
 
 int
-window_box_left_offset (struct window *w, int area)
+window_box_left_offset (struct window *w, enum glyph_row_area area)
 {
   int x;
 
@@ -1087,21 +1064,21 @@ window_box_left_offset (struct window *w, int area)
 
 
 /* Return the window-relative coordinate of the right edge of display
-   area AREA of window W.  AREA < 0 means return the right edge of the
+   area AREA of window W.  ANY_AREA means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
 int
-window_box_right_offset (struct window *w, int area)
+window_box_right_offset (struct window *w, enum glyph_row_area 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
+   area AREA of window W.  ANY_AREA means return the left edge of the
    whole window, to the right of the left fringe of W.  */
 
 int
-window_box_left (struct window *w, int area)
+window_box_left (struct window *w, enum glyph_row_area area)
 {
   struct frame *f = XFRAME (w->frame);
   int x;
@@ -1117,25 +1094,25 @@ window_box_left (struct window *w, int area)
 
 
 /* Return the frame-relative coordinate of the right edge of display
-   area AREA of window W.  AREA < 0 means return the right edge of the
+   area AREA of window W.  ANY_AREA means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
 int
-window_box_right (struct window *w, int area)
+window_box_right (struct window *w, enum glyph_row_area 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
+   mode lines, in frame-relative coordinates.  ANY_AREA means the
    whole window, not including the left and right fringes of
    the window.  Return in *BOX_X and *BOX_Y the frame-relative pixel
    coordinates of the upper-left corner of the box.  Return in
    *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box.  */
 
 void
-window_box (struct window *w, int area, int *box_x, int *box_y,
-           int *box_width, int *box_height)
+window_box (struct window *w, enum glyph_row_area area, int *box_x,
+           int *box_y, int *box_width, int *box_height)
 {
   if (box_width)
     *box_width = window_box_width (w, area);
@@ -1151,27 +1128,27 @@ window_box (struct window *w, int area, int *box_x, int *box_y,
     }
 }
 
+#ifdef HAVE_WINDOW_SYSTEM
 
 /* Get the bounding box of the display area AREA of window W, without
-   mode lines.  AREA < 0 means the whole window, not including the
-   left and right fringe of the window.  Return in *TOP_LEFT_X
+   mode lines and both fringes of the window.  Return in *TOP_LEFT_X
    and TOP_LEFT_Y the frame-relative pixel coordinates of the
    upper-left corner of the box.  Return in *BOTTOM_RIGHT_X, and
    *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
    box.  */
 
 static void
-window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y,
-                  int *bottom_right_x, int *bottom_right_y)
+window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
+                 int *bottom_right_x, int *bottom_right_y)
 {
-  window_box (w, area, top_left_x, top_left_y, bottom_right_x,
-             bottom_right_y);
+  window_box (w, ANY_AREA, top_left_x, top_left_y,
+             bottom_right_x, bottom_right_y);
   *bottom_right_x += *top_left_x;
   *bottom_right_y += *top_left_y;
 }
 
+#endif /* HAVE_WINDOW_SYSTEM */
 
-\f
 /***********************************************************************
                              Utilities
  ***********************************************************************/
@@ -1232,6 +1209,52 @@ Value is the height in pixels of the line at point.  */)
   return make_number (line_bottom_y (&it));
 }
 
+/* Return the default pixel height of text lines in window W.  The
+   value is the canonical height of the W frame's default font, plus
+   any extra space required by the line-spacing variable or frame
+   parameter.
+
+   Implementation note: this ignores any line-spacing text properties
+   put on the newline characters.  This is because those properties
+   only affect the _screen_ line ending in the newline (i.e., in a
+   continued line, only the last screen line will be affected), which
+   means only a small number of lines in a buffer can ever use this
+   feature.  Since this function is used to compute the default pixel
+   equivalent of text lines in a window, we can safely ignore those
+   few lines.  For the same reasons, we ignore the line-height
+   properties.  */
+int
+default_line_pixel_height (struct window *w)
+{
+  struct frame *f = WINDOW_XFRAME (w);
+  int height = FRAME_LINE_HEIGHT (f);
+
+  if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
+    {
+      struct buffer *b = XBUFFER (w->contents);
+      Lisp_Object val = BVAR (b, extra_line_spacing);
+
+      if (NILP (val))
+       val = BVAR (&buffer_defaults, extra_line_spacing);
+      if (!NILP (val))
+       {
+         if (RANGED_INTEGERP (0, val, INT_MAX))
+           height += XFASTINT (val);
+         else if (FLOATP (val))
+           {
+             int addon = XFLOAT_DATA (val) * height + 0.5;
+
+             if (addon >= 0)
+               height += addon;
+           }
+       }
+      else
+       height += f->extra_line_spacing;
+    }
+
+  return height;
+}
+
 /* Subroutine of pos_visible_p below.  Extracts a display string, if
    any, from the display spec given as its argument.  */
 static Lisp_Object
@@ -1312,12 +1335,12 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
 
   /* Compute exact mode line heights.  */
   if (WINDOW_WANTS_MODELINE_P (w))
-    current_mode_line_height
+    w->mode_line_height
       = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
                           BVAR (current_buffer, mode_line_format));
 
   if (WINDOW_WANTS_HEADER_LINE_P (w))
-    current_header_line_height
+    w->header_line_height
       = display_mode_line (w, HEADER_LINE_FACE_ID,
                           BVAR (current_buffer, header_line_format));
 
@@ -1366,8 +1389,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
          struct it save_it = it;
          /* Why 10? because we don't know how many canonical lines
             will the height of the next line(s) be.  So we guess.  */
-         int ten_more_lines =
-           10 * FRAME_LINE_HEIGHT (XFRAME (WINDOW_FRAME (w)));
+         int ten_more_lines = 10 * default_line_pixel_height (w);
 
          move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
                      MOVE_TO_POS | MOVE_TO_Y);
@@ -1611,8 +1633,6 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
 
-  current_header_line_height = current_mode_line_height = -1;
-
   if (visible_p && w->hscroll > 0)
     *x -=
       window_hscroll_limited (w, WINDOW_XFRAME (w))
@@ -1810,7 +1830,7 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
    not force the value into range.  */
 
 void
-pixel_to_glyph_coords (FRAME_PTR f, register int pix_x, register int pix_y,
+pixel_to_glyph_coords (struct frame *f, register int pix_x, register int pix_y,
                       int *x, int *y, NativeRectangle *bounds, int noclip)
 {
 
@@ -2422,7 +2442,16 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
-\f
+static void
+adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
+{
+  eassert (w);
+  w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
+  w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+  w->window_end_vpos
+    = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
+}
+
 /***********************************************************************
                        Lisp form evaluation
  ***********************************************************************/
@@ -2558,8 +2587,7 @@ check_window_end (struct window *w)
   if (!MINI_WINDOW_P (w) && w->window_end_valid)
     {
       struct glyph_row *row;
-      eassert ((row = MATRIX_ROW (w->current_matrix,
-                                 XFASTINT (w->window_end_vpos)),
+      eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
                !row->enabled_p
                || MATRIX_ROW_DISPLAYS_TEXT_P (row)
                || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
@@ -3865,10 +3893,14 @@ handle_face_prop (struct it *it)
          /* For strings from a `display' property, use the face at
             IT's current buffer position as the base face to merge
             with, so that overlay strings appear in the same face as
-            surrounding text, unless they specify their own
-            faces.  */
+            surrounding text, unless they specify their own faces.
+            For strings from wrap-prefix and line-prefix properties,
+            use the default face, possibly remapped via
+            Vface_remapping_alist.  */
          base_face_id = it->string_from_prefix_prop_p
-           ? DEFAULT_FACE_ID
+           ? (!NILP (Vface_remapping_alist)
+              ? lookup_basic_face (it->f, DEFAULT_FACE_ID)
+              : DEFAULT_FACE_ID)
            : underlying_face_id (it);
        }
 
@@ -5302,7 +5334,7 @@ handle_composition_prop (struct it *it)
      composition (in the case that the composition is from the current
      buffer), draw a glyph composed from the composition components.  */
   if (find_composition (pos, -1, &start, &end, &prop, string)
-      && COMPOSITION_VALID_P (start, end, prop)
+      && composition_valid_p (start, end, prop)
       && (STRINGP (it->string) || (PT <= start || PT >= end)))
     {
       if (start < pos)
@@ -5465,8 +5497,8 @@ next_overlay_string (struct it *it)
 static int
 compare_overlay_entries (const void *e1, const void *e2)
 {
-  struct overlay_entry *entry1 = (struct overlay_entry *) e1;
-  struct overlay_entry *entry2 = (struct overlay_entry *) e2;
+  struct overlay_entry const *entry1 = e1;
+  struct overlay_entry const *entry2 = e2;
   int result;
 
   if (entry1->after_string_p != entry2->after_string_p)
@@ -6630,17 +6662,59 @@ lookup_glyphless_char_display (int c, struct it *it)
   return glyphless_method;
 }
 
-/* Load IT's display element fields with information about the next
-   display element from the current position of IT.  Value is zero if
-   end of buffer (or C string) is reached.  */
+/* Merge escape glyph face and cache the result.  */
 
 static struct frame *last_escape_glyph_frame = NULL;
 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
 static int last_escape_glyph_merged_face_id = 0;
 
-struct frame *last_glyphless_glyph_frame = NULL;
-int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
-int last_glyphless_glyph_merged_face_id = 0;
+static int
+merge_escape_glyph_face (struct it *it)
+{
+  int face_id;
+
+  if (it->f == last_escape_glyph_frame
+      && it->face_id == last_escape_glyph_face_id)
+    face_id = last_escape_glyph_merged_face_id;
+  else
+    {
+      /* Merge the `escape-glyph' face into the current face.  */
+      face_id = merge_faces (it->f, Qescape_glyph, 0, it->face_id);
+      last_escape_glyph_frame = it->f;
+      last_escape_glyph_face_id = it->face_id;
+      last_escape_glyph_merged_face_id = face_id;
+    }
+  return face_id;
+}
+
+/* Likewise for glyphless glyph face.  */
+
+static struct frame *last_glyphless_glyph_frame = NULL;
+static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
+static int last_glyphless_glyph_merged_face_id = 0;
+
+int
+merge_glyphless_glyph_face (struct it *it)
+{
+  int face_id;
+
+  if (it->f == last_glyphless_glyph_frame
+      && it->face_id == last_glyphless_glyph_face_id)
+    face_id = last_glyphless_glyph_merged_face_id;
+  else
+    {
+      /* Merge the `glyphless-char' face into the current face.  */
+      face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
+      last_glyphless_glyph_frame = it->f;
+      last_glyphless_glyph_face_id = it->face_id;
+      last_glyphless_glyph_merged_face_id = face_id;
+    }
+  return face_id;
+}
+
+/* Load IT's display element fields with information about the next
+   display element from the current position of IT.  Value is zero if
+   end of buffer (or C string) is reached.  */
 
 static int
 get_next_display_element (struct it *it)
@@ -6788,24 +6862,10 @@ get_next_display_element (struct it *it)
                      g = GLYPH_CODE_CHAR (gc);
                      lface_id = GLYPH_CODE_FACE (gc);
                    }
-                 if (lface_id)
-                   {
-                     face_id = merge_faces (it->f, Qt, lface_id, it->face_id);
-                   }
-                 else if (it->f == last_escape_glyph_frame
-                          && it->face_id == last_escape_glyph_face_id)
-                   {
-                     face_id = last_escape_glyph_merged_face_id;
-                   }
-                 else
-                   {
-                     /* Merge the escape-glyph face into the current face.  */
-                     face_id = merge_faces (it->f, Qescape_glyph, 0,
-                                            it->face_id);
-                     last_escape_glyph_frame = it->f;
-                     last_escape_glyph_face_id = it->face_id;
-                     last_escape_glyph_merged_face_id = face_id;
-                   }
+
+                 face_id = (lface_id
+                            ? merge_faces (it->f, Qt, lface_id, it->face_id)
+                            : merge_escape_glyph_face (it));
 
                  XSETINT (it->ctl_chars[0], g);
                  XSETINT (it->ctl_chars[1], c ^ 0100);
@@ -6837,27 +6897,10 @@ get_next_display_element (struct it *it)
                  escape_glyph = GLYPH_CODE_CHAR (gc);
                  lface_id = GLYPH_CODE_FACE (gc);
                }
-             if (lface_id)
-               {
-                 /* The display table specified a face.
-                    Merge it into face_id and also into escape_glyph.  */
-                 face_id = merge_faces (it->f, Qt, lface_id,
-                                        it->face_id);
-               }
-             else if (it->f == last_escape_glyph_frame
-                      && it->face_id == last_escape_glyph_face_id)
-               {
-                 face_id = last_escape_glyph_merged_face_id;
-               }
-             else
-               {
-                 /* Merge the escape-glyph face into the current face.  */
-                 face_id = merge_faces (it->f, Qescape_glyph, 0,
-                                        it->face_id);
-                 last_escape_glyph_frame = it->f;
-                 last_escape_glyph_face_id = it->face_id;
-                 last_escape_glyph_merged_face_id = face_id;
-               }
+
+             face_id = (lface_id
+                        ? merge_faces (it->f, Qt, lface_id, it->face_id)
+                        : merge_escape_glyph_face (it));
 
              /* Draw non-ASCII hyphen with just highlighting: */
 
@@ -6999,7 +7042,9 @@ get_next_display_element (struct it *it)
                }
            }
        }
-      else
+      /* next_element_from_display_vector sets this flag according to
+        faces of the display vector glyphs, see there.  */
+      else if (it->method != GET_FROM_DISPLAY_VECTOR)
        {
          int face_id = face_after_it_pos (it);
          it->end_of_box_run_p
@@ -7414,6 +7459,8 @@ static int
 next_element_from_display_vector (struct it *it)
 {
   Lisp_Object gc;
+  int prev_face_id = it->face_id;
+  int next_face_id;
 
   /* Precondition.  */
   eassert (it->dpvec && it->current.dpvec_index >= 0);
@@ -7426,6 +7473,8 @@ next_element_from_display_vector (struct it *it)
 
   if (GLYPH_CODE_P (gc))
     {
+      struct face *this_face, *prev_face, *next_face;
+
       it->c = GLYPH_CODE_CHAR (gc);
       it->len = CHAR_BYTES (it->c);
 
@@ -7441,6 +7490,41 @@ next_element_from_display_vector (struct it *it)
            it->face_id = merge_faces (it->f, Qt, lface_id,
                                       it->saved_face_id);
        }
+
+      /* Glyphs in the display vector could have the box face, so we
+        need to set the related flags in the iterator, as
+        appropriate.  */
+      this_face = FACE_FROM_ID (it->f, it->face_id);
+      prev_face = FACE_FROM_ID (it->f, prev_face_id);
+
+      /* Is this character the first character of a box-face run?  */
+      it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
+                               && (!prev_face
+                                   || prev_face->box == FACE_NO_BOX));
+
+      /* For the last character of the box-face run, we need to look
+        either at the next glyph from the display vector, or at the
+        face we saw before the display vector.  */
+      next_face_id = it->saved_face_id;
+      if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
+       {
+         if (it->dpvec_face_id >= 0)
+           next_face_id = it->dpvec_face_id;
+         else
+           {
+             int lface_id =
+               GLYPH_CODE_FACE (it->dpvec[it->current.dpvec_index + 1]);
+
+             if (lface_id > 0)
+               next_face_id = merge_faces (it->f, Qt, lface_id,
+                                           it->saved_face_id);
+           }
+       }
+      next_face = FACE_FROM_ID (it->f, next_face_id);
+      it->end_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
+                             && (!next_face
+                                 || next_face->box == FACE_NO_BOX));
+      it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
     }
   else
     /* Display table entry is invalid.  Return a space.  */
@@ -9015,7 +9099,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
       && it->current_x == it->last_visible_x - 1
       && it->c != '\n'
       && it->c != '\t'
-      && it->vpos < XFASTINT (it->w->window_end_vpos))
+      && it->vpos < it->w->window_end_vpos)
     {
       it->continuation_lines_width += it->current_x;
       it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
@@ -9056,7 +9140,7 @@ move_it_vertically_backward (struct it *it, int dy)
   start_pos = IT_CHARPOS (*it);
 
   /* Estimate how many newlines we must move back.  */
-  nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
+  nlines = max (1, dy / default_line_pixel_height (it->w));
   if (it->line_wrap == TRUNCATE)
     pos_limit = BEGV;
   else
@@ -9453,7 +9537,20 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
 
       old_deactivate_mark = Vdeactivate_mark;
       oldbuf = current_buffer;
-      Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
+
+      /* Ensure the Messages buffer exists, and switch to it.
+         If we created it, set the major-mode.  */
+      {
+        int newbuffer = 0;
+        if (NILP (Fget_buffer (Vmessages_buffer_name))) newbuffer = 1;
+
+        Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
+
+        if (newbuffer &&
+            !NILP (Ffboundp (intern ("messages-buffer-mode"))))
+          call0 (intern ("messages-buffer-mode"));
+      }
+
       bset_undo_list (current_buffer, Qt);
 
       oldpoint = message_dolog_marker1;
@@ -9746,7 +9843,7 @@ message3_nolog (Lisp_Object m)
 void
 message1 (const char *m)
 {
-  message3 (m ? make_unibyte_string (m, strlen (m)) : Qnil);
+  message3 (m ? build_unibyte_string (m) : Qnil);
 }
 
 
@@ -9755,7 +9852,7 @@ message1 (const char *m)
 void
 message1_nolog (const char *m)
 {
-  message3_nolog (m ? make_unibyte_string (m, strlen (m)) : Qnil);
+  message3_nolog (m ? build_unibyte_string (m) : Qnil);
 }
 
 /* Display a message M which contains a single %s
@@ -9865,7 +9962,7 @@ vmessage (const char *m, va_list ap)
              ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
              char *message_buf = alloca (maxsize + 1);
 
-             len = doprnt (message_buf, maxsize, m, (char *)0, ap);
+             len = doprnt (message_buf, maxsize, m, 0, ap);
 
              message3 (make_string (message_buf, len));
            }
@@ -10101,7 +10198,7 @@ with_echo_area_buffer_unwind_data (struct window *w)
 /* Restore global state from VECTOR which was created by
    with_echo_area_buffer_unwind_data.  */
 
-static Lisp_Object
+static void
 unwind_with_echo_area_buffer (Lisp_Object vector)
 {
   set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
@@ -10126,7 +10223,6 @@ unwind_with_echo_area_buffer (Lisp_Object vector)
     }
 
   Vwith_echo_area_save_vector = vector;
-  return Qnil;
 }
 
 
@@ -10418,7 +10514,8 @@ resize_mini_window (struct window *w, int exact_p)
          if (height > WINDOW_TOTAL_LINES (w))
            {
              int old_height = WINDOW_TOTAL_LINES (w);
-             freeze_window_starts (f, 1);
+
+             FRAME_WINDOWS_FROZEN (f) = 1;
              grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
              window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
@@ -10426,7 +10523,8 @@ resize_mini_window (struct window *w, int exact_p)
                   && (exact_p || BEGV == ZV))
            {
              int old_height = WINDOW_TOTAL_LINES (w);
-             freeze_window_starts (f, 0);
+
+             FRAME_WINDOWS_FROZEN (f) = 0;
              shrink_mini_window (w);
              window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
@@ -10437,19 +10535,21 @@ resize_mini_window (struct window *w, int exact_p)
          if (height > WINDOW_TOTAL_LINES (w))
            {
              int old_height = WINDOW_TOTAL_LINES (w);
-             freeze_window_starts (f, 1);
+
+             FRAME_WINDOWS_FROZEN (f) = 1;
              grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
              window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
          else if (height < WINDOW_TOTAL_LINES (w))
            {
              int old_height = WINDOW_TOTAL_LINES (w);
-             freeze_window_starts (f, 0);
+
+             FRAME_WINDOWS_FROZEN (f) = 0;
              shrink_mini_window (w);
 
              if (height)
                {
-                 freeze_window_starts (f, 1);
+                 FRAME_WINDOWS_FROZEN (f) = 1;
                  grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
                }
 
@@ -10525,20 +10625,12 @@ restore_message (void)
 }
 
 
-/* Handler for record_unwind_protect calling pop_message.  */
-
-Lisp_Object
-pop_message_unwind (Lisp_Object dummy)
-{
-  pop_message ();
-  return Qnil;
-}
-
-/* Pop the top-most entry off Vmessage_stack.  */
+/* Handler for unwind-protect calling pop_message.  */
 
-static void
-pop_message (void)
+void
+pop_message_unwind (void)
 {
+  /* Pop the top-most entry off Vmessage_stack.  */
   eassert (CONSP (Vmessage_stack));
   Vmessage_stack = XCDR (Vmessage_stack);
 }
@@ -10684,11 +10776,9 @@ clear_garbaged_frames (void)
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
              if (f->resized_p)
-               {
-                 redraw_frame (f);
-                 f->force_flush_display_p = 1;
-               }
-             clear_current_matrices (f);
+               redraw_frame (f);
+             else
+               clear_current_matrices (f);
              changed_count++;
              f->garbaged = 0;
              f->resized_p = 0;
@@ -10776,7 +10866,7 @@ echo_area_display (int update_frame_p)
                 Can do with a display update of the echo area,
                 unless we displayed some mode lines.  */
              update_single_window (w, 1);
-             FRAME_RIF (f)->flush_display (f);
+             flush_frame (f);
            }
          else
            update_frame (f, 1, 1);
@@ -10815,17 +10905,6 @@ buffer_shared_and_changed (void)
          && UNCHANGED_MODIFIED < MODIFF);
 }
 
-/* Nonzero if W doesn't reflect the actual state of current buffer due
-   to its text or overlays change.  FIXME: this may be called when
-   XBUFFER (w->contents) != current_buffer, which looks suspicious.  */
-
-static int
-window_outdated (struct window *w)
-{
-  return (w->last_modified < MODIFF
-         || w->last_overlay_modified < OVERLAY_MODIFF);
-}
-
 /* Nonzero if W's buffer was changed but not saved or Transient Mark mode
    is enabled and mark of W's buffer was changed since last W's update.  */
 
@@ -10851,6 +10930,31 @@ mode_line_update_needed (struct window *w)
          && (w->column_number_displayed != current_column ()));
 }
 
+/* Nonzero if window start of W is frozen and may not be changed during
+   redisplay.  */
+
+static bool
+window_frozen_p (struct window *w)
+{
+  if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
+    {
+      Lisp_Object window;
+
+      XSETWINDOW (window, w);
+      if (MINI_WINDOW_P (w))
+       return 0;
+      else if (EQ (window, selected_window))
+       return 0;
+      else if (MINI_WINDOW_P (XWINDOW (selected_window))
+              && EQ (window, Vminibuf_scroll_window))
+       /* This special window can't be frozen too.  */
+       return 0;
+      else
+       return 1;
+    }
+  return 0;
+}
+
 /***********************************************************************
                     Mode Lines and Frame Titles
  ***********************************************************************/
@@ -10934,7 +11038,7 @@ format_mode_line_unwind_data (struct frame *target_frame,
   return vector;
 }
 
-static Lisp_Object
+static void
 unwind_format_mode_line (Lisp_Object vector)
 {
   Lisp_Object old_window = AREF (vector, 7);
@@ -10977,7 +11081,6 @@ unwind_format_mode_line (Lisp_Object vector)
     }
 
   Vmode_line_unwind_vector = vector;
-  return Qnil;
 }
 
 
@@ -11147,7 +11250,18 @@ prepare_menu_bars (void)
        {
          f = XFRAME (frame);
          if (!EQ (frame, tooltip_frame)
-             && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
+             && (FRAME_ICONIFIED_P (f)
+                 || FRAME_VISIBLE_P (f) == 1
+                 /* Exclude TTY frames that are obscured because they
+                    are not the top frame on their console.  This is
+                    because x_consider_frame_title actually switches
+                    to the frame, which for TTY frames means it is
+                    marked as garbaged, and will be completely
+                    redrawn on the next redisplay cycle.  This causes
+                    TTY frames to be completely redrawn, when there
+                    are more than one of them, even though nothing
+                    should be changed on display.  */
+                 || (FRAME_VISIBLE_P (f) == 2 && FRAME_WINDOW_P (f))))
            x_consider_frame_title (frame);
        }
     }
@@ -11334,89 +11448,12 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
   return hooks_run;
 }
 
-
-\f
-/***********************************************************************
-                           Output Cursor
- ***********************************************************************/
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* 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.  */
-
-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 (struct cursor_pos *cursor)
-{
-  output_cursor.hpos = cursor->hpos;
-  output_cursor.vpos = cursor->vpos;
-  output_cursor.x = cursor->x;
-  output_cursor.y = cursor->y;
-}
-
-
-/* EXPORT for RIF:
-   Set a nominal cursor position.
-
-   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 (int vpos, int hpos, int y, int 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.  */
 
@@ -11426,7 +11463,7 @@ int last_tool_bar_item;
    do_switch_frame.
    FIXME: Maybe do_switch_frame should be trimmed down similarly
    when `norecord' is set.  */
-static Lisp_Object
+static void
 fast_set_selected_frame (Lisp_Object frame)
 {
   if (!EQ (selected_frame, frame))
@@ -11434,7 +11471,6 @@ fast_set_selected_frame (Lisp_Object frame)
       selected_frame = frame;
       selected_window = XFRAME (frame)->selected_window;
     }
-  return Qnil;
 }
 
 /* Update the tool-bar item list for frame F.  This has to be done
@@ -11535,6 +11571,7 @@ update_tool_bar (struct frame *f, int save_match_data)
     }
 }
 
+#if ! defined (USE_GTK) && ! defined (HAVE_NS)
 
 /* Set F->desired_tool_bar_string to a Lisp string representing frame
    F's desired tool-bar contents.  F->tool_bar_items must have
@@ -11872,6 +11909,11 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
   return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
 }
 
+#endif /* !USE_GTK && !HAVE_NS */
+
+#if defined USE_GTK || defined HAVE_NS
+EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
+#endif
 
 DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
        0, 1, 0,
@@ -11879,9 +11921,10 @@ DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
 If FRAME is nil or omitted, use the selected frame.  */)
   (Lisp_Object frame)
 {
+  int nlines = 0;
+#if ! defined (USE_GTK) && ! defined (HAVE_NS)
   struct frame *f = decode_any_frame (frame);
   struct window *w;
-  int nlines = 0;
 
   if (WINDOWP (f->tool_bar_window)
       && (w = XWINDOW (f->tool_bar_window),
@@ -11894,7 +11937,7 @@ If FRAME is nil or omitted, use the selected frame.  */)
          nlines = tool_bar_lines_needed (f, NULL);
        }
     }
-
+#endif
   return make_number (nlines);
 }
 
@@ -11905,15 +11948,17 @@ If FRAME is nil or omitted, use the selected frame.  */)
 static int
 redisplay_tool_bar (struct frame *f)
 {
-  struct window *w;
-  struct it it;
-  struct glyph_row *row;
-
 #if defined (USE_GTK) || defined (HAVE_NS)
+
   if (FRAME_EXTERNAL_TOOL_BAR (f))
     update_frame_tool_bar (f);
   return 0;
-#endif
+
+#else /* !USE_GTK && !HAVE_NS */
+
+  struct window *w;
+  struct it it;
+  struct glyph_row *row;
 
   /* If frame hasn't a tool-bar window or if it is zero-height, don't
      do anything.  This means you must start with tool-bar-lines
@@ -11954,13 +11999,12 @@ redisplay_tool_bar (struct frame *f)
 
          XSETFRAME (frame, f);
          Fmodify_frame_parameters (frame,
-                                   Fcons (Fcons (Qtool_bar_lines,
-                                                 make_number (nlines)),
-                                          Qnil));
+                                   list1 (Fcons (Qtool_bar_lines,
+                                                 make_number (nlines))));
          if (WINDOW_TOTAL_LINES (w) != old_height)
            {
              clear_glyph_matrix (w->desired_matrix);
-             fonts_changed_p = 1;
+             f->fonts_changed = 1;
              return 1;
            }
        }
@@ -12055,14 +12099,13 @@ redisplay_tool_bar (struct frame *f)
            {
              XSETFRAME (frame, f);
              Fmodify_frame_parameters (frame,
-                                       Fcons (Fcons (Qtool_bar_lines,
-                                                     make_number (nlines)),
-                                              Qnil));
+                                       list1 (Fcons (Qtool_bar_lines,
+                                                     make_number (nlines))));
              if (WINDOW_TOTAL_LINES (w) != old_height)
                {
                  clear_glyph_matrix (w->desired_matrix);
                  f->n_tool_bar_rows = nrows;
-                 fonts_changed_p = 1;
+                 f->fonts_changed = 1;
                  return 1;
                }
            }
@@ -12071,8 +12114,11 @@ redisplay_tool_bar (struct frame *f)
 
   f->minimize_tool_bar_window_p = 0;
   return 0;
+
+#endif /* USE_GTK || HAVE_NS */
 }
 
+#if ! defined (USE_GTK) && ! defined (HAVE_NS)
 
 /* Get information about the tool-bar item which is displayed in GLYPH
    on frame F.  Return in *PROP_IDX the index where tool-bar item
@@ -12237,7 +12283,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
 {
   Lisp_Object window = f->tool_bar_window;
   struct window *w = XWINDOW (window);
-  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
   int hpos, vpos;
   struct glyph *glyph;
@@ -12270,9 +12316,9 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
   clear_mouse_face (hlinfo);
 
   /* Mouse is down, but on different tool-bar item?  */
-  mouse_down_p = (dpyinfo->grabbed
-                 && f == last_mouse_frame
-                 && FRAME_LIVE_P (f));
+  mouse_down_p = (x_mouse_grabbed (dpyinfo)
+                 && f == dpyinfo->last_mouse_frame);
+
   if (mouse_down_p
       && last_tool_bar_item != prop_idx)
     return;
@@ -12293,13 +12339,11 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
       hlinfo->mouse_face_beg_col = hpos;
       hlinfo->mouse_face_beg_row = vpos;
       hlinfo->mouse_face_beg_x = x;
-      hlinfo->mouse_face_beg_y = row->y;
       hlinfo->mouse_face_past_end = 0;
 
       hlinfo->mouse_face_end_col = hpos + 1;
       hlinfo->mouse_face_end_row = vpos;
       hlinfo->mouse_face_end_x = x + glyph->pixel_width;
-      hlinfo->mouse_face_end_y = row->y;
       hlinfo->mouse_face_window = window;
       hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
 
@@ -12318,6 +12362,8 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
     help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
 }
 
+#endif /* !USE_GTK && !HAVE_NS */
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 
@@ -12544,6 +12590,7 @@ static void debug_method_add (struct window *, char const *, ...)
 static void
 debug_method_add (struct window *w, char const *fmt, ...)
 {
+  void *ptr = w;
   char *method = w->desired_matrix->method;
   int len = strlen (method);
   int size = sizeof w->desired_matrix->method;
@@ -12562,7 +12609,7 @@ debug_method_add (struct window *w, char const *fmt, ...)
 
   if (trace_redisplay_p)
     fprintf (stderr, "%p (%s): %s\n",
-            w,
+            ptr,
             ((BUFFERP (w->contents)
               && STRINGP (BVAR (XBUFFER (w->contents), name)))
              ? SSDATA (BVAR (XBUFFER (w->contents), name))
@@ -12820,7 +12867,7 @@ check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
 
       if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
          && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
-         && COMPOSITION_VALID_P (start, end, prop)
+         && composition_valid_p (start, end, prop)
          && start < prev_pt && end > prev_pt)
        /* The last point was within the composition.  Return 1 iff
             point moved out of the composition.  */
@@ -12830,17 +12877,17 @@ check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
   /* Check a composition at the current point.  */
   return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
          && find_composition (pt, -1, &start, &end, &prop, buffer)
-         && COMPOSITION_VALID_P (start, end, prop)
+         && composition_valid_p (start, end, prop)
          && start < pt && end > pt);
 }
 
-
-/* Reconsider the setting of B->clip_changed which is displayed
-   in window W.  */
+/* Reconsider the clip changes of buffer which is displayed in W.  */
 
 static void
-reconsider_clip_changes (struct window *w, struct buffer *b)
+reconsider_clip_changes (struct window *w)
 {
+  struct buffer *b = XBUFFER (w->contents);
+
   if (b->clip_changed
       && w->window_end_valid
       && w->current_matrix->buffer == b
@@ -12853,24 +12900,17 @@ reconsider_clip_changes (struct window *w, struct buffer *b)
      we set b->clip_changed to 1 to force updating the screen.  If
      b->clip_changed has already been set to 1, we can skip this
      check.  */
-  if (!b->clip_changed && BUFFERP (w->contents) && w->window_end_valid)
+  if (!b->clip_changed && w->window_end_valid)
     {
-      ptrdiff_t pt;
-
-      if (w == XWINDOW (selected_window))
-       pt = PT;
-      else
-       pt = marker_position (w->pointm);
+      ptrdiff_t pt = (w == XWINDOW (selected_window)
+                     ? PT : marker_position (w->pointm));
 
-      if ((w->current_matrix->buffer != XBUFFER (w->contents)
-          || pt != w->last_point)
+      if ((w->current_matrix->buffer != b || pt != w->last_point)
          && check_point_in_composition (w->current_matrix->buffer,
-                                        w->last_point,
-                                        XBUFFER (w->contents), pt))
+                                        w->last_point, b, pt))
        b->clip_changed = 1;
     }
 }
-\f
 
 #define STOP_POLLING                                   \
 do { if (! polling_stopped_here) stop_polling ();      \
@@ -12891,10 +12931,10 @@ redisplay_internal (void)
   struct window *sw;
   struct frame *fr;
   int pending;
-  int must_finish = 0;
+  bool must_finish = 0, match_p;
   struct text_pos tlbufpos, tlendpos;
   int number_of_visible_frames;
-  ptrdiff_t count, count1;
+  ptrdiff_t count;
   struct frame *sf;
   int polling_stopped_here = 0;
   Lisp_Object tail, frame;
@@ -12936,7 +12976,7 @@ redisplay_internal (void)
   /* Record a function that clears redisplaying_p
      when we leave this function.  */
   count = SPECPDL_INDEX ();
-  record_unwind_protect (unwind_redisplay, selected_frame);
+  record_unwind_protect_void (unwind_redisplay);
   redisplaying_p = 1;
   specbind (Qinhibit_free_realized_faces, Qnil);
 
@@ -12951,21 +12991,11 @@ redisplay_internal (void)
   sw = w;
 
   pending = 0;
-  reconsider_clip_changes (w, current_buffer);
   last_escape_glyph_frame = NULL;
   last_escape_glyph_face_id = (1 << FACE_ID_BITS);
   last_glyphless_glyph_frame = NULL;
   last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
 
-  /* If new fonts have been loaded that make a glyph matrix adjustment
-     necessary, do it.  */
-  if (fonts_changed_p)
-    {
-      adjust_glyphs (NULL);
-      ++windows_or_buffers_changed;
-      fonts_changed_p = 0;
-    }
-
   /* If face_change_count is non-zero, init_iterator will free all
      realized faces, which includes the faces referenced from current
      matrices.  So, we can't reuse current matrices in this case.  */
@@ -12996,7 +13026,19 @@ redisplay_internal (void)
       struct frame *f = XFRAME (frame);
 
       if (FRAME_VISIBLE_P (f))
-       ++number_of_visible_frames;
+       {
+         ++number_of_visible_frames;
+         /* Adjust matrices for visible frames only.  */
+         if (f->fonts_changed)
+           {
+             adjust_frame_glyphs (f);
+             f->fonts_changed = 0;
+           }
+         /* If cursor type has been changed on the frame
+            other than selected, consider all frames.  */
+         if (f != sf && f->cursor_type_changed)
+           update_mode_lines++;
+       }
       clear_desired_matrices (f);
     }
 
@@ -13006,10 +13048,7 @@ redisplay_internal (void)
   /* do_pending_window_change could change the selected_window due to
      frame resizing which makes the selected window too small.  */
   if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
-    {
-      sw = w;
-      reconsider_clip_changes (w, current_buffer);
-    }
+    sw = w;
 
   /* Clear frames marked as garbaged.  */
   clear_garbaged_frames ();
@@ -13021,26 +13060,34 @@ redisplay_internal (void)
   if (windows_or_buffers_changed)
     update_mode_lines++;
 
-  /* Detect case that we need to write or remove a star in the mode line.  */
-  if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
+  reconsider_clip_changes (w);
+
+  /* In most cases selected window displays current buffer.  */
+  match_p = XBUFFER (w->contents) == current_buffer;
+  if (match_p)
     {
-      w->update_mode_line = 1;
-      if (buffer_shared_and_changed ())
-       update_mode_lines++;
-    }
+      ptrdiff_t count1;
 
-  /* Avoid invocation of point motion hooks by `current_column' below.  */
-  count1 = SPECPDL_INDEX ();
-  specbind (Qinhibit_point_motion_hooks, Qt);
+      /* Detect case that we need to write or remove a star in the mode line.  */
+      if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
+       {
+         w->update_mode_line = 1;
+         if (buffer_shared_and_changed ())
+           update_mode_lines++;
+       }
 
-  if (mode_line_update_needed (w))
-    w->update_mode_line = 1;
+      /* Avoid invocation of point motion hooks by `current_column' below.  */
+      count1 = SPECPDL_INDEX ();
+      specbind (Qinhibit_point_motion_hooks, Qt);
 
-  unbind_to (count1, Qnil);
+      if (mode_line_update_needed (w))
+       w->update_mode_line = 1;
+
+      unbind_to (count1, Qnil);
+    }
 
   consider_all_windows_p = (update_mode_lines
-                           || buffer_shared_and_changed ()
-                           || cursor_type_changed);
+                           || buffer_shared_and_changed ());
 
   /* If specs for an arrow have changed, do thorough redisplay
      to ensure we remove any arrow that should no longer exist.  */
@@ -13074,9 +13121,7 @@ redisplay_internal (void)
       if (!display_last_displayed_message_p)
        message_cleared_p = 0;
 
-      if (fonts_changed_p)
-       goto retry;
-      else if (window_height_changed_p)
+      if (window_height_changed_p)
        {
          consider_all_windows_p = 1;
          ++update_mode_lines;
@@ -13133,9 +13178,10 @@ redisplay_internal (void)
       && !current_buffer->prevent_redisplay_optimizations_p
       && FRAME_VISIBLE_P (XFRAME (w->frame))
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
+      && !XFRAME (w->frame)->cursor_type_changed
       /* Make sure recorded data applies to current buffer, etc.  */
       && this_line_buffer == current_buffer
-      && current_buffer == XBUFFER (w->contents)
+      && match_p
       && !w->force_start
       && !w->optional_new_start
       /* Point must be on the line that we have info recorded about.  */
@@ -13231,12 +13277,12 @@ redisplay_internal (void)
                 adjusted.  */
              if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
                {
-                 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
-                   wset_window_end_vpos (w, make_number (this_line_vpos));
+                 if (w->window_end_vpos < this_line_vpos)
+                   w->window_end_vpos = this_line_vpos;
                }
-             else if (XFASTINT (w->window_end_vpos) == this_line_vpos
+             else if (w->window_end_vpos == this_line_vpos
                       && this_line_vpos > 0)
-               wset_window_end_vpos (w, make_number (this_line_vpos - 1));
+               w->window_end_vpos = this_line_vpos - 1;
              w->window_end_valid = 0;
 
              /* Update hint: No need to try to scroll in update_window.  */
@@ -13351,6 +13397,8 @@ redisplay_internal (void)
              && !EQ (FRAME_TTY (f)->top_frame, frame))
            continue;
 
+       retry_frame:
+
          if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
              /* Mark all the scroll bars to be removed; we'll redeem
@@ -13370,20 +13418,22 @@ redisplay_internal (void)
              if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
                FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
 
-             /* If fonts changed, display again.  */
-             /* ??? rms: I suspect it is a mistake to jump all the way
-                back to retry here.  It should just retry this frame.  */
-             if (fonts_changed_p)
-               goto retry;
-
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                {
+                 /* If fonts changed on visible frame, display again.  */
+                 if (f->fonts_changed)
+                   {
+                     adjust_frame_glyphs (f);
+                     f->fonts_changed = 0;
+                     goto retry_frame;
+                   }
+
                  /* See if we have to hscroll.  */
                  if (!f->already_hscrolled_p)
                    {
                      f->already_hscrolled_p = 1;
                      if (hscroll_windows (f->root_window))
-                       goto retry;
+                       goto retry_frame;
                    }
 
                  /* Prevent various kinds of signals during display
@@ -13397,6 +13447,7 @@ redisplay_internal (void)
                  /* Update the display.  */
                  set_window_update_flags (XWINDOW (f->root_window), 1);
                  pending |= update_frame (f, 0, 0);
+                 f->cursor_type_changed = 0;
                  f->updated_p = 1;
                }
            }
@@ -13441,7 +13492,7 @@ redisplay_internal (void)
 
     update:
       /* If fonts changed, display again.  */
-      if (fonts_changed_p)
+      if (sf->fonts_changed)
        goto retry;
 
       /* Prevent various kinds of signals during display update.
@@ -13458,6 +13509,7 @@ redisplay_internal (void)
 
          XWINDOW (selected_window)->must_be_updated_p = 1;
          pending = update_frame (sf, 0, 0);
+         sf->cursor_type_changed = 0;
        }
 
       /* We may have called echo_area_display at the top of this
@@ -13472,6 +13524,7 @@ redisplay_internal (void)
        {
          XWINDOW (mini_window)->must_be_updated_p = 1;
          pending |= update_frame (mini_frame, 0, 0);
+         mini_frame->cursor_type_changed = 0;
          if (!pending && hscroll_windows (mini_window))
            goto retry;
        }
@@ -13512,7 +13565,6 @@ redisplay_internal (void)
 
       update_mode_lines = 0;
       windows_or_buffers_changed = 0;
-      cursor_type_changed = 0;
     }
 
   /* Start SIGIO interrupts coming again.  Having them off during the
@@ -13610,20 +13662,16 @@ redisplay_preserve_echo_area (int from_where)
   else
     redisplay_internal ();
 
-  if (FRAME_RIF (SELECTED_FRAME ()) != NULL
-      && FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
-    FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (NULL);
+  flush_frame (SELECTED_FRAME ());
 }
 
 
-/* Function registered with record_unwind_protect in redisplay_internal.
-   Clear redisplaying_p.  Also select the previously selected frame.  */
+/* Function registered with record_unwind_protect in redisplay_internal.  */
 
-static Lisp_Object
-unwind_redisplay (Lisp_Object old_frame)
+static void
+unwind_redisplay (void)
 {
   redisplaying_p = 0;
-  return Qnil;
 }
 
 
@@ -13655,7 +13703,7 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p)
       w->current_matrix->begv = BUF_BEGV (b);
       w->current_matrix->zv = BUF_ZV (b);
 
-      w->last_cursor = w->cursor;
+      w->last_cursor_vpos = w->cursor.vpos;
       w->last_cursor_off_p = w->cursor_off_p;
 
       if (w == XWINDOW (selected_window))
@@ -14428,8 +14476,7 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
   struct window *w = XWINDOW (window);
   SET_MARKER_FROM_TEXT_POS (w->start, startp);
 
-  if (current_buffer != XBUFFER (w->contents))
-    emacs_abort ();
+  eassert (current_buffer == XBUFFER (w->contents));
 
   if (!NILP (Vwindow_scroll_functions))
     {
@@ -14536,6 +14583,9 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
   Lisp_Object aggressive;
   /* We will never try scrolling more than this number of lines.  */
   int scroll_limit = SCROLL_LIMIT;
+  int frame_line_height = default_line_pixel_height (w);
+  int window_total_lines
+    = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
 
 #ifdef GLYPH_DEBUG
   debug_method_add (w, "try_scrolling");
@@ -14546,8 +14596,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
   /* Compute scroll margin height in pixels.  We scroll when point is
      within this distance from the top or bottom of the window.  */
   if (scroll_margin > 0)
-    this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
-      * FRAME_LINE_HEIGHT (f);
+    this_scroll_margin = min (scroll_margin, window_total_lines / 4)
+      * frame_line_height;
   else
     this_scroll_margin = 0;
 
@@ -14558,19 +14608,19 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
   if (arg_scroll_conservatively > scroll_limit)
     {
       arg_scroll_conservatively = scroll_limit + 1;
-      scroll_max = scroll_limit * FRAME_LINE_HEIGHT (f);
+      scroll_max = scroll_limit * frame_line_height;
     }
   else if (scroll_step || arg_scroll_conservatively || temp_scroll_step)
     /* Compute how much we should try to scroll maximally to bring
        point into view.  */
     scroll_max = (max (scroll_step,
                       max (arg_scroll_conservatively, temp_scroll_step))
-                 * FRAME_LINE_HEIGHT (f));
+                 * frame_line_height);
   else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
           || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
     /* We're trying to scroll because of aggressive scrolling but no
        scroll_step is set.  Choose an arbitrary one.  */
-    scroll_max = 10 * FRAME_LINE_HEIGHT (f);
+    scroll_max = 10 * frame_line_height;
   else
     scroll_max = 0;
 
@@ -14585,7 +14635,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
         either that ypos or PT, whichever comes first.  */
       start_display (&it, w, startp);
       scroll_margin_y = it.last_visible_y - this_scroll_margin
-       - FRAME_LINE_HEIGHT (f) * extra_scroll_margin_lines;
+       - frame_line_height * extra_scroll_margin_lines;
       move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
                  (MOVE_TO_POS | MOVE_TO_Y));
 
@@ -14597,7 +14647,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
             the user limited scrolling by a small number of lines, but
             always finds PT if scroll_conservatively is set to a large
             number, such as most-positive-fixnum.  */
-         int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f));
+         int slack = max (scroll_max, 10 * frame_line_height);
          int y_to_move = it.last_visible_y + slack;
 
          /* Compute the distance from the scroll margin to PT or to
@@ -14624,8 +14674,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
         move it down by scroll_step.  */
       if (arg_scroll_conservatively)
        amount_to_scroll
-         = min (max (dy, FRAME_LINE_HEIGHT (f)),
-                FRAME_LINE_HEIGHT (f) * arg_scroll_conservatively);
+         = min (max (dy, frame_line_height),
+                frame_line_height * arg_scroll_conservatively);
       else if (scroll_step || temp_scroll_step)
        amount_to_scroll = scroll_max;
       else
@@ -14722,7 +14772,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          start_display (&it, w, pos);
          y0 = it.current_y;
          y_to_move = max (it.last_visible_y,
-                          max (scroll_max, 10 * FRAME_LINE_HEIGHT (f)));
+                          max (scroll_max, 10 * frame_line_height));
          move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
                      y_to_move, -1,
                      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
@@ -14738,7 +14788,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          start_display (&it, w, startp);
 
          if (arg_scroll_conservatively)
-           amount_to_scroll = max (dy, FRAME_LINE_HEIGHT (f) *
+           amount_to_scroll = max (dy, frame_line_height *
                                    max (scroll_step, temp_scroll_step));
          else if (scroll_step || temp_scroll_step)
            amount_to_scroll = scroll_max;
@@ -14867,7 +14917,25 @@ compute_window_start_on_continuation_line (struct window *w)
            {
              min_distance = distance;
              pos = it.current.pos;
-             move_it_by_lines (&it, 1);
+             if (it.line_wrap == WORD_WRAP)
+               {
+                 /* Under WORD_WRAP, move_it_by_lines is likely to
+                    overshoot and stop not at the first, but the
+                    second character from the left margin.  So in
+                    that case, we need a more tight control on the X
+                    coordinate of the iterator than move_it_by_lines
+                    promises in its contract.  The method is to first
+                    go to the last (rightmost) visible character of a
+                    line, then move to the leftmost character on the
+                    next line in a separate call.  */
+                 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
+                             MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+                 move_it_to (&it, ZV, 0,
+                             it.current_y + it.max_ascent + it.max_descent, -1,
+                             MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+               }
+             else
+               move_it_by_lines (&it, 1);
            }
 
          /* Set the window start there.  */
@@ -14919,6 +14987,10 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
      if-statement below. Now, this field is converted to
      ptrdiff_t, thus zero means invalid position in a buffer.  */
   eassert (w->last_point > 0);
+  /* Likewise there was a check whether window_end_vpos is nil or larger
+     than the window.  Now window_end_vpos is int and so never nil, but
+     let's leave eassert to check whether it fits in the window.  */
+  eassert (w->window_end_vpos < w->current_matrix->nrows);
 
   /* Handle case where text has not changed, only point, and it has
      not moved off the frame.  */
@@ -14932,7 +15004,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
         cases.  */
       && !update_mode_lines
       && !windows_or_buffers_changed
-      && !cursor_type_changed
+      && !f->cursor_type_changed
       /* Can't use this case if highlighting a region.  When a
          region exists, cursor movement has to do more than just
          set the cursor.  */
@@ -14946,18 +15018,14 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
         since the handling of this_line_start_pos, etc., in redisplay
         handles the same cases.  */
       && !EQ (window, minibuf_window)
-      /* When splitting windows or for new windows, it happens that
-        redisplay is called with a nil window_end_vpos or one being
-        larger than the window.  This should really be fixed in
-        window.c.  I don't have this on my list, now, so we do
-        approximately the same as the old redisplay code.  --gerd.  */
-      && INTEGERP (w->window_end_vpos)
-      && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
       && (FRAME_WINDOW_P (f)
          || !overlay_arrow_in_current_buffer_p ()))
     {
       int this_scroll_margin, top_scroll_margin;
       struct glyph_row *row = NULL;
+      int frame_line_height = default_line_pixel_height (w);
+      int window_total_lines
+       = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
 
 #ifdef GLYPH_DEBUG
       debug_method_add (w, "cursor movement");
@@ -14967,8 +15035,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
         of the window.  This is a pixel value.  */
       if (scroll_margin > 0)
        {
-         this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-         this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+         this_scroll_margin = min (scroll_margin, window_total_lines / 4);
+         this_scroll_margin *= frame_line_height;
        }
       else
        this_scroll_margin = 0;
@@ -14979,12 +15047,12 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
 
       /* Start with the row the cursor was displayed during the last
         not paused redisplay.  Give up if that row is not valid.  */
-      if (w->last_cursor.vpos < 0
-         || w->last_cursor.vpos >= w->current_matrix->nrows)
+      if (w->last_cursor_vpos < 0
+         || w->last_cursor_vpos >= w->current_matrix->nrows)
        rc = CURSOR_MOVEMENT_MUST_SCROLL;
       else
        {
-         row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
+         row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
          if (row->mode_line_p)
            ++row;
          if (!row->enabled_p)
@@ -15263,7 +15331,7 @@ set_vertical_scroll_bar (struct window *w)
       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);
+      end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
 
       if (end < start)
        end = start;
@@ -15283,9 +15351,8 @@ set_vertical_scroll_bar (struct window *w)
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
    selected_window is redisplayed.
 
-   We can return without actually redisplaying the window if
-   fonts_changed_p.  In that case, redisplay_internal will
-   retry.  */
+   We can return without actually redisplaying the window if fonts has been
+   changed on window's frame.  In that case, redisplay_internal will retry.  */
 
 static void
 redisplay_window (Lisp_Object window, int just_this_one_p)
@@ -15310,6 +15377,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   int centering_position = -1;
   int last_line_misfit = 0;
   ptrdiff_t beg_unchanged, end_unchanged;
+  int frame_line_height;
 
   SET_TEXT_POS (lpoint, PT, PT_BYTE);
   opoint = lpoint;
@@ -15323,7 +15391,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   eassert (XMARKER (w->pointm)->buffer == buffer);
 
  restart:
-  reconsider_clip_changes (w, buffer);
+  reconsider_clip_changes (w);
+  frame_line_height = default_line_pixel_height (w);
 
   /* Has the mode line to be updated?  */
   update_mode_line = (w->update_mode_line
@@ -15402,8 +15471,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
        && !current_buffer->clip_changed
        && !window_outdated (w));
 
-  /* When windows_or_buffers_changed is non-zero, we can't rely on
-     the window end being valid, so set it to nil there.  */
+  /* When windows_or_buffers_changed is non-zero, we can't rely
+     on the window end being valid, so set it to zero there.  */
   if (windows_or_buffers_changed)
     {
       /* If window starts on a continuation line, maybe adjust the
@@ -15412,6 +15481,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
        compute_window_start_on_continuation_line (w);
 
       w->window_end_valid = 0;
+      /* If so, we also can't rely on current matrix
+        and should not fool try_cursor_movement below.  */
+      current_matrix_up_to_date_p = 0;
     }
 
   /* Some sanity checks.  */
@@ -15493,7 +15565,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
   /* Handle case where place to start displaying has been specified,
      unless the specified location is outside the accessible range.  */
-  if (w->force_start || w->frozen_window_start_p)
+  if (w->force_start || window_frozen_p (w))
     {
       /* We set this later on if we have to adjust point.  */
       int new_vpos = -1;
@@ -15521,8 +15593,6 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          startp = run_window_scroll_functions (window, startp);
        }
 
-      w->last_modified = 0;
-      w->last_overlay_modified = 0;
       if (CHARPOS (startp) < BEGV)
        SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
       else if (CHARPOS (startp) > ZV)
@@ -15540,7 +15610,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          goto need_larger_matrices;
        }
 
-      if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
+      if (w->cursor.vpos < 0 && !window_frozen_p (w))
        {
          /* If point does not appear, try to move point so it does
             appear. The desired matrix has been built above, so we
@@ -15559,8 +15629,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          /* Some people insist on not letting point enter the scroll
             margin, even though this part handles windows that didn't
             scroll at all.  */
-         int margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-         int pixel_margin = margin * FRAME_LINE_HEIGHT (f);
+         int window_total_lines
+           = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
+         int margin = min (scroll_margin, window_total_lines / 4);
+         int pixel_margin = margin * frame_line_height;
          bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
 
          /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
@@ -15568,10 +15640,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
             the Y coordinate of the _next_ row, see the definition of
             MATRIX_ROW_BOTTOM_Y.  */
          if (w->cursor.vpos < margin + header_line)
-           new_vpos
-             = pixel_margin + (header_line
-                               ? CURRENT_HEADER_LINE_HEIGHT (w)
-                               : 0) + FRAME_LINE_HEIGHT (f);
+           {
+             w->cursor.vpos = -1;
+             clear_glyph_matrix (w->desired_matrix);
+             goto try_to_scroll;
+           }
          else
            {
              int window_height = window_box_height (w);
@@ -15579,7 +15652,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
              if (header_line)
                window_height += CURRENT_HEADER_LINE_HEIGHT (w);
              if (w->cursor.y >= window_height - pixel_margin)
-               new_vpos = window_height - pixel_margin;
+               {
+                 w->cursor.vpos = -1;
+                 clear_glyph_matrix (w->desired_matrix);
+                 goto try_to_scroll;
+               }
            }
        }
 
@@ -15660,7 +15737,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
       debug_method_add (w, "try_window_id %d", tem);
 #endif
 
-      if (fonts_changed_p)
+      if (f->fonts_changed)
        goto need_larger_matrices;
       if (tem > 0)
        goto done;
@@ -15730,12 +15807,12 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          IF_DEBUG (debug_method_add (w, "1"));
          if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
            /* -1 means we need to scroll.
-              0 means we need new matrices, but fonts_changed_p
+              0 means we need new matrices, but fonts_changed
               is set in that case, so we will detect it below.  */
            goto try_to_scroll;
        }
 
-      if (fonts_changed_p)
+      if (f->fonts_changed)
        goto need_larger_matrices;
 
       if (w->cursor.vpos >= 0)
@@ -15761,9 +15838,6 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
  try_to_scroll:
 
-  w->last_modified = 0;
-  w->last_overlay_modified = 0;
-
   /* Redisplay the mode line.  Select the buffer properly for that.  */
   if (!update_mode_line)
     {
@@ -15820,9 +15894,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   it.current_y = it.last_visible_y;
   if (centering_position < 0)
     {
+      int window_total_lines
+       = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
       int margin =
        scroll_margin > 0
-       ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+       ? min (scroll_margin, window_total_lines / 4)
        : 0;
       ptrdiff_t margin_pos = CHARPOS (startp);
       Lisp_Object aggressive;
@@ -15844,7 +15920,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
          SAVE_IT (it1, it, it1data);
          start_display (&it1, w, startp);
-         move_it_vertically (&it1, margin * FRAME_LINE_HEIGHT (f));
+         move_it_vertically (&it1, margin * frame_line_height);
          margin_pos = IT_CHARPOS (it1);
          RESTORE_IT (&it, &it, it1data);
        }
@@ -15880,15 +15956,15 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
              if (pt_offset)
                centering_position -= pt_offset;
              centering_position -=
-               FRAME_LINE_HEIGHT (f) * (1 + margin + (last_line_misfit != 0))
+               frame_line_height * (1 + margin + (last_line_misfit != 0))
                + WINDOW_HEADER_LINE_HEIGHT (w);
              /* Don't let point enter the scroll margin near top of
                 the window.  */
-             if (centering_position < margin * FRAME_LINE_HEIGHT (f))
-               centering_position = margin * FRAME_LINE_HEIGHT (f);
+             if (centering_position < margin * frame_line_height)
+               centering_position = margin * frame_line_height;
            }
          else
-           centering_position = margin * FRAME_LINE_HEIGHT (f) + pt_offset;
+           centering_position = margin * frame_line_height + pt_offset;
        }
       else
        /* Set the window start half the height of the window backward
@@ -15924,7 +16000,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   /* Redisplay the window.  */
   if (!current_matrix_up_to_date_p
       || windows_or_buffers_changed
-      || cursor_type_changed
+      || f->cursor_type_changed
       /* Don't use try_window_reusing_current_matrix in this case
         because it can have changed the buffer.  */
       || !NILP (Vwindow_scroll_functions)
@@ -15937,7 +16013,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   /* If new fonts have been loaded (due to fontsets), give up.  We
      have to start a new redisplay since we need to re-adjust glyph
      matrices.  */
-  if (fonts_changed_p)
+  if (f->fonts_changed)
     goto need_larger_matrices;
 
   /* If cursor did not appear assume that the middle of the window is
@@ -15947,7 +16023,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
      line.)  */
   if (w->cursor.vpos < 0)
     {
-      if (w->window_end_valid && PT >= Z - XFASTINT (w->window_end_pos))
+      if (w->window_end_valid && PT >= Z - w->window_end_pos)
        {
          clear_glyph_matrix (w->desired_matrix);
          move_it_by_lines (&it, 1);
@@ -15993,11 +16069,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
         make that row fully visible and out of the margin.  */
       if (scroll_conservatively > SCROLL_LIMIT)
        {
+         int window_total_lines
+           = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) * frame_line_height;
          int margin =
            scroll_margin > 0
-           ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+           ? min (scroll_margin, window_total_lines / 4)
            : 0;
-         int move_down = w->cursor.vpos >= WINDOW_TOTAL_LINES (w) / 2;
+         int move_down = w->cursor.vpos >= window_total_lines / 2;
 
          move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
          clear_glyph_matrix (w->desired_matrix);
@@ -16048,7 +16126,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
       if (WINDOW_WANTS_MODELINE_P (w)
          && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
        {
-         fonts_changed_p = 1;
+         f->fonts_changed = 1;
+         w->mode_line_height = -1;
          MATRIX_MODE_LINE_ROW (w->current_matrix)->height
            = DESIRED_MODE_LINE_HEIGHT (w);
        }
@@ -16058,12 +16137,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
       if (WINDOW_WANTS_HEADER_LINE_P (w)
          && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
        {
-         fonts_changed_p = 1;
+         f->fonts_changed = 1;
+         w->header_line_height = -1;
          MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
            = DESIRED_HEADER_LINE_HEIGHT (w);
        }
 
-      if (fonts_changed_p)
+      if (f->fonts_changed)
        goto need_larger_matrices;
     }
 
@@ -16128,8 +16208,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
     }
 #endif /* HAVE_WINDOW_SYSTEM */
 
-  /* We go to this label, with fonts_changed_p set,
-     if it is necessary to try again using larger glyph matrices.
+  /* We go to this label, with fonts_changed set, if it is
+     necessary to try again using larger glyph matrices.
      We have to redeem the scroll bar even in this case,
      because the loop in redisplay_internal expects that.  */
  need_larger_matrices:
@@ -16184,6 +16264,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
   struct it it;
   struct glyph_row *last_text_row = NULL;
   struct frame *f = XFRAME (w->frame);
+  int frame_line_height = default_line_pixel_height (w);
 
   /* Make POS the new window start.  */
   set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
@@ -16200,7 +16281,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
     {
       if (display_line (&it))
        last_text_row = it.glyph_row - 1;
-      if (fonts_changed_p && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
+      if (f->fonts_changed && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
        return 0;
     }
 
@@ -16209,11 +16290,13 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
       && !MINI_WINDOW_P (w))
     {
       int this_scroll_margin;
+      int window_total_lines
+       = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
 
       if (scroll_margin > 0)
        {
-         this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-         this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+         this_scroll_margin = min (scroll_margin, window_total_lines / 4);
+         this_scroll_margin *= frame_line_height;
        }
       else
        this_scroll_margin = 0;
@@ -16235,8 +16318,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
     }
 
   /* If bottom moved off end of frame, change mode line percentage.  */
-  if (XFASTINT (w->window_end_pos) <= 0
-      && Z != IT_CHARPOS (it))
+  if (w->window_end_pos <= 0 && Z != IT_CHARPOS (it))
     w->update_mode_line = 1;
 
   /* Set window_end_pos to the offset of the last character displayed
@@ -16245,21 +16327,16 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
   if (last_text_row)
     {
       eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
-      w->window_end_bytepos
-       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-      wset_window_end_pos
-       (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
-      wset_window_end_vpos
-       (w, make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix)));
+      adjust_window_ends (w, last_text_row, 0);
       eassert
        (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
-                                                XFASTINT (w->window_end_vpos))));
+                                                w->window_end_vpos)));
     }
   else
     {
       w->window_end_bytepos = Z_BYTE - ZV_BYTE;
-      wset_window_end_pos (w, make_number (Z - ZV));
-      wset_window_end_vpos (w, make_number (0));
+      w->window_end_pos = Z - ZV;
+      w->window_end_vpos = 0;
     }
 
   /* But that is not valid info until redisplay finishes.  */
@@ -16302,7 +16379,7 @@ try_window_reusing_current_matrix (struct window *w)
       /* Don't try to reuse the display if windows have been split
         or such.  */
       || windows_or_buffers_changed
-      || cursor_type_changed)
+      || f->cursor_type_changed)
     return 0;
 
   /* Can't do this if region may have changed.  */
@@ -16350,8 +16427,7 @@ try_window_reusing_current_matrix (struct window *w)
       w->cursor.vpos = -1;
       last_text_row = last_reused_text_row = NULL;
 
-      while (it.current_y < it.last_visible_y
-            && !fonts_changed_p)
+      while (it.current_y < it.last_visible_y && !f->fonts_changed)
        {
          /* If we have reached into the characters in the START row,
             that means the line boundaries have changed.  So we
@@ -16483,32 +16559,15 @@ try_window_reusing_current_matrix (struct window *w)
         The value of last_text_row is the last displayed line
         containing text.  */
       if (last_reused_text_row)
-       {
-         w->window_end_bytepos
-           = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
-         wset_window_end_pos
-           (w, make_number (Z
-                            - MATRIX_ROW_END_CHARPOS (last_reused_text_row)));
-         wset_window_end_vpos
-           (w, make_number (MATRIX_ROW_VPOS (last_reused_text_row,
-                                             w->current_matrix)));
-       }
+       adjust_window_ends (w, last_reused_text_row, 1);
       else if (last_text_row)
-       {
-         w->window_end_bytepos
-           = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-         wset_window_end_pos
-           (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
-         wset_window_end_vpos
-           (w, make_number (MATRIX_ROW_VPOS (last_text_row,
-                                             w->desired_matrix)));
-       }
+       adjust_window_ends (w, last_text_row, 0);
       else
        {
          /* This window must be completely empty.  */
          w->window_end_bytepos = Z_BYTE - ZV_BYTE;
-         wset_window_end_pos (w, make_number (Z - ZV));
-         wset_window_end_vpos (w, make_number (0));
+         w->window_end_pos = Z - ZV;
+         w->window_end_vpos = 0;
        }
       w->window_end_valid = 0;
 
@@ -16579,7 +16638,7 @@ try_window_reusing_current_matrix (struct window *w)
       if (pt_row == NULL)
        w->cursor.vpos = -1;
       last_text_row = NULL;
-      while (it.current_y < it.last_visible_y && !fonts_changed_p)
+      while (it.current_y < it.last_visible_y && !f->fonts_changed)
        if (display_line (&it))
          last_text_row = it.glyph_row - 1;
 
@@ -16693,20 +16752,9 @@ try_window_reusing_current_matrix (struct window *w)
         the window end is in reused rows which in turn means that
         only its vpos can have changed.  */
       if (last_text_row)
-       {
-         w->window_end_bytepos
-           = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-         wset_window_end_pos
-           (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
-         wset_window_end_vpos
-           (w, make_number (MATRIX_ROW_VPOS (last_text_row,
-                                             w->desired_matrix)));
-       }
+       adjust_window_ends (w, last_text_row, 0);
       else
-       {
-         wset_window_end_vpos
-           (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled));
-       }
+       w->window_end_vpos -= nrows_scrolled;
 
       w->window_end_valid = 0;
       w->desired_matrix->no_scrolling_p = 1;
@@ -16846,11 +16894,11 @@ find_first_unchanged_at_end_row (struct window *w,
   /* A value of window_end_pos >= END_UNCHANGED means that the window
      end is in the range of changed text.  If so, there is no
      unchanged row at the end of W's current matrix.  */
-  if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
+  if (w->window_end_pos >= END_UNCHANGED)
     return NULL;
 
   /* Set row to the last row in W's current matrix displaying text.  */
-  row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+  row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
 
   /* If matrix is entirely empty, no unchanged row exists.  */
   if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
@@ -16861,7 +16909,7 @@ find_first_unchanged_at_end_row (struct window *w,
         buffer positions in the current matrix to current buffer
         positions for characters not in changed text.  */
       ptrdiff_t Z_old =
-       MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
+       MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
       ptrdiff_t Z_BYTE_old =
        MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
       ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
@@ -17102,7 +17150,7 @@ try_window_id (struct window *w)
     GIVE_UP (1);
 
   /* This flag is used to prevent redisplay optimizations.  */
-  if (windows_or_buffers_changed || cursor_type_changed)
+  if (windows_or_buffers_changed || f->cursor_type_changed)
     GIVE_UP (2);
 
   /* Verify that narrowing has not changed.
@@ -17195,7 +17243,7 @@ try_window_id (struct window *w)
      This case happens with stealth-fontification.  Note that although
      the display is unchanged, glyph positions in the matrix have to
      be adjusted, of course.  */
-  row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+  row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
   if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
       && ((last_changed_charpos < CHARPOS (start)
           && CHARPOS (start) == BEGV)
@@ -17207,7 +17255,7 @@ try_window_id (struct window *w)
 
       /* Compute how many chars/bytes have been added to or removed
         from the buffer.  */
-      Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
+      Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
       Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
       Z_delta = Z - Z_old;
       Z_delta_bytes = Z_BYTE - Z_BYTE_old;
@@ -17278,10 +17326,8 @@ try_window_id (struct window *w)
        {
          /* We have to compute the window end anew since text
             could have been added/removed after it.  */
-         wset_window_end_pos
-           (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
-         w->window_end_bytepos
-           = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+         w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
+         w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
 
          /* Set the cursor.  */
          row = row_containing_pos (w, PT, r0, NULL, 0);
@@ -17314,7 +17360,7 @@ try_window_id (struct window *w)
 
   /* Give up if the window ends in strings.  Overlay strings
      at the end are difficult to handle, so don't try.  */
-  row = MATRIX_ROW (current_matrix, XFASTINT (w->window_end_vpos));
+  row = MATRIX_ROW (current_matrix, w->window_end_vpos);
   if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
     GIVE_UP (20);
 
@@ -17435,7 +17481,7 @@ try_window_id (struct window *w)
   last_text_row = NULL;
   overlay_arrow_seen = 0;
   while (it.current_y < it.last_visible_y
-        && !fonts_changed_p
+        && !f->fonts_changed
         && (first_unchanged_at_end_row == NULL
             || IT_CHARPOS (it) < stop_pos))
     {
@@ -17443,7 +17489,7 @@ try_window_id (struct window *w)
        last_text_row = it.glyph_row - 1;
     }
 
-  if (fonts_changed_p)
+  if (f->fonts_changed)
     return -1;
 
 
@@ -17514,10 +17560,13 @@ try_window_id (struct window *w)
   /* Don't let the cursor end in the scroll margins.  */
   {
     int this_scroll_margin, cursor_height;
+    int frame_line_height = default_line_pixel_height (w);
+    int window_total_lines
+      = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (it.f) / frame_line_height;
 
     this_scroll_margin =
-      max (0, min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4));
-    this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+      max (0, min (scroll_margin, window_total_lines / 4));
+    this_scroll_margin *= frame_line_height;
     cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
 
     if ((w->cursor.y < this_scroll_margin
@@ -17657,7 +17706,7 @@ try_window_id (struct window *w)
       /* Set last_row to the glyph row in the current matrix where the
         window end line is found.  It has been moved up or down in
         the matrix by dvpos.  */
-      int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
+      int last_vpos = w->window_end_vpos + dvpos;
       struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
 
       /* If last_row is the window end line, it should display text.  */
@@ -17687,8 +17736,7 @@ try_window_id (struct window *w)
 
       /* Display the rest of the lines at the window end.  */
       it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
-      while (it.current_y < it.last_visible_y
-            && !fonts_changed_p)
+      while (it.current_y < it.last_visible_y && !f->fonts_changed)
        {
          /* Is it always sure that the display agrees with lines in
             the current matrix?  I don't think so, so we mark rows
@@ -17701,8 +17749,7 @@ try_window_id (struct window *w)
     }
 
   /* Update window_end_pos and window_end_vpos.  */
-  if (first_unchanged_at_end_row
-      && !last_text_row_at_end)
+  if (first_unchanged_at_end_row && !last_text_row_at_end)
     {
       /* Window end line if one of the preserved rows from the current
         matrix.  Set row to the last row displaying text in current
@@ -17712,23 +17759,13 @@ try_window_id (struct window *w)
       row = find_last_row_displaying_text (w->current_matrix, &it,
                                           first_unchanged_at_end_row);
       eassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
-
-      wset_window_end_pos (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
-      w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
-      wset_window_end_vpos
-       (w, make_number (MATRIX_ROW_VPOS (row, w->current_matrix)));
+      adjust_window_ends (w, row, 1);
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "A"));
     }
   else if (last_text_row_at_end)
     {
-      wset_window_end_pos
-       (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end)));
-      w->window_end_bytepos
-       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
-      wset_window_end_vpos
-       (w, make_number (MATRIX_ROW_VPOS (last_text_row_at_end,
-                                         desired_matrix)));
+      adjust_window_ends (w, last_text_row_at_end, 0);
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "B"));
     }
@@ -17737,12 +17774,7 @@ try_window_id (struct window *w)
       /* We have displayed either to the end of the window or at the
         end of the window, i.e. the last row with text is to be found
         in the desired matrix.  */
-      wset_window_end_pos
-       (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
-      w->window_end_bytepos
-       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-      wset_window_end_vpos
-       (w, make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix)));
+      adjust_window_ends (w, last_text_row, 0);
       eassert (w->window_end_bytepos >= 0);
     }
   else if (first_unchanged_at_end_row == NULL
@@ -17752,7 +17784,7 @@ try_window_id (struct window *w)
       /* Displayed to end of window, but no line containing text was
         displayed.  Lines were deleted at the end of the window.  */
       int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
-      int vpos = XFASTINT (w->window_end_vpos);
+      int vpos = w->window_end_vpos;
       struct glyph_row *current_row = current_matrix->rows + vpos;
       struct glyph_row *desired_row = desired_matrix->rows + vpos;
 
@@ -17770,8 +17802,8 @@ try_window_id (struct window *w)
        }
 
       eassert (row != NULL);
-      wset_window_end_vpos (w, make_number (vpos + 1));
-      wset_window_end_pos (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
+      w->window_end_vpos = vpos + 1;
+      w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "C"));
@@ -17779,8 +17811,8 @@ try_window_id (struct window *w)
   else
     emacs_abort ();
 
-  IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
-           debug_end_vpos = XFASTINT (w->window_end_vpos));
+  IF_DEBUG (debug_end_pos = w->window_end_pos;
+           debug_end_vpos = w->window_end_vpos);
 
   /* Record that display has not been completed.  */
   w->window_end_valid = 0;
@@ -19240,7 +19272,7 @@ display_line (struct it *it)
       >= it->w->desired_matrix->nrows)
     {
       it->w->nrows_scale_factor++;
-      fonts_changed_p = 1;
+      it->f->fonts_changed = 1;
       return 0;
     }
 
@@ -20060,7 +20092,7 @@ Value is the new character position of point.  */)
   (Lisp_Object direction)
 {
   struct window *w = XWINDOW (selected_window);
-  struct buffer *b = NULL;
+  struct buffer *b = XBUFFER (w->contents);
   struct glyph_row *row;
   int dir;
   Lisp_Object paragraph_dir;
@@ -20080,9 +20112,6 @@ Value is the new character position of point.  */)
   else
     dir = -1;
 
-  if (BUFFERP (w->contents))
-    b = XBUFFER (w->contents);
-
   /* If current matrix is up-to-date, we can use the information
      recorded in the glyphs, at least as long as the goal is on the
      screen.  */
@@ -20091,8 +20120,7 @@ Value is the new character position of point.  */)
       && b
       && !b->clip_changed
       && !b->prevent_redisplay_optimizations_p
-      && w->last_modified >= BUF_MODIFF (b)
-      && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)
+      && !window_outdated (w)
       && w->cursor.vpos >= 0
       && w->cursor.vpos < w->current_matrix->nrows
       && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
@@ -20596,13 +20624,8 @@ redisplay_mode_lines (Lisp_Object window, int force)
            {
              struct text_pos pt;
 
-             SET_TEXT_POS_FROM_MARKER (pt, w->pointm);
-             if (CHARPOS (pt) < BEGV)
-               TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
-             else if (CHARPOS (pt) > (ZV - 1))
-               TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
-             else
-               TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
+             CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
+             TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
            }
 
          /* Display mode lines.  */
@@ -21279,7 +21302,7 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string, int copy_st
          if (NILP (face))
            face = mode_line_string_face;
          else
-           face = Fcons (face, Fcons (mode_line_string_face, Qnil));
+           face = list2 (face, mode_line_string_face);
          props = Fplist_put (props, Qface, face);
        }
       Fadd_text_properties (make_number (0), make_number (len),
@@ -21303,8 +21326,8 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string, int copy_st
          if (NILP (face))
            face = mode_line_string_face;
          else
-           face = Fcons (face, Fcons (mode_line_string_face, Qnil));
-         props = Fcons (Qface, Fcons (face, Qnil));
+           face = list2 (face, mode_line_string_face);
+         props = list2 (Qface, face);
          if (copy_string)
            lisp_string = Fcopy_sequence (lisp_string);
        }
@@ -21418,7 +21441,7 @@ are the selected window and the WINDOW's buffer).  */)
       mode_line_string_list = Qnil;
       mode_line_string_face = face;
       mode_line_string_face_prop
-       = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
+       = NILP (face) ? Qnil : list2 (Qface, face);
     }
 
   push_kboard (FRAME_KBOARD (it.f));
@@ -21952,7 +21975,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        ptrdiff_t pos = marker_position (w->start);
        ptrdiff_t total = BUF_ZV (b) - BUF_BEGV (b);
 
-       if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
+       if (w->window_end_pos <= BUF_Z (b) - BUF_ZV (b))
          {
            if (pos <= BUF_BEGV (b))
              return "All";
@@ -21981,7 +22004,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
     case 'P':
       {
        ptrdiff_t toppos = marker_position (w->start);
-       ptrdiff_t botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
+       ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
        ptrdiff_t total = BUF_ZV (b) - BUF_BEGV (b);
 
        if (botpos >= BUF_ZV (b))
@@ -23801,17 +23824,15 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          && hlinfo->mouse_face_beg_row >= 0
          && hlinfo->mouse_face_end_row >= 0)
        {
-         struct glyph_row *mouse_beg_row, *mouse_end_row;
-
-         mouse_beg_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
-         mouse_end_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
+         ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
 
-         if (row >= mouse_beg_row && row <= mouse_end_row)
+         if (row_vpos >= hlinfo->mouse_face_beg_row
+             && row_vpos <= hlinfo->mouse_face_end_row)
            {
              check_mouse_face = 1;
-             mouse_beg_col = (row == mouse_beg_row)
+             mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
                ? hlinfo->mouse_face_beg_col : 0;
-             mouse_end_col = (row == mouse_end_row)
+             mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
                ? hlinfo->mouse_face_end_col
                : row->used[TEXT_AREA];
            }
@@ -23979,12 +24000,12 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 
 #define IT_EXPAND_MATRIX_WIDTH(it, area)               \
   {                                                    \
-    if (!fonts_changed_p                               \
+    if (!it->f->fonts_changed                          \
        && (it->glyph_row->glyphs[area]                 \
            < it->glyph_row->glyphs[area + 1]))         \
       {                                                        \
        it->w->ncols_scale_factor++;                    \
-       fonts_changed_p = 1;                            \
+       it->f->fonts_changed = 1;                       \
       }                                                        \
   }
 
@@ -24900,21 +24921,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
   base_height = it->ascent + it->descent;
   base_width = font->average_width;
 
-  /* Get a face ID for the glyph by utilizing a cache (the same way as
-     done for `escape-glyph' in get_next_display_element).  */
-  if (it->f == last_glyphless_glyph_frame
-      && it->face_id == last_glyphless_glyph_face_id)
-    {
-      face_id = last_glyphless_glyph_merged_face_id;
-    }
-  else
-    {
-      /* Merge the `glyphless-char' face into the current face.  */
-      face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
-      last_glyphless_glyph_frame = it->f;
-      last_glyphless_glyph_face_id = it->face_id;
-      last_glyphless_glyph_merged_face_id = face_id;
-    }
+  face_id = merge_glyphless_glyph_face (it);
 
   if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
     {
@@ -25702,17 +25709,16 @@ x_produce_glyphs (struct it *it)
 
 /* 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.  */
+   Advance the nominal cursor over the text.  UPDATED_ROW is the glyph row
+   being updated, and UPDATED_AREA is the area of that row being updated.  */
 
 void
-x_write_glyphs (struct glyph *start, int len)
+x_write_glyphs (struct window *w, struct glyph_row *updated_row,
+               struct glyph *start, enum glyph_row_area updated_area, int len)
 {
-  int x, hpos, chpos = updated_window->phys_cursor.hpos;
+  int x, hpos, chpos = w->phys_cursor.hpos;
 
-  eassert (updated_window && updated_row);
+  eassert (updated_row);
   /* When the window is hscrolled, cursor hpos can legitimately be out
      of bounds, but we draw the cursor at the corresponding window
      margin in that case.  */
@@ -25726,24 +25732,24 @@ x_write_glyphs (struct glyph *start, int len)
   /* Write glyphs.  */
 
   hpos = start - updated_row->glyphs[updated_area];
-  x = draw_glyphs (updated_window, output_cursor.x,
+  x = draw_glyphs (w, w->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
+      && w->phys_cursor_on_p
+      && w->phys_cursor.vpos == w->output_cursor.vpos
       && chpos >= hpos
       && chpos < hpos + len)
-    updated_window->phys_cursor_on_p = 0;
+    w->phys_cursor_on_p = 0;
 
   unblock_input ();
 
   /* Advance the output cursor.  */
-  output_cursor.hpos += len;
-  output_cursor.x = x;
+  w->output_cursor.hpos += len;
+  w->output_cursor.x = x;
 }
 
 
@@ -25751,19 +25757,18 @@ x_write_glyphs (struct glyph *start, int len)
    Insert LEN glyphs from START at the nominal cursor position.  */
 
 void
-x_insert_glyphs (struct glyph *start, int len)
+x_insert_glyphs (struct window *w, struct glyph_row *updated_row,
+                struct glyph *start, enum glyph_row_area updated_area, 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;
   ptrdiff_t hpos;
 
-  eassert (updated_window && updated_row);
+  eassert (updated_row);
   block_input ();
-  w = updated_window;
   f = XFRAME (WINDOW_FRAME (w));
 
   /* Get the height of the line we are in.  */
@@ -25777,25 +25782,25 @@ x_insert_glyphs (struct glyph *start, int len)
 
   /* Get the width of the region to shift right.  */
   shifted_region_width = (window_box_width (w, updated_area)
-                         - output_cursor.x
+                         - w->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_x = window_box_left (w, updated_area) + w->output_cursor.x;
+  frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, 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,
+  draw_glyphs (w, 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;
+  w->output_cursor.hpos += len;
+  w->output_cursor.x += shift_by_width;
   unblock_input ();
 }
 
@@ -25805,18 +25810,18 @@ x_insert_glyphs (struct glyph *start, int len)
    (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.  */
+   TO_X is a pixel position relative to UPDATED_AREA of currently
+   updated window W.  TO_X == -1 means clear to the end of this area.  */
 
 void
-x_clear_end_of_line (int to_x)
+x_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
+                    enum glyph_row_area updated_area, 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;
 
-  eassert (updated_window && updated_row);
+  eassert (updated_row);
   f = XFRAME (w->frame);
 
   if (updated_row->full_width_p)
@@ -25834,16 +25839,16 @@ x_clear_end_of_line (int to_x)
   else
     to_x = min (to_x, max_x);
 
-  to_y = min (max_y, output_cursor.y + updated_row->height);
+  to_y = min (max_y, w->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,
+                              w->output_cursor.x, -1,
                               updated_row->y,
                               MATRIX_ROW_BOTTOM_Y (updated_row));
 
-  from_x = output_cursor.x;
+  from_x = w->output_cursor.x;
 
   /* Translate to frame coordinates.  */
   if (updated_row->full_width_p)
@@ -25859,7 +25864,7 @@ x_clear_end_of_line (int to_x)
     }
 
   min_y = WINDOW_HEADER_LINE_HEIGHT (w);
-  from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
+  from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
 
   /* Prevent inadvertently clearing to end of the X window.  */
@@ -25955,6 +25960,9 @@ set_frame_cursor_types (struct frame *f, Lisp_Object arg)
     }
   else
     FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
+
+  /* Make sure the cursor gets redrawn.  */
+  f->cursor_type_changed = 1;
 }
 
 
@@ -26005,7 +26013,7 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
 
   /* Detect a nonselected window or nonselected frame.  */
   else if (w != XWINDOW (f->selected_window)
-          || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
+          || f != FRAME_DISPLAY_INFO (f)->x_highlight_frame)
     {
       *active_cursor = 0;
 
@@ -26403,7 +26411,7 @@ erase_phys_cursor (struct window *w)
    where to put the cursor is specified by HPOS, VPOS, X and Y.  */
 
 void
-display_and_set_cursor (struct window *w, int on,
+display_and_set_cursor (struct window *w, bool on,
                        int hpos, int vpos, int x, int y)
 {
   struct frame *f = XFRAME (w->frame);
@@ -26487,7 +26495,7 @@ display_and_set_cursor (struct window *w, int on,
    of ON.  */
 
 static void
-update_window_cursor (struct window *w, int on)
+update_window_cursor (struct window *w, bool on)
 {
   /* Don't update cursor in windows whose frame is in the process
      of being deleted.  */
@@ -26523,7 +26531,7 @@ update_window_cursor (struct window *w, int on)
    in the window tree rooted at W.  */
 
 static void
-update_cursor_in_window_tree (struct window *w, int on_p)
+update_cursor_in_window_tree (struct window *w, bool on_p)
 {
   while (w)
     {
@@ -26542,7 +26550,7 @@ update_cursor_in_window_tree (struct window *w, int on_p)
    Don't change the cursor's position.  */
 
 void
-x_update_cursor (struct frame *f, int on_p)
+x_update_cursor (struct frame *f, bool on_p)
 {
   update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
 }
@@ -26702,10 +26710,13 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
   /* Change the mouse cursor.  */
   if (FRAME_WINDOW_P (f))
     {
+#if ! defined (USE_GTK) && ! defined (HAVE_NS)
       if (draw == DRAW_NORMAL_TEXT
          && !EQ (hlinfo->mouse_face_window, f->tool_bar_window))
        FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
-      else if (draw == DRAW_MOUSE_FACE)
+      else
+#endif
+      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);
@@ -26729,10 +26740,7 @@ clear_mouse_face (Mouse_HLInfo *hlinfo)
       cleared = 1;
     }
 
-  hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
-  hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
-  hlinfo->mouse_face_window = Qnil;
-  hlinfo->mouse_face_overlay = Qnil;
+  reset_mouse_highlight (hlinfo);
   return cleared;
 }
 
@@ -26993,7 +27001,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
   /* Find the rows corresponding to START_CHARPOS and END_CHARPOS.  */
   rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
   if (r1 == NULL)
-    r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+    r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
   /* If the before-string or display-string contains newlines,
      rows_from_pos_range skips to its last row.  Move back.  */
   if (!NILP (before_string) || !NILP (disp_string))
@@ -27015,7 +27023,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
     }
   if (r2 == NULL)
     {
-      r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+      r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
       hlinfo->mouse_face_past_end = 1;
     }
   else if (!NILP (after_string))
@@ -27023,7 +27031,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
       /* If the after-string has newlines, advance to its last row.  */
       struct glyph_row *next;
       struct glyph_row *last
-       = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+       = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
 
       for (next = r2 + 1;
           next <= last
@@ -27045,9 +27053,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
       r1 = tem;
     }
 
-  hlinfo->mouse_face_beg_y = r1->y;
   hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
-  hlinfo->mouse_face_end_y = r2->y;
   hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
 
   /* For a bidi-reordered row, the positions of BEFORE_STRING,
@@ -27411,7 +27417,6 @@ mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
              {
                hlinfo->mouse_face_beg_row
                  = MATRIX_ROW_VPOS (r, w->current_matrix);
-               hlinfo->mouse_face_beg_y = r->y;
                hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
                hlinfo->mouse_face_beg_x = gx;
                found = 1;
@@ -27430,7 +27435,6 @@ mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
              {
                hlinfo->mouse_face_beg_row
                  = MATRIX_ROW_VPOS (r, w->current_matrix);
-               hlinfo->mouse_face_beg_y = r->y;
                hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
                for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
                  gx += g1->pixel_width;
@@ -27467,9 +27471,8 @@ mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
   /* The highlighted region ends on the previous row.  */
   r--;
 
-  /* Set the end row and its vertical pixel coordinate.  */
+  /* Set the end row.  */
   hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
-  hlinfo->mouse_face_end_y = r->y;
 
   /* Compute and set the end column and the end column's horizontal
      pixel coordinate.  */
@@ -27663,7 +27666,7 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer)
        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;
+       cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
 #endif
       else if (EQ (pointer, intern ("hourglass")))
        cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
@@ -27826,7 +27829,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
       /* Change the mouse pointer according to what is under it.  */
       if (FRAME_WINDOW_P (f))
        {
-         dpyinfo = FRAME_X_DISPLAY_INFO (f);
+         dpyinfo = FRAME_DISPLAY_INFO (f);
          if (STRINGP (string))
            {
              cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -27848,7 +27851,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
            }
          else
            /* Default mode-line pointer.  */
-           cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
+           cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
        }
 #endif
     }
@@ -27967,8 +27970,6 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
 
          hlinfo->mouse_face_beg_row  = vpos;
          hlinfo->mouse_face_end_row  = hlinfo->mouse_face_beg_row;
-         hlinfo->mouse_face_beg_y    = 0;
-         hlinfo->mouse_face_end_y    = 0;
          hlinfo->mouse_face_past_end = 0;
          hlinfo->mouse_face_window   = window;
 
@@ -28053,7 +28054,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
   w = XWINDOW (window);
   frame_to_window_pixel_xy (w, &x, &y);
 
-#ifdef HAVE_WINDOW_SYSTEM
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
   /* Handle tool-bar window differently since it doesn't display a
      buffer.  */
   if (EQ (window, f->tool_bar_window))
@@ -28087,10 +28088,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
   b = XBUFFER (w->contents);
-  if (part == ON_TEXT
-      && w->window_end_valid
-      && w->last_modified == BUF_MODIFF (b)
-      && w->last_overlay_modified == BUF_OVERLAY_MODIFF (b))
+  if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
     {
       int hpos, vpos, dx, dy, area = LAST_AREA;
       ptrdiff_t pos;
@@ -28332,8 +28330,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
                    : Qnil;
                  Lisp_Object lim2 =
                    NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
-                   ? make_number (BUF_Z (XBUFFER (buffer))
-                                  - XFASTINT (w->window_end_pos))
+                   ? make_number (BUF_Z (XBUFFER (buffer)) - w->window_end_pos)
                    : Qnil;
 
                  if (NILP (overlay))
@@ -28531,11 +28528,7 @@ cancel_mouse_face (struct frame *f)
 
   window = hlinfo->mouse_face_window;
   if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
-    {
-      hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
-      hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
-      hlinfo->mouse_face_window = Qnil;
-    }
+    reset_mouse_highlight (hlinfo);
 }
 
 
@@ -28735,7 +28728,7 @@ x_draw_vertical_border (struct window *w)
     {
       int x0, x1, y0, y1;
 
-      window_box_edges (w, -1, &x0, &y0, &x1, &y1);
+      window_box_edges (w, &x0, &y0, &x1, &y1);
       y1 -= 1;
 
       if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
@@ -28748,7 +28741,7 @@ x_draw_vertical_border (struct window *w)
     {
       int x0, x1, y0, y1;
 
-      window_box_edges (w, -1, &x0, &y0, &x1, &y1);
+      window_box_edges (w, &x0, &y0, &x1, &y1);
       y1 -= 1;
 
       if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
@@ -28781,7 +28774,7 @@ expose_window (struct window *w, XRectangle *fr)
   /* 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)
+  if (w->must_be_updated_p)
     {
       SET_FRAME_GARBAGED (f);
       return 0;
@@ -28974,9 +28967,11 @@ expose_frame (struct frame *f, int x, int y, int w, int 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 ! defined (USE_GTK) && ! defined (HAVE_NS)
   if (WINDOWP (f->tool_bar_window))
     mouse_face_overwritten_p
       |= expose_window (XWINDOW (f->tool_bar_window), &r);
+#endif
 
 #ifdef HAVE_X_WINDOWS
 #ifndef MSDOS
@@ -29168,9 +29163,8 @@ syms_of_xdisp (void)
   DEFSYM (Qarrow, "arrow");
   DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
 
-  list_of_error = Fcons (Fcons (intern_c_string ("error"),
-                               Fcons (intern_c_string ("void-variable"), Qnil)),
-                        Qnil);
+  list_of_error = list1 (list2 (intern_c_string ("error"),
+                               intern_c_string ("void-variable")));
   staticpro (&list_of_error);
 
   DEFSYM (Qlast_arrow_position, "last-arrow-position");
@@ -29274,7 +29268,7 @@ See also `overlay-arrow-position'.  */);
 The symbols on this list are examined during redisplay to determine
 where to display overlay arrows.  */);
   Voverlay_arrow_variable_list
-    = Fcons (intern_c_string ("overlay-arrow-position"), Qnil);
+    = list1 (intern_c_string ("overlay-arrow-position"));
 
   DEFVAR_INT ("scroll-step", emacs_scroll_step,
     doc: /* The number of lines to try scrolling a window by when point moves out.
@@ -29658,8 +29652,10 @@ cursor shapes.  */);
               doc: /* Seconds to wait before displaying an hourglass pointer when Emacs is busy.  */);
   Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
 
+#ifdef HAVE_WINDOW_SYSTEM
   hourglass_atimer = NULL;
   hourglass_shown_p = 0;
+#endif /* HAVE_WINDOW_SYSTEM */
 
   DEFSYM (Qglyphless_char, "glyphless-char");
   DEFSYM (Qhex_code, "hex-code");
@@ -29668,10 +29664,6 @@ cursor shapes.  */);
   DEFSYM (Qzero_width, "zero-width");
 
   DEFSYM (Qglyphless_char_display, "glyphless-char-display");
-  /* Intern this now in case it isn't already done.
-     Setting this variable twice is harmless.
-     But don't staticpro it here--that is done in alloc.c.  */
-  Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots");
   Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1));
 
   DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
@@ -29705,8 +29697,6 @@ Its value should be an ASCII acronym string, `hex-code', `empty-box', or
 void
 init_xdisp (void)
 {
-  current_header_line_height = current_mode_line_height = -1;
-
   CHARPOS (this_line_start_pos) = 0;
 
   if (!noninteractive)
@@ -29750,27 +29740,28 @@ init_xdisp (void)
   help_echo_showing_p = 0;
 }
 
+#ifdef HAVE_WINDOW_SYSTEM
+
 /* Platform-independent portion of hourglass implementation.  */
 
 /* Cancel a currently active hourglass timer, and start a new one.  */
 void
 start_hourglass (void)
 {
-#if defined (HAVE_WINDOW_SYSTEM)
-  EMACS_TIME delay;
+  struct timespec delay;
 
   cancel_hourglass ();
 
   if (INTEGERP (Vhourglass_delay)
       && XINT (Vhourglass_delay) > 0)
-    delay = make_emacs_time (min (XINT (Vhourglass_delay),
+    delay = make_timespec (min (XINT (Vhourglass_delay),
                                  TYPE_MAXIMUM (time_t)),
-                            0);
+                          0);
   else if (FLOATP (Vhourglass_delay)
           && XFLOAT_DATA (Vhourglass_delay) > 0)
-    delay = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (Vhourglass_delay));
+    delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
   else
-    delay = make_emacs_time (DEFAULT_HOURGLASS_DELAY, 0);
+    delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
 
 #ifdef HAVE_NTGUI
   {
@@ -29781,7 +29772,6 @@ start_hourglass (void)
 
   hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
                                   show_hourglass, NULL);
-#endif
 }
 
 
@@ -29790,7 +29780,6 @@ start_hourglass (void)
 void
 cancel_hourglass (void)
 {
-#if defined (HAVE_WINDOW_SYSTEM)
   if (hourglass_atimer)
     {
       cancel_atimer (hourglass_atimer);
@@ -29799,5 +29788,6 @@ cancel_hourglass (void)
 
   if (hourglass_shown_p)
     hide_hourglass ();
-#endif
 }
+
+#endif /* HAVE_WINDOW_SYSTEM */