* lisp.h (last_glyphless_glyph_frame, last_glyphless_glyph_face_id)
[bpt/emacs.git] / src / xdisp.c
index 37f2c94..d5def06 100644 (file)
@@ -299,19 +299,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 +512,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 +569,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 +740,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 +749,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 +760,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);
@@ -966,12 +953,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;
@@ -982,22 +969,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;
        }
     }
@@ -1053,11 +1036,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;
 
@@ -1085,21 +1068,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;
@@ -1115,25 +1098,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);
@@ -1149,27 +1132,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
  ***********************************************************************/
@@ -1356,12 +1339,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));
 
@@ -1654,8 +1637,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))
@@ -2465,7 +2446,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
  ***********************************************************************/
@@ -2601,8 +2591,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));
@@ -3908,10 +3897,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);
        }
 
@@ -6673,17 +6666,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)
@@ -6831,24 +6866,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);
@@ -6880,27 +6901,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: */
 
@@ -7042,7 +7046,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
@@ -7457,6 +7463,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);
@@ -7469,6 +7477,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);
 
@@ -7484,6 +7494,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.  */
@@ -9058,7 +9103,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;
@@ -11396,62 +11441,6 @@ 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 currently 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.
-
-   This is always done during window update, so the position is the
-   future output cursor position for currently updated window W.
-   NOTE: W is used only to check whether this function is called
-   in a consistent manner via the redisplay interface.  */
-
-void
-x_cursor_to (struct window *w, int vpos, int hpos, int y, int x)
-{
-  eassert (w);
-
-  /* Set the output cursor.  */
-  output_cursor.hpos = hpos;
-  output_cursor.vpos = vpos;
-  output_cursor.x = x;
-  output_cursor.y = y;
-}
-
-#endif /* HAVE_WINDOW_SYSTEM */
-
-\f
 /***********************************************************************
                               Tool-bars
  ***********************************************************************/
@@ -12003,7 +11992,7 @@ redisplay_tool_bar (struct frame *f)
          if (WINDOW_TOTAL_LINES (w) != old_height)
            {
              clear_glyph_matrix (w->desired_matrix);
-             fonts_changed_p = 1;
+             f->fonts_changed = 1;
              return 1;
            }
        }
@@ -12104,7 +12093,7 @@ redisplay_tool_bar (struct frame *f)
                {
                  clear_glyph_matrix (w->desired_matrix);
                  f->n_tool_bar_rows = nrows;
-                 fonts_changed_p = 1;
+                 f->fonts_changed = 1;
                  return 1;
                }
            }
@@ -12335,13 +12324,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;
 
@@ -12992,15 +12979,6 @@ redisplay_internal (void)
   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.  */
@@ -13031,7 +13009,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);
     }
 
@@ -13080,8 +13070,7 @@ redisplay_internal (void)
     }
 
   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.  */
@@ -13115,9 +13104,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;
@@ -13174,6 +13161,7 @@ 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
       && match_p
@@ -13272,12 +13260,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.  */
@@ -13392,6 +13380,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
@@ -13411,20 +13401,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
@@ -13438,6 +13430,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;
                }
            }
@@ -13482,7 +13475,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.
@@ -13499,6 +13492,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
@@ -13513,6 +13507,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;
        }
@@ -13553,7 +13548,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
@@ -13694,7 +13688,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))
@@ -14908,7 +14902,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.  */
@@ -14960,6 +14972,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.  */
@@ -14973,7 +14989,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.  */
@@ -14987,13 +15003,6 @@ 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 ()))
     {
@@ -15023,12 +15032,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)
@@ -15307,7 +15316,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;
@@ -15327,9 +15336,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)
@@ -15448,8 +15456,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
@@ -15458,6 +15466,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.  */
@@ -15711,7 +15722,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;
@@ -15781,12 +15792,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)
@@ -15974,7 +15985,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)
@@ -15987,7 +15998,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
@@ -15997,7 +16008,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);
@@ -16100,7 +16111,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);
        }
@@ -16110,12 +16122,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;
     }
 
@@ -16180,8 +16193,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:
@@ -16253,7 +16266,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;
     }
 
@@ -16290,8 +16303,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
@@ -16300,21 +16312,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.  */
@@ -16357,7 +16364,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.  */
@@ -16405,8 +16412,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
@@ -16538,32 +16544,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;
 
@@ -16634,7 +16623,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;
 
@@ -16748,20 +16737,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;
@@ -16901,11 +16879,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))
@@ -16916,7 +16894,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;
@@ -17157,7 +17135,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.
@@ -17250,7 +17228,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)
@@ -17262,7 +17240,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;
@@ -17333,10 +17311,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);
@@ -17369,7 +17345,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);
 
@@ -17490,7 +17466,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))
     {
@@ -17498,7 +17474,7 @@ try_window_id (struct window *w)
        last_text_row = it.glyph_row - 1;
     }
 
-  if (fonts_changed_p)
+  if (f->fonts_changed)
     return -1;
 
 
@@ -17715,7 +17691,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.  */
@@ -17745,8 +17721,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
@@ -17759,8 +17734,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
@@ -17770,23 +17744,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"));
     }
@@ -17795,12 +17759,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
@@ -17810,7 +17769,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;
 
@@ -17828,8 +17787,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"));
@@ -17837,8 +17796,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;
@@ -19298,7 +19257,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;
     }
 
@@ -20650,13 +20609,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.  */
@@ -22006,7 +21960,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";
@@ -22035,7 +21989,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))
@@ -24031,12 +23985,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;                       \
       }                                                        \
   }
 
@@ -24952,21 +24906,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)
     {
@@ -25754,12 +25694,12 @@ 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_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 window *w, 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 = w->phys_cursor.hpos;
 
@@ -25777,7 +25717,7 @@ x_write_glyphs (struct window *w, struct glyph *start, int len)
   /* Write glyphs.  */
 
   hpos = start - updated_row->glyphs[updated_area];
-  x = draw_glyphs (w, output_cursor.x,
+  x = draw_glyphs (w, w->output_cursor.x,
                   updated_row, updated_area,
                   hpos, hpos + len,
                   DRAW_NORMAL_TEXT, 0);
@@ -25785,7 +25725,7 @@ x_write_glyphs (struct window *w, struct glyph *start, int len)
   /* Invalidate old phys cursor if the glyph at its hpos is redrawn.  */
   if (updated_area == TEXT_AREA
       && w->phys_cursor_on_p
-      && w->phys_cursor.vpos == output_cursor.vpos
+      && w->phys_cursor.vpos == w->output_cursor.vpos
       && chpos >= hpos
       && chpos < hpos + len)
     w->phys_cursor_on_p = 0;
@@ -25793,8 +25733,8 @@ x_write_glyphs (struct window *w, struct glyph *start, int len)
   unblock_input ();
 
   /* Advance the output cursor.  */
-  output_cursor.hpos += len;
-  output_cursor.x = x;
+  w->output_cursor.hpos += len;
+  w->output_cursor.x = x;
 }
 
 
@@ -25802,7 +25742,8 @@ x_write_glyphs (struct window *w, struct glyph *start, int len)
    Insert LEN glyphs from START at the nominal cursor position.  */
 
 void
-x_insert_glyphs (struct window *w, 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;
   int line_height, shift_by_width, shifted_region_width;
@@ -25826,25 +25767,25 @@ x_insert_glyphs (struct window *w, 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 ();
 }
 
@@ -25854,11 +25795,12 @@ x_insert_glyphs (struct window *w, 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 currently
+   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 (struct window *w, 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;
   int max_x, min_y, max_y;
@@ -25882,16 +25824,16 @@ x_clear_end_of_line (struct window *w, 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)
@@ -25907,7 +25849,7 @@ x_clear_end_of_line (struct window *w, 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.  */
@@ -26003,6 +25945,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;
 }
 
 
@@ -26451,7 +26396,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);
@@ -26535,7 +26480,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.  */
@@ -26571,7 +26516,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)
     {
@@ -26590,7 +26535,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);
 }
@@ -26777,10 +26722,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;
 }
 
@@ -27041,7 +26983,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))
@@ -27063,7 +27005,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))
@@ -27071,7 +27013,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
@@ -27093,9 +27035,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,
@@ -27459,7 +27399,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;
@@ -27478,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];
                for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
                  gx += g1->pixel_width;
@@ -27515,9 +27453,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.  */
@@ -28015,8 +27952,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;
 
@@ -28377,8 +28312,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))
@@ -28576,11 +28510,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);
 }
 
 
@@ -28780,7 +28710,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)
@@ -28793,7 +28723,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)
@@ -29702,8 +29632,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");
@@ -29712,10 +29644,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,
@@ -29749,8 +29677,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)
@@ -29794,27 +29720,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
   {
@@ -29825,7 +29752,6 @@ start_hourglass (void)
 
   hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
                                   show_hourglass, NULL);
-#endif
 }
 
 
@@ -29834,7 +29760,6 @@ start_hourglass (void)
 void
 cancel_hourglass (void)
 {
-#if defined (HAVE_WINDOW_SYSTEM)
   if (hourglass_atimer)
     {
       cancel_atimer (hourglass_atimer);
@@ -29843,5 +29768,6 @@ cancel_hourglass (void)
 
   if (hourglass_shown_p)
     hide_hourglass ();
-#endif
 }
+
+#endif /* HAVE_WINDOW_SYSTEM */