Merge from emacs-24; up to 2012-12-06T01:39:03Z!monnier@iro.umontreal.ca
[bpt/emacs.git] / src / xdisp.c
index 0eae25d..8b0d8b6 100644 (file)
@@ -1,6 +1,7 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
+Inc.
 
 This file is part of GNU Emacs.
 
@@ -273,16 +274,16 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <stdio.h>
 #include <limits.h>
-#include <setjmp.h>
 
 #include "lisp.h"
+#include "atimer.h"
 #include "keyboard.h"
 #include "frame.h"
 #include "window.h"
 #include "termchar.h"
 #include "dispextern.h"
-#include "buffer.h"
 #include "character.h"
+#include "buffer.h"
 #include "charset.h"
 #include "indent.h"
 #include "commands.h"
@@ -302,7 +303,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
 #include "w32term.h"
 #endif
 #ifdef HAVE_NS
@@ -333,10 +334,10 @@ static Lisp_Object Qinhibit_eval_during_redisplay;
 static Lisp_Object Qbuffer_position, Qposition, Qobject;
 static Lisp_Object Qright_to_left, Qleft_to_right;
 
-/* Cursor shapes */
+/* Cursor shapes */
 Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
 
-/* Pointer shapes */
+/* Pointer shapes */
 static Lisp_Object Qarrow, Qhand;
 Lisp_Object Qtext;
 
@@ -347,6 +348,7 @@ static Lisp_Object Qfontification_functions;
 
 static Lisp_Object Qwrap_prefix;
 static Lisp_Object Qline_prefix;
+static Lisp_Object Qredisplay_internal;
 
 /* Non-nil means don't actually do any redisplay.  */
 
@@ -365,6 +367,28 @@ Lisp_Object Qcenter;
 static Lisp_Object Qmargin, Qpointer;
 static Lisp_Object Qline_height;
 
+/* These setters are used only in this file, so they can be private.  */
+static void
+wset_base_line_number (struct window *w, Lisp_Object val)
+{
+  w->base_line_number = val;
+}
+static void
+wset_base_line_pos (struct window *w, Lisp_Object val)
+{
+  w->base_line_pos = val;
+}
+static void
+wset_column_number_displayed (struct window *w, Lisp_Object val)
+{
+  w->column_number_displayed = val;
+}
+static void
+wset_region_showing (struct window *w, Lisp_Object val)
+{
+  w->region_showing = val;
+}
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Test if overflow newline into fringe.  Called with iterator IT
@@ -492,12 +516,6 @@ Lisp_Object Qmenu_bar_update_hook;
 
 static int overlay_arrow_seen;
 
-/* Number of windows showing the buffer of the selected window (or
-   another buffer with the same base buffer).  keyboard.c refers to
-   this.  */
-
-int buffer_shared;
-
 /* Vector containing glyphs for an ellipsis `...'.  */
 
 static Lisp_Object default_invis_vector[3];
@@ -627,10 +645,10 @@ int current_mode_line_height, current_header_line_height;
     CACHE = NULL;                              \
   } while (0)
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
 
 /* Non-zero means print traces of redisplay if compiled with
-   GLYPH_DEBUG != 0.  */
+   GLYPH_DEBUG defined.  */
 
 int trace_redisplay_p;
 
@@ -746,9 +764,9 @@ static int clear_image_cache_count;
 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 #endif
 
-/* Non-zero while redisplay_internal is in progress.  */
+/* True while redisplay_internal is in progress.  */
 
-int redisplaying_p;
+bool redisplaying_p;
 
 static Lisp_Object Qinhibit_free_realized_faces;
 static Lisp_Object Qmode_line_default_help_echo;
@@ -838,7 +856,6 @@ static int string_char_and_length (const unsigned char *, int *);
 static struct text_pos display_prop_end (struct it *, Lisp_Object,
                                          struct text_pos);
 static int compute_window_start_on_continuation_line (struct window *);
-static Lisp_Object safe_eval_handler (Lisp_Object);
 static void insert_left_trunc_glyphs (struct it *);
 static struct glyph_row *get_overlay_arrow_glyph_row (struct window *,
                                                       Lisp_Object);
@@ -853,7 +870,6 @@ static void push_it (struct it *, struct text_pos *);
 static void iterate_out_of_display_property (struct it *);
 static void pop_it (struct it *);
 static void sync_frame_with_window_matrix_rows (struct window *);
-static void select_frame_for_redisplay (Lisp_Object);
 static void redisplay_internal (void);
 static int echo_area_display (int);
 static void redisplay_windows (Lisp_Object);
@@ -906,6 +922,7 @@ static enum move_it_result
        move_it_in_display_line_to (struct it *, ptrdiff_t, int,
                                   enum move_operation_enum);
 void move_it_vertically_backward (struct it *, int);
+static void get_visually_first_element (struct it *);
 static void init_to_row_start (struct it *, struct window *,
                                struct glyph_row *);
 static int init_to_row_end (struct it *, struct window *,
@@ -951,6 +968,7 @@ static void append_stretch_glyph (struct it *, Lisp_Object,
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
+static void produce_special_glyphs (struct it *, enum display_element_type);
 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
 static int coords_in_mouse_face_p (struct window *, int, int);
 
@@ -1025,7 +1043,7 @@ window_box_height (struct window *w)
   struct frame *f = XFRAME (w->frame);
   int height = WINDOW_TOTAL_HEIGHT (w);
 
-  xassert (height >= 0);
+  eassert (height >= 0);
 
   /* Note: the code below that determines the mode-line/header-line
      height is essentially the same as that contained in the macro
@@ -1168,7 +1186,7 @@ window_box (struct window *w, int area, int *box_x, int *box_y,
    *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
    box.  */
 
-static inline void
+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)
 {
@@ -1251,6 +1269,23 @@ string_from_display_spec (Lisp_Object spec)
   return spec;
 }
 
+
+/* Limit insanely large values of W->hscroll on frame F to the largest
+   value that will still prevent first_visible_x and last_visible_x of
+   'struct it' from overflowing an int.  */
+static int
+window_hscroll_limited (struct window *w, struct frame *f)
+{
+  ptrdiff_t window_hscroll = w->hscroll;
+  int window_text_width = window_box_width (w, TEXT_AREA);
+  int colwidth = FRAME_COLUMN_WIDTH (f);
+
+  if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
+    window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
+
+  return window_hscroll;
+}
+
 /* Return 1 if position CHARPOS is visible in window W.
    CHARPOS < 0 means return info about WINDOW_END position.
    If visible, set *X and *Y to pixel coordinates of top left corner.
@@ -1292,10 +1327,10 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   if (WINDOW_WANTS_HEADER_LINE_P (w))
     current_header_line_height
       = display_mode_line (w, HEADER_LINE_FACE_ID,
-                              BVAR (current_buffer, header_line_format));
+                          BVAR (current_buffer, header_line_format));
 
   start_display (&it, w, top);
-  move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
+  move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
              (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
 
   if (charpos >= 0
@@ -1303,7 +1338,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
           && IT_CHARPOS (it) >= charpos)
          /* When scanning backwards under bidi iteration, move_it_to
             stops at or _before_ CHARPOS, because it stops at or to
-            the _right_ of the character at CHARPOS. */
+            the _right_ of the character at CHARPOS.  */
          || (it.bidi_p && it.bidi_it.scan_dir == -1
              && IT_CHARPOS (it) <= charpos)))
     {
@@ -1511,7 +1546,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                          --g;
                          top_x -= g->pixel_width;
                        }
-                     xassert (g < it3.glyph_row->glyphs[TEXT_AREA]
+                     eassert (g < it3.glyph_row->glyphs[TEXT_AREA]
                                    + it3.glyph_row->used[TEXT_AREA]);
                    }
                }
@@ -1562,8 +1597,10 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
 
   current_header_line_height = current_mode_line_height = -1;
 
-  if (visible_p && XFASTINT (w->hscroll) > 0)
-    *x -= XFASTINT (w->hscroll) * WINDOW_FRAME_COLUMN_WIDTH (w);
+  if (visible_p && w->hscroll > 0)
+    *x -=
+      window_hscroll_limited (w, WINDOW_XFRAME (w))
+      * WINDOW_FRAME_COLUMN_WIDTH (w);
 
 #if 0
   /* Debugging code.  */
@@ -1583,7 +1620,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
    returns an invalid character.  If we find one, we return a `?', but
    with the length of the invalid character.  */
 
-static inline int
+static int
 string_char_and_length (const unsigned char *str, int *len)
 {
   int c;
@@ -1606,7 +1643,7 @@ string_char_and_length (const unsigned char *str, int *len)
 static struct text_pos
 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
 {
-  xassert (STRINGP (string) && nchars >= 0);
+  eassert (STRINGP (string) && nchars >= 0);
 
   if (STRING_MULTIBYTE (string))
     {
@@ -1631,12 +1668,12 @@ string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t ncha
 /* Value is the text position, i.e. character and byte position,
    for character position CHARPOS in STRING.  */
 
-static inline struct text_pos
+static struct text_pos
 string_pos (ptrdiff_t charpos, Lisp_Object string)
 {
   struct text_pos pos;
-  xassert (STRINGP (string));
-  xassert (charpos >= 0);
+  eassert (STRINGP (string));
+  eassert (charpos >= 0);
   SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
   return pos;
 }
@@ -1651,8 +1688,8 @@ c_string_pos (ptrdiff_t charpos, const char *s, int multibyte_p)
 {
   struct text_pos pos;
 
-  xassert (s != NULL);
-  xassert (charpos >= 0);
+  eassert (s != NULL);
+  eassert (charpos >= 0);
 
   if (multibyte_p)
     {
@@ -1708,8 +1745,8 @@ number_of_chars (const char *s, int multibyte_p)
 static void
 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
 {
-  xassert (STRINGP (string));
-  xassert (CHARPOS (*newpos) >= CHARPOS (pos));
+  eassert (STRINGP (string));
+  eassert (CHARPOS (*newpos) >= CHARPOS (pos));
 
   if (STRING_MULTIBYTE (string))
     *newpos = string_pos_nchars_ahead (pos, string,
@@ -2377,22 +2414,19 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
 /* Error handler for safe_eval and safe_call.  */
 
 static Lisp_Object
-safe_eval_handler (Lisp_Object arg)
+safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
 {
-  add_to_log ("Error during redisplay: %S", arg, Qnil);
+  add_to_log ("Error during redisplay: %S signaled %S",
+             Flist (nargs, args), arg);
   return Qnil;
 }
 
-
-/* Evaluate SEXPR and return the result, or nil if something went
+/* Call function FUNC with the rest of NARGS - 1 arguments
+   following.  Return the result, or nil if something went
    wrong.  Prevent redisplay during the evaluation.  */
 
-/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
-   Return the result, or nil if something went wrong.  Prevent
-   redisplay during the evaluation.  */
-
 Lisp_Object
-safe_call (ptrdiff_t nargs, Lisp_Object *args)
+safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
 {
   Lisp_Object val;
 
@@ -2400,8 +2434,17 @@ safe_call (ptrdiff_t nargs, Lisp_Object *args)
     val = Qnil;
   else
     {
+      va_list ap;
+      ptrdiff_t i;
       ptrdiff_t count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
+      Lisp_Object *args = alloca (nargs * word_size);
+
+      args[0] = func;
+      va_start (ap, func);
+      for (i = 1; i < nargs; i++)
+       args[i] = va_arg (ap, Lisp_Object);
+      va_end (ap);
 
       GCPRO1 (args[0]);
       gcpro1.nvars = nargs;
@@ -2424,10 +2467,7 @@ safe_call (ptrdiff_t nargs, Lisp_Object *args)
 Lisp_Object
 safe_call1 (Lisp_Object fn, Lisp_Object arg)
 {
-  Lisp_Object args[2];
-  args[0] = fn;
-  args[1] = arg;
-  return safe_call (2, args);
+  return safe_call (2, fn, arg);
 }
 
 static Lisp_Object Qeval;
@@ -2438,17 +2478,13 @@ safe_eval (Lisp_Object sexpr)
   return safe_call1 (Qeval, sexpr);
 }
 
-/* Call function FN with one argument ARG.
+/* Call function FN with two arguments ARG1 and ARG2.
    Return the result, or nil if something went wrong.  */
 
 Lisp_Object
 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
 {
-  Lisp_Object args[3];
-  args[0] = fn;
-  args[1] = arg1;
-  args[2] = arg2;
-  return safe_call (3, args);
+  return safe_call (3, fn, arg1, arg2);
 }
 
 
@@ -2467,23 +2503,23 @@ check_it (struct it *it)
 {
   if (it->method == GET_FROM_STRING)
     {
-      xassert (STRINGP (it->string));
-      xassert (IT_STRING_CHARPOS (*it) >= 0);
+      eassert (STRINGP (it->string));
+      eassert (IT_STRING_CHARPOS (*it) >= 0);
     }
   else
     {
-      xassert (IT_STRING_CHARPOS (*it) < 0);
+      eassert (IT_STRING_CHARPOS (*it) < 0);
       if (it->method == GET_FROM_BUFFER)
        {
          /* Check that character and byte positions agree.  */
-         xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
+         eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
        }
     }
 
   if (it->dpvec)
-    xassert (it->current.dpvec_index >= 0);
+    eassert (it->current.dpvec_index >= 0);
   else
-    xassert (it->current.dpvec_index < 0);
+    eassert (it->current.dpvec_index < 0);
 }
 
 #define CHECK_IT(IT)   check_it ((IT))
@@ -2495,7 +2531,7 @@ check_it (struct it *it)
 #endif /* not 0 */
 
 
-#if GLYPH_DEBUG && XASSERTS
+#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
 
 /* Check that the window end of window W is what we expect it
    to be---the last row in the current matrix displaying text.  */
@@ -2507,7 +2543,7 @@ check_window_end (struct window *w)
       && !NILP (w->window_end_valid))
     {
       struct glyph_row *row;
-      xassert ((row = MATRIX_ROW (w->current_matrix,
+      eassert ((row = MATRIX_ROW (w->current_matrix,
                                  XFASTINT (w->window_end_vpos)),
                !row->enabled_p
                || MATRIX_ROW_DISPLAYS_TEXT_P (row)
@@ -2521,10 +2557,26 @@ check_window_end (struct window *w)
 
 #define CHECK_WINDOW_END(W)    (void) 0
 
-#endif
+#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
 
+/* Return mark position if current buffer has the region of non-zero length,
+   or -1 otherwise.  */
+
+static ptrdiff_t
+markpos_of_region (void)
+{
+  if (!NILP (Vtransient_mark_mode)
+      && !NILP (BVAR (current_buffer, mark_active))
+      && XMARKER (BVAR (current_buffer, mark))->buffer != NULL)
+    {
+      ptrdiff_t markpos = XMARKER (BVAR (current_buffer, mark))->charpos;
+
+      if (markpos != PT)
+       return markpos;
+    }
+  return -1;
+}
 
-\f
 /***********************************************************************
                       Iterator initialization
  ***********************************************************************/
@@ -2553,12 +2605,12 @@ init_iterator (struct it *it, struct window *w,
               ptrdiff_t charpos, ptrdiff_t bytepos,
               struct glyph_row *row, enum face_id base_face_id)
 {
-  int highlight_region_p;
+  ptrdiff_t markpos;
   enum face_id remapped_base_face_id = base_face_id;
 
   /* Some precondition checks.  */
-  xassert (w != NULL && it != NULL);
-  xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
+  eassert (w != NULL && it != NULL);
+  eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
                           && charpos <= ZV));
 
   /* If face attributes have been changed since the last redisplay,
@@ -2573,7 +2625,8 @@ init_iterator (struct it *it, struct window *w,
 
   /* Perhaps remap BASE_FACE_ID to a user-specified alternative.  */
   if (! NILP (Vface_remapping_alist))
-    remapped_base_face_id = lookup_basic_face (XFRAME (w->frame), base_face_id);
+    remapped_base_face_id
+      = lookup_basic_face (XFRAME (w->frame), base_face_id);
 
   /* Use one of the mode line rows of W's desired matrix if
      appropriate.  */
@@ -2641,9 +2694,9 @@ init_iterator (struct it *it, struct window *w,
      is invisible.  >0 means lines indented more than this value are
      invisible.  */
   it->selective = (INTEGERP (BVAR (current_buffer, selective_display))
-                  ? clip_to_bounds (-1, XINT (BVAR (current_buffer,
-                                                    selective_display)),
-                                    PTRDIFF_MAX)
+                  ? (clip_to_bounds
+                     (-1, XINT (BVAR (current_buffer, selective_display)),
+                      PTRDIFF_MAX))
                   : (!NILP (BVAR (current_buffer, selective_display))
                      ? -1 : 0));
   it->selective_display_ellipsis_p
@@ -2655,16 +2708,11 @@ init_iterator (struct it *it, struct window *w,
   /* Are multibyte characters enabled in current_buffer?  */
   it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
 
-  /* Non-zero if we should highlight the region.  */
-  highlight_region_p
-    = (!NILP (Vtransient_mark_mode)
-       && !NILP (BVAR (current_buffer, mark_active))
-       && XMARKER (BVAR (current_buffer, mark))->buffer != 0);
-
-  /* Set IT->region_beg_charpos and IT->region_end_charpos to the
-     start and end of a visible region in window IT->w.  Set both to
-     -1 to indicate no region.  */
-  if (highlight_region_p
+  /* If visible region is of non-zero length, set IT->region_beg_charpos
+     and IT->region_end_charpos to the start and end of a visible region
+     in window IT->w.  Set both to -1 to indicate no region.  */
+  markpos = markpos_of_region ();
+  if (0 <= markpos
       /* Maybe highlight only in selected window.  */
       && (/* Either show region everywhere.  */
          highlight_nonselected_windows
@@ -2676,7 +2724,6 @@ init_iterator (struct it *it, struct window *w,
              && WINDOWP (minibuf_selected_window)
              && w == XWINDOW (minibuf_selected_window))))
     {
-      ptrdiff_t markpos = marker_position (BVAR (current_buffer, mark));
       it->region_beg_charpos = min (PT, markpos);
       it->region_end_charpos = max (PT, markpos);
     }
@@ -2697,7 +2744,7 @@ init_iterator (struct it *it, struct window *w,
 
   /* Are lines in the display truncated?  */
   if (base_face_id != DEFAULT_FACE_ID
-      || XINT (it->w->hscroll)
+      || it->w->hscroll
       || (! WINDOW_FULL_WIDTH_P (it->w)
          && ((!NILP (Vtruncate_partial_width_windows)
               && !INTEGERP (Vtruncate_partial_width_windows))
@@ -2712,31 +2759,37 @@ init_iterator (struct it *it, struct window *w,
     it->line_wrap = TRUNCATE;
 
   /* Get dimensions of truncation and continuation glyphs.  These are
-     displayed as fringe bitmaps under X, so we don't need them for such
-     frames.  */
-  if (!FRAME_WINDOW_P (it->f))
+     displayed as fringe bitmaps under X, but we need them for such
+     frames when the fringes are turned off.  But leave the dimensions
+     zero for tooltip frames, as these glyphs look ugly there and also
+     sabotage calculations of tooltip dimensions in x-show-tip.  */
+#ifdef HAVE_WINDOW_SYSTEM
+  if (!(FRAME_WINDOW_P (it->f)
+       && FRAMEP (tip_frame)
+       && it->f == XFRAME (tip_frame)))
+#endif
     {
       if (it->line_wrap == TRUNCATE)
        {
          /* We will need the truncation glyph.  */
-         xassert (it->glyph_row == NULL);
+         eassert (it->glyph_row == NULL);
          produce_special_glyphs (it, IT_TRUNCATION);
          it->truncation_pixel_width = it->pixel_width;
        }
       else
        {
          /* We will need the continuation glyph.  */
-         xassert (it->glyph_row == NULL);
+         eassert (it->glyph_row == NULL);
          produce_special_glyphs (it, IT_CONTINUATION);
          it->continuation_pixel_width = it->pixel_width;
        }
-
-      /* Reset these values to zero because the produce_special_glyphs
-        above has changed them.  */
-      it->pixel_width = it->ascent = it->descent = 0;
-      it->phys_ascent = it->phys_descent = 0;
     }
 
+  /* Reset these values to zero because the produce_special_glyphs
+     above has changed them.  */
+  it->pixel_width = it->ascent = it->descent = 0;
+  it->phys_ascent = it->phys_descent = 0;
+
   /* Set this after getting the dimensions of truncation and
      continuation glyphs, so that we don't produce glyphs when calling
      produce_special_glyphs, above.  */
@@ -2759,16 +2812,19 @@ init_iterator (struct it *it, struct window *w,
     }
   else
     {
-      it->first_visible_x
-       = XFASTINT (it->w->hscroll) * FRAME_COLUMN_WIDTH (it->f);
+      it->first_visible_x =
+       window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f);
       it->last_visible_x = (it->first_visible_x
                            + window_box_width (w, TEXT_AREA));
 
-      /* If we truncate lines, leave room for the truncator glyph(s) at
+      /* If we truncate lines, leave room for the truncation glyph(s) at
         the right margin.  Otherwise, leave room for the continuation
-        glyph(s).  Truncation and continuation glyphs are not inserted
-        for window-based redisplay.  */
-      if (!FRAME_WINDOW_P (it->f))
+        glyph(s).  Done only if the window has no fringes.  Since we
+        don't know at this point whether there will be any R2L lines in
+        the window, we reserve space for truncation/continuation glyphs
+        even if only one of the fringes is absent.  */
+      if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
+         || (it->bidi_p && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
        {
          if (it->line_wrap == TRUNCATE)
            it->last_visible_x -= it->truncation_pixel_width;
@@ -2904,7 +2960,10 @@ start_display (struct it *it, struct window *w, struct text_pos pos)
                  /* Or it fits exactly and we're on a window
                     system frame.  */
                  || (new_x == it->last_visible_x
-                     && FRAME_WINDOW_P (it->f))))
+                     && FRAME_WINDOW_P (it->f)
+                     && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+                         ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                         : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
            {
              if ((it->current.dpvec_index >= 0
                   || it->current.overlay_string_index >= 0)
@@ -3056,9 +3115,43 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
       relative_index = (it->current.overlay_string_index
                        % OVERLAY_STRING_CHUNK_SIZE);
       it->string = it->overlay_strings[relative_index];
-      xassert (STRINGP (it->string));
+      eassert (STRINGP (it->string));
       it->current.string_pos = pos->string_pos;
       it->method = GET_FROM_STRING;
+      it->end_charpos = SCHARS (it->string);
+      /* Set up the bidi iterator for this overlay string.  */
+      if (it->bidi_p)
+       {
+         it->bidi_it.string.lstring = it->string;
+         it->bidi_it.string.s = NULL;
+         it->bidi_it.string.schars = SCHARS (it->string);
+         it->bidi_it.string.bufpos = it->overlay_strings_charpos;
+         it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
+         it->bidi_it.string.unibyte = !it->multibyte_p;
+         bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
+                       FRAME_WINDOW_P (it->f), &it->bidi_it);
+
+         /* Synchronize the state of the bidi iterator with
+            pos->string_pos.  For any string position other than
+            zero, this will be done automagically when we resume
+            iteration over the string and get_visually_first_element
+            is called.  But if string_pos is zero, and the string is
+            to be reordered for display, we need to resync manually,
+            since it could be that the iteration state recorded in
+            pos ended at string_pos of 0 moving backwards in string.  */
+         if (CHARPOS (pos->string_pos) == 0)
+           {
+             get_visually_first_element (it);
+             if (IT_STRING_CHARPOS (*it) != 0)
+               do {
+                 /* Paranoia.  */
+                 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
+                 bidi_move_to_visually_next (&it->bidi_it);
+               } while (it->bidi_it.charpos != 0);
+           }
+         eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
+                  && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
+       }
     }
 
   if (CHARPOS (pos->string_pos) >= 0)
@@ -3067,7 +3160,10 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
         string.  This can only be a string from a `display' property.
         IT should already be filled with that string.  */
       it->current.string_pos = pos->string_pos;
-      xassert (STRINGP (it->string));
+      eassert (STRINGP (it->string));
+      if (it->bidi_p)
+       bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
+                     FRAME_WINDOW_P (it->f), &it->bidi_it);
     }
 
   /* Restore position in display vector translations, control
@@ -3076,7 +3172,7 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
     {
       if (it->dpvec == NULL)
        get_next_display_element (it);
-      xassert (it->dpvec && it->current.dpvec_index == 0);
+      eassert (it->dpvec && it->current.dpvec_index == 0);
       it->current.dpvec_index = pos->dpvec_index;
     }
 
@@ -3290,7 +3386,7 @@ compute_stop_pos (struct it *it)
      interval if there isn't such an interval.  */
   position = make_number (charpos);
   iv = validate_interval_range (object, &position, &position, 0);
-  if (!NULL_INTERVAL_P (iv))
+  if (iv)
     {
       Lisp_Object values_here[LAST_PROP_IDX];
       struct props *p;
@@ -3302,7 +3398,7 @@ compute_stop_pos (struct it *it)
       /* Look for an interval following iv that has different
         properties.  */
       for (next_iv = next_interval (iv);
-          (!NULL_INTERVAL_P (next_iv)
+          (next_iv
            && (NILP (limit)
                || XFASTINT (limit) > next_iv->position));
           next_iv = next_interval (next_iv))
@@ -3320,7 +3416,7 @@ compute_stop_pos (struct it *it)
            break;
        }
 
-      if (!NULL_INTERVAL_P (next_iv))
+      if (next_iv)
        {
          if (INTEGERP (limit)
              && next_iv->position >= XFASTINT (limit))
@@ -3342,7 +3438,7 @@ compute_stop_pos (struct it *it)
                                    stoppos, it->string);
     }
 
-  xassert (STRINGP (it->string)
+  eassert (STRINGP (it->string)
           || (it->stop_charpos >= BEGV
               && it->stop_charpos >= IT_CHARPOS (*it)));
 }
@@ -3558,7 +3654,7 @@ handle_fontified_prop (struct it *it)
       val = Vfontification_functions;
       specbind (Qfontification_functions, Qnil);
 
-      xassert (it->end_charpos == ZV);
+      eassert (it->end_charpos == ZV);
 
       if (!CONSP (val) || EQ (XCAR (val), Qlambda))
        safe_call1 (val, pos);
@@ -3613,7 +3709,7 @@ handle_fontified_prop (struct it *it)
        }
       /* There isn't much we can reasonably do to protect against
         misbehaving fontification, but here's a fig leaf.  */
-      else if (!NILP (BVAR (obuf, name)))
+      else if (BUFFER_LIVE_P (obuf))
        set_buffer_internal_1 (obuf);
 
       /* The fontification code may have added/removed text.
@@ -3669,18 +3765,26 @@ handle_face_prop (struct it *it)
       if (new_face_id != it->face_id)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
+         /* If it->face_id is -1, old_face below will be NULL, see
+            the definition of FACE_FROM_ID.  This will happen if this
+            is the initial call that gets the face.  */
+         struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
 
-         /* If new face has a box but old face has not, this is
-            the start of a run of characters with box, i.e. it has
-            a shadow on the left side.  The value of face_id of the
-            iterator will be -1 if this is the initial call that gets
-            the face.  In this case, we have to look in front of IT's
-            position and see whether there is a face != new_face_id.  */
-         it->start_of_box_run_p
-           = (new_face->box != FACE_NO_BOX
-              && (it->face_id >= 0
-                  || IT_CHARPOS (*it) == BEG
-                  || new_face_id != face_before_it_pos (it)));
+         /* If the value of face_id of the iterator is -1, we have to
+            look in front of IT's position and see whether there is a
+            face there that's different from new_face_id.  */
+         if (!old_face && IT_CHARPOS (*it) > BEG)
+           {
+             int prev_face_id = face_before_it_pos (it);
+
+             old_face = FACE_FROM_ID (it->f, prev_face_id);
+           }
+
+         /* If the new face has a box, but the old face does not,
+            this is the start of a run of characters with box face,
+            i.e. this character has a shadow on the left side.  */
+         it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
+                                   && (old_face == NULL || !old_face->box));
          it->face_box_p = new_face->box != FACE_NO_BOX;
        }
     }
@@ -3691,7 +3795,8 @@ handle_face_prop (struct it *it)
       int i;
       Lisp_Object from_overlay
        = (it->current.overlay_string_index >= 0
-          ? it->string_overlays[it->current.overlay_string_index]
+          ? it->string_overlays[it->current.overlay_string_index
+                                % OVERLAY_STRING_CHUNK_SIZE]
           : Qnil);
 
       /* See if we got to this string directly or indirectly from
@@ -3705,7 +3810,8 @@ handle_face_prop (struct it *it)
          {
            if (it->stack[i].current.overlay_string_index >= 0)
              from_overlay
-               = it->string_overlays[it->stack[i].current.overlay_string_index];
+               = it->string_overlays[it->stack[i].current.overlay_string_index
+                                     % OVERLAY_STRING_CHUNK_SIZE];
            else if (! NILP (it->stack[i].from_overlay))
              from_overlay = it->stack[i].from_overlay;
 
@@ -3788,7 +3894,7 @@ underlying_face_id (struct it *it)
 {
   int face_id = it->base_face_id, i;
 
-  xassert (STRINGP (it->string));
+  eassert (STRINGP (it->string));
 
   for (i = it->sp - 1; i >= 0; --i)
     if (NILP (it->stack[i].string))
@@ -3811,7 +3917,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
   struct it it_copy;
   void *it_copy_data = NULL;
 
-  xassert (it->s == NULL);
+  eassert (it->s == NULL);
 
   if (STRINGP (it->string))
     {
@@ -3877,7 +3983,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
              charpos = it_copy.bidi_it.charpos;
            }
        }
-      xassert (0 <= charpos && charpos <= SCHARS (it->string));
+      eassert (0 <= charpos && charpos <= SCHARS (it->string));
 
       if (it->current.overlay_string_index >= 0)
        bufpos = IT_CHARPOS (*it);
@@ -3977,7 +4083,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
                            it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
            }
        }
-      xassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
+      eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
 
       /* Determine face for CHARSET_ASCII, or unibyte.  */
       face_id = face_at_buffer_position (it->w,
@@ -4014,38 +4120,54 @@ static enum prop_handled
 handle_invisible_prop (struct it *it)
 {
   enum prop_handled handled = HANDLED_NORMALLY;
+  int invis_p;
+  Lisp_Object prop;
 
   if (STRINGP (it->string))
     {
-      Lisp_Object prop, end_charpos, limit, charpos;
+      Lisp_Object end_charpos, limit, charpos;
 
       /* Get the value of the invisible text property at the
         current position.  Value will be nil if there is no such
         property.  */
       charpos = make_number (IT_STRING_CHARPOS (*it));
       prop = Fget_text_property (charpos, Qinvisible, it->string);
+      invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
 
-      if (!NILP (prop)
-         && IT_STRING_CHARPOS (*it) < it->end_charpos)
+      if (invis_p && IT_STRING_CHARPOS (*it) < it->end_charpos)
        {
-         ptrdiff_t endpos;
+         /* Record whether we have to display an ellipsis for the
+            invisible text.  */
+         int display_ellipsis_p = (invis_p == 2);
+         ptrdiff_t len, endpos;
 
          handled = HANDLED_RECOMPUTE_PROPS;
 
-         /* Get the position at which the next change of the
-            invisible text property can be found in IT->string.
-            Value will be nil if the property value is the same for
-            all the rest of IT->string.  */
-         XSETINT (limit, SCHARS (it->string));
-         end_charpos = Fnext_single_property_change (charpos, Qinvisible,
-                                                     it->string, limit);
-
-         /* Text at current position is invisible.  The next
-            change in the property is at position end_charpos.
-            Move IT's current position to that position.  */
-         if (INTEGERP (end_charpos)
-             && (endpos = XFASTINT (end_charpos)) < XFASTINT (limit))
+         /* Get the position at which the next visible text can be
+            found in IT->string, if any.  */
+         endpos = len = SCHARS (it->string);
+         XSETINT (limit, len);
+         do
            {
+             end_charpos = Fnext_single_property_change (charpos, Qinvisible,
+                                                         it->string, limit);
+             if (INTEGERP (end_charpos))
+               {
+                 endpos = XFASTINT (end_charpos);
+                 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
+                 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
+                 if (invis_p == 2)
+                   display_ellipsis_p = 1;
+               }
+           }
+         while (invis_p && endpos < len);
+
+         if (display_ellipsis_p)
+           it->ellipsis_p = 1;
+
+         if (endpos < len)
+           {
+             /* Text at END_CHARPOS is visible.  Move IT there.  */
              struct text_pos old;
              ptrdiff_t oldpos;
 
@@ -4081,7 +4203,8 @@ handle_invisible_prop (struct it *it)
              /* The rest of the string is invisible.  If this is an
                 overlay string, proceed with the next overlay string
                 or whatever comes and return a character from there.  */
-             if (it->current.overlay_string_index >= 0)
+             if (it->current.overlay_string_index >= 0
+                 && !display_ellipsis_p)
                {
                  next_overlay_string (it);
                  /* Don't check for overlay strings when we just
@@ -4098,9 +4221,8 @@ handle_invisible_prop (struct it *it)
     }
   else
     {
-      int invis_p;
       ptrdiff_t newpos, next_stop, start_charpos, tem;
-      Lisp_Object pos, prop, overlay;
+      Lisp_Object pos, overlay;
 
       /* First of all, is there invisible text at this position?  */
       tem = start_charpos = IT_CHARPOS (*it);
@@ -5235,7 +5357,7 @@ next_overlay_string (struct it *it)
 
       it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0);
       pop_it (it);
-      xassert (it->sp > 0
+      eassert (it->sp > 0
               || (NILP (it->string)
                   && it->method == GET_FROM_BUFFER
                   && it->stop_charpos >= BEGV
@@ -5276,6 +5398,7 @@ next_overlay_string (struct it *it)
       SET_TEXT_POS (it->current.string_pos, 0, 0);
       it->method = GET_FROM_STRING;
       it->stop_charpos = 0;
+      it->end_charpos = SCHARS (it->string);
       if (it->cmp_it.stop_pos >= 0)
        it->cmp_it.stop_pos = 0;
       it->prev_stop = 0;
@@ -5379,8 +5502,7 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
   ptrdiff_t size = 20;
   ptrdiff_t n = 0, i, j;
   int invis_p;
-  struct overlay_entry *entries
-    = (struct overlay_entry *) alloca (size * sizeof *entries);
+  struct overlay_entry *entries = alloca (size * sizeof *entries);
   USE_SAFE_ALLOCA;
 
   if (charpos <= 0)
@@ -5416,7 +5538,7 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
   for (ov = current_buffer->overlays_before; ov; ov = ov->next)
     {
       XSETMISC (overlay, ov);
-      xassert (OVERLAYP (overlay));
+      eassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
 
@@ -5456,7 +5578,7 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
   for (ov = current_buffer->overlays_after; ov; ov = ov->next)
     {
       XSETMISC (overlay, ov);
-      xassert (OVERLAYP (overlay));
+      eassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
 
@@ -5544,11 +5666,11 @@ get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, int compute_stop_p)
         strings.  */
       if (compute_stop_p)
        compute_stop_pos (it);
-      xassert (it->face_id >= 0);
+      eassert (it->face_id >= 0);
 
       /* Save IT's settings.  They are restored after all overlay
         strings have been processed.  */
-      xassert (!compute_stop_p || it->sp == 0);
+      eassert (!compute_stop_p || it->sp == 0);
 
       /* When called from handle_stop, there might be an empty display
          string loaded.  In that case, don't bother saving it.  But
@@ -5568,7 +5690,7 @@ get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, int compute_stop_p)
       it->string = it->overlay_strings[0];
       it->from_overlay = Qnil;
       it->stop_charpos = 0;
-      xassert (STRINGP (it->string));
+      eassert (STRINGP (it->string));
       it->end_charpos = SCHARS (it->string);
       it->prev_stop = 0;
       it->base_level_stop = 0;
@@ -5634,14 +5756,14 @@ push_it (struct it *it, struct text_pos *position)
 {
   struct iterator_stack_entry *p;
 
-  xassert (it->sp < IT_STACK_SIZE);
+  eassert (it->sp < IT_STACK_SIZE);
   p = it->stack + it->sp;
 
   p->stop_charpos = it->stop_charpos;
   p->prev_stop = it->prev_stop;
   p->base_level_stop = it->base_level_stop;
   p->cmp_it = it->cmp_it;
-  xassert (it->face_id >= 0);
+  eassert (it->face_id >= 0);
   p->face_id = it->face_id;
   p->string = it->string;
   p->method = it->method;
@@ -5688,7 +5810,7 @@ iterate_out_of_display_property (struct it *it)
   ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
   ptrdiff_t bob = (buffer_p ? BEGV : 0);
 
-  xassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
+  eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
 
   /* Maybe initialize paragraph direction.  If we are at the beginning
      of a new paragraph, next_element_from_buffer may not have a
@@ -5727,7 +5849,7 @@ pop_it (struct it *it)
   struct iterator_stack_entry *p;
   int from_display_prop = it->from_disp_prop_p;
 
-  xassert (it->sp > 0);
+  eassert (it->sp > 0);
   --it->sp;
   p = it->stack + it->sp;
   it->stop_charpos = p->stop_charpos;
@@ -5797,7 +5919,7 @@ pop_it (struct it *it)
          && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
        iterate_out_of_display_property (it);
 
-      xassert ((BUFFERP (it->object)
+      eassert ((BUFFERP (it->object)
                && IT_CHARPOS (*it) == it->bidi_it.charpos
                && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
               || (STRINGP (it->object)
@@ -5894,7 +6016,7 @@ forward_to_next_line_start (struct it *it, int *skipped_p,
       ptrdiff_t limit = find_next_newline_no_quit (start, 1);
       Lisp_Object pos;
 
-      xassert (!STRINGP (it->string));
+      eassert (!STRINGP (it->string));
 
       /* If there isn't any `display' property in sight, and no
         overlays, we can just use the position of the newline in
@@ -5978,7 +6100,7 @@ back_to_previous_visible_line_start (struct it *it)
       {
        Lisp_Object prop;
        prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
-                                    Qinvisible, it->window);
+                                  Qinvisible, it->window);
        if (TEXT_PROP_MEANS_INVISIBLE (prop))
          continue;
       }
@@ -6033,8 +6155,8 @@ back_to_previous_visible_line_start (struct it *it)
 
   it->continuation_lines_width = 0;
 
-  xassert (IT_CHARPOS (*it) >= BEGV);
-  xassert (IT_CHARPOS (*it) == BEGV
+  eassert (IT_CHARPOS (*it) >= BEGV);
+  eassert (IT_CHARPOS (*it) == BEGV
           || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
   CHECK_IT (it);
 }
@@ -6076,7 +6198,7 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p)
           && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
                                 it->selective))
       {
-       xassert (IT_BYTEPOS (*it) == BEGV
+       eassert (IT_BYTEPOS (*it) == BEGV
                 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
        newline_found_p =
          forward_to_next_line_start (it, &skipped_p, &bidi_it_prev);
@@ -6190,10 +6312,10 @@ static void
 reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
 {
   /* Don't call this function when scanning a C string.  */
-  xassert (it->s == NULL);
+  eassert (it->s == NULL);
 
   /* POS must be a reasonable value.  */
-  xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
+  eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
 
   it->current.pos = it->position = pos;
   it->end_charpos = ZV;
@@ -6230,6 +6352,8 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
       it->stop_charpos = CHARPOS (pos);
       it->base_level_stop = CHARPOS (pos);
     }
+  /* This make the information stored in it->cmp_it invalidate.  */
+  it->cmp_it.id = -1;
 }
 
 
@@ -6266,7 +6390,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
   memset (&it->current, 0, sizeof it->current);
   it->current.overlay_string_index = -1;
   it->current.dpvec_index = -1;
-  xassert (charpos >= 0);
+  eassert (charpos >= 0);
 
   /* If STRING is specified, use its multibyteness, otherwise use the
      setting of MULTIBYTE, if specified.  */
@@ -6283,7 +6407,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
 
   if (s == NULL)
     {
-      xassert (STRINGP (string));
+      eassert (STRINGP (string));
       it->string = string;
       it->s = NULL;
       it->end_charpos = it->string_nchars = SCHARS (string);
@@ -6526,7 +6650,7 @@ get_next_display_element (struct it *it)
 
          if (! it->multibyte_p && ! ASCII_CHAR_P (c))
            {
-             xassert (SINGLE_BYTE_CHAR_P (c));
+             eassert (SINGLE_BYTE_CHAR_P (c));
              if (unibyte_display_via_language_environment)
                {
                  c = DECODE_CHAR (unibyte, c);
@@ -6979,7 +7103,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
        }
       else
        {
-         xassert (it->len != 0);
+         eassert (it->len != 0);
 
          if (!it->bidi_p)
            {
@@ -7007,7 +7131,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
                                                IT_BYTEPOS (*it), stop, Qnil);
                }
            }
-         xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
+         eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
        }
       break;
 
@@ -7079,7 +7203,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
 
     case GET_FROM_STRING:
       /* Current display element is a character from a Lisp string.  */
-      xassert (it->s == NULL && STRINGP (it->string));
+      eassert (it->s == NULL && STRINGP (it->string));
       /* Don't advance past string end.  These conditions are true
         when set_iterator_to_next is called at the end of
         get_next_display_element, in which case the Lisp string is
@@ -7228,7 +7352,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
       /* The position etc with which we have to proceed are on
         the stack.  The position may be at the end of a string,
          if the `display' property takes up the whole string.  */
-      xassert (it->sp > 0);
+      eassert (it->sp > 0);
       pop_it (it);
       if (it->method == GET_FROM_STRING)
        goto consider_string_end;
@@ -7236,10 +7360,10 @@ set_iterator_to_next (struct it *it, int reseat_p)
 
     default:
       /* There are no other methods defined, so this should be a bug.  */
-      abort ();
+      emacs_abort ();
     }
 
-  xassert (it->method != GET_FROM_STRING
+  eassert (it->method != GET_FROM_STRING
           || (STRINGP (it->string)
               && IT_STRING_CHARPOS (*it) >= 0));
 }
@@ -7259,7 +7383,7 @@ next_element_from_display_vector (struct it *it)
   Lisp_Object gc;
 
   /* Precondition.  */
-  xassert (it->dpvec && it->current.dpvec_index >= 0);
+  eassert (it->dpvec && it->current.dpvec_index >= 0);
 
   it->face_id = it->saved_face_id;
 
@@ -7377,7 +7501,7 @@ get_visually_first_element (struct it *it)
 
       if (STRINGP (it->string))
        {
-         xassert (!it->s);
+         eassert (!it->s);
          stop = SCHARS (it->string);
          if (stop > it->end_charpos)
            stop = it->end_charpos;
@@ -7407,9 +7531,9 @@ next_element_from_string (struct it *it)
 {
   struct text_pos position;
 
-  xassert (STRINGP (it->string));
-  xassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
-  xassert (IT_STRING_CHARPOS (*it) >= 0);
+  eassert (STRINGP (it->string));
+  eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
+  eassert (IT_STRING_CHARPOS (*it) >= 0);
   position = it->current.string_pos;
 
   /* With bidi reordering, the character to display might not be the
@@ -7573,8 +7697,8 @@ next_element_from_c_string (struct it *it)
 {
   int success_p = 1;
 
-  xassert (it->s);
-  xassert (!it->bidi_p || it->s == it->bidi_it.string.s);
+  eassert (it->s);
+  eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
   it->what = IT_CHARACTER;
   BYTEPOS (it->position) = CHARPOS (it->position) = 0;
   it->object = Qnil;
@@ -7679,19 +7803,19 @@ compute_stop_pos_backwards (struct it *it)
   ptrdiff_t save_stop_pos = it->stop_charpos;
   ptrdiff_t save_end_pos = it->end_charpos;
 
-  xassert (NILP (it->string) && !it->s);
-  xassert (it->bidi_p);
+  eassert (NILP (it->string) && !it->s);
+  eassert (it->bidi_p);
   it->bidi_p = 0;
   do
     {
       it->end_charpos = min (charpos + 1, ZV);
       charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
-      SET_TEXT_POS (pos, charpos, BYTE_TO_CHAR (charpos));
+      SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
       reseat_1 (it, pos, 0);
       compute_stop_pos (it);
       /* We must advance forward, right?  */
       if (it->stop_charpos <= charpos)
-       abort ();
+       emacs_abort ();
     }
   while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
 
@@ -7725,7 +7849,7 @@ handle_stop_backwards (struct it *it, ptrdiff_t charpos)
   ptrdiff_t next_stop;
 
   /* Scan in strict logical order.  */
-  xassert (it->bidi_p);
+  eassert (it->bidi_p);
   it->bidi_p = 0;
   do
     {
@@ -7740,7 +7864,7 @@ handle_stop_backwards (struct it *it, ptrdiff_t charpos)
       compute_stop_pos (it);
       /* We must advance forward, right?  */
       if (it->stop_charpos <= it->prev_stop)
-       abort ();
+       emacs_abort ();
       charpos = it->stop_charpos;
     }
   while (charpos <= where_we_are);
@@ -7764,9 +7888,9 @@ next_element_from_buffer (struct it *it)
 {
   int success_p = 1;
 
-  xassert (IT_CHARPOS (*it) >= BEGV);
-  xassert (NILP (it->string) && !it->s);
-  xassert (!it->bidi_p
+  eassert (IT_CHARPOS (*it) >= BEGV);
+  eassert (NILP (it->string) && !it->s);
+  eassert (!it->bidi_p
           || (EQ (it->bidi_it.string.lstring, Qnil)
               && it->bidi_it.string.s == NULL));
 
@@ -7925,7 +8049,7 @@ next_element_from_buffer (struct it *it)
     }
 
   /* Value is zero if end of buffer reached.  */
-  xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
+  eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
   return success_p;
 }
 
@@ -7939,7 +8063,7 @@ run_redisplay_end_trigger_hook (struct it *it)
 
   /* IT->glyph_row should be non-null, i.e. we should be actually
      displaying something, or otherwise we should not run the hook.  */
-  xassert (it->glyph_row);
+  eassert (it->glyph_row);
 
   /* Set up hook arguments.  */
   args[0] = Qredisplay_end_trigger_functions;
@@ -7949,7 +8073,7 @@ run_redisplay_end_trigger_hook (struct it *it)
 
   /* Since we are *trying* to run these functions, don't try to run
      them again, even if they get an error.  */
-  it->w->redisplay_end_trigger = Qnil;
+  wset_redisplay_end_trigger (it->w, Qnil);
   Frun_hook_with_args (3, args);
 
   /* Notice if it changed the face of the character we are on.  */
@@ -8307,7 +8431,10 @@ move_it_in_display_line_to (struct it *it,
                      /* Or it fits exactly and we're on a window
                         system frame.  */
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f))))
+                         && FRAME_WINDOW_P (it->f)
+                         && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
                {
                  if (/* IT->hpos == 0 means the very first glyph
                         doesn't fit on the line, e.g. a wide image.  */
@@ -8354,10 +8481,15 @@ move_it_in_display_line_to (struct it *it,
                          /* On graphical terminals, newlines may
                             "overflow" into the fringe if
                             overflow-newline-into-fringe is non-nil.
-                            On text-only terminals, newlines may
-                            overflow into the last glyph on the
+                            On text terminals, and on graphical
+                            terminals with no right margin, newlines
+                            may overflow into the last glyph on the
                             display line.*/
                          if (!FRAME_WINDOW_P (it->f)
+                             || ((it->bidi_p
+                                  && it->bidi_it.paragraph_dir == R2L)
+                                 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                                 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
                              || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                            {
                              if (!get_next_display_element (it))
@@ -8432,7 +8564,7 @@ move_it_in_display_line_to (struct it *it,
             necessary here because of lines consisting of a line end,
             only.  The line end will not produce any glyphs and we
             would never get MOVE_X_REACHED.  */
-         xassert (it->nglyphs == 0);
+         eassert (it->nglyphs == 0);
          result = MOVE_X_REACHED;
          break;
        }
@@ -8489,6 +8621,9 @@ move_it_in_display_line_to (struct it *it,
          && it->current_x >= it->last_visible_x)
        {
          if (!FRAME_WINDOW_P (it->f)
+             || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+                 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
              || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
            {
              int at_eob_p = 0;
@@ -8817,7 +8952,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
          break;
 
        default:
-         abort ();
+         emacs_abort ();
        }
 
       /* Reset/increment for the next run.  */
@@ -8882,7 +9017,7 @@ move_it_vertically_backward (struct it *it, int dy)
   ptrdiff_t start_pos;
 
  move_further_back:
-  xassert (dy >= 0);
+  eassert (dy >= 0);
 
   start_pos = IT_CHARPOS (*it);
 
@@ -8925,11 +9060,11 @@ move_it_vertically_backward (struct it *it, int dy)
           || (it2.method == GET_FROM_STRING
               && IT_CHARPOS (it2) == start_pos
               && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
-  xassert (IT_CHARPOS (*it) >= BEGV);
+  eassert (IT_CHARPOS (*it) >= BEGV);
   SAVE_IT (it3, it2, it3data);
 
   move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
-  xassert (IT_CHARPOS (*it) >= BEGV);
+  eassert (IT_CHARPOS (*it) >= BEGV);
   /* H is the actual vertical distance from the position in *IT
      and the starting position.  */
   h = it2.current_y - it->current_y;
@@ -9210,12 +9345,6 @@ add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   USE_SAFE_ALLOCA;
 
-  /* Do nothing if called asynchronously.  Inserting text into
-     a buffer may call after-change-functions and alike and
-     that would means running Lisp asynchronously.  */
-  if (handling_signal)
-    return;
-
   fmt = msg = Qnil;
   GCPRO4 (fmt, msg, arg1, arg2);
 
@@ -9225,7 +9354,7 @@ add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
   msg = Fformat (3, args);
 
   len = SBYTES (msg) + 1;
-  SAFE_ALLOCA (buffer, char *, len);
+  buffer = SAFE_ALLOCA (len);
   memcpy (buffer, SDATA (msg), len);
 
   message_dolog (buffer, len - 1, 1, 0);
@@ -9269,13 +9398,14 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
       int old_windows_or_buffers_changed = windows_or_buffers_changed;
       ptrdiff_t point_at_end = 0;
       ptrdiff_t zv_at_end = 0;
-      Lisp_Object old_deactivate_mark, tem;
+      Lisp_Object old_deactivate_mark;
+      bool shown;
       struct gcpro gcpro1;
 
       old_deactivate_mark = Vdeactivate_mark;
       oldbuf = current_buffer;
       Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
-      BVAR (current_buffer, undo_list) = Qt;
+      bset_undo_list (current_buffer, Qt);
 
       oldpoint = message_dolog_marker1;
       set_marker_restricted (oldpoint, make_number (PT), Qnil);
@@ -9363,12 +9493,10 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
                    {
                      char dupstr[sizeof " [ times]"
                                  + INT_STRLEN_BOUND (printmax_t)];
-                     int duplen;
 
                      /* If you change this format, don't forget to also
                         change message_log_check_duplicate.  */
-                     sprintf (dupstr, " [%"pMd" times]", dups);
-                     duplen = strlen (dupstr);
+                     int duplen = sprintf (dupstr, " [%"pMd" times]", dups);
                      TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
                      insert_1 (dupstr, duplen, 1, 0, 1);
                    }
@@ -9386,7 +9514,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
              del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
            }
        }
-      BEGV = XMARKER (oldbegv)->charpos;
+      BEGV = marker_position (oldbegv);
       BEGV_BYTE = marker_byte_position (oldbegv);
 
       if (zv_at_end)
@@ -9396,7 +9524,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
        }
       else
        {
-         ZV = XMARKER (oldzv)->charpos;
+         ZV = marker_position (oldzv);
          ZV_BYTE = marker_byte_position (oldzv);
        }
 
@@ -9405,17 +9533,17 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
       else
        /* We can't do Fgoto_char (oldpoint) because it will run some
            Lisp code.  */
-       TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
-                         XMARKER (oldpoint)->bytepos);
+       TEMP_SET_PT_BOTH (marker_position (oldpoint),
+                         marker_byte_position (oldpoint));
 
       UNGCPRO;
       unchain_marker (XMARKER (oldpoint));
       unchain_marker (XMARKER (oldbegv));
       unchain_marker (XMARKER (oldzv));
 
-      tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
+      shown = buffer_window_count (current_buffer) > 0;
       set_buffer_internal (oldbuf);
-      if (NILP (tem))
+      if (!shown)
        windows_or_buffers_changed = old_windows_or_buffers_changed;
       message_log_need_newline = !nlflag;
       Vdeactivate_mark = old_deactivate_mark;
@@ -9528,7 +9656,7 @@ message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte)
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+      if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
        (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
 }
@@ -9554,10 +9682,8 @@ message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
   message_log_maybe_newline ();
   if (STRINGP (m))
     {
-      char *buffer;
       USE_SAFE_ALLOCA;
-
-      SAFE_ALLOCA (buffer, char *, nbytes);
+      char *buffer = SAFE_ALLOCA (nbytes);
       memcpy (buffer, SDATA (m), nbytes);
       message_dolog (buffer, nbytes, 1, multibyte);
       SAFE_FREE ();
@@ -9627,7 +9753,7 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+      if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
        (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
 }
@@ -9832,16 +9958,16 @@ ensure_echo_area_buffers (void)
 
   for (i = 0; i < 2; ++i)
     if (!BUFFERP (echo_buffer[i])
-       || NILP (BVAR (XBUFFER (echo_buffer[i]), name)))
+       || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
       {
        char name[30];
        Lisp_Object old_buffer;
        int j;
 
        old_buffer = echo_buffer[i];
-       sprintf (name, " *Echo Area %d*", i);
-       echo_buffer[i] = Fget_buffer_create (build_string (name));
-       BVAR (XBUFFER (echo_buffer[i]), truncate_lines) = Qnil;
+       echo_buffer[i] = Fget_buffer_create
+         (make_formatted_string (name, " *Echo Area %d*", i));
+       bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
        /* to force word wrap in echo area -
           it was decided to postpone this*/
        /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
@@ -9930,25 +10056,25 @@ with_echo_area_buffer (struct window *w, int which,
   set_buffer_internal_1 (XBUFFER (buffer));
   if (w)
     {
-      w->buffer = buffer;
+      wset_buffer (w, buffer);
       set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
     }
 
-  BVAR (current_buffer, undo_list) = Qt;
-  BVAR (current_buffer, read_only) = Qnil;
+  bset_undo_list (current_buffer, Qt);
+  bset_read_only (current_buffer, Qnil);
   specbind (Qinhibit_read_only, Qt);
   specbind (Qinhibit_modification_hooks, Qt);
 
   if (clear_buffer_p && Z > BEG)
     del_range (BEG, Z);
 
-  xassert (BEGV >= BEG);
-  xassert (ZV <= Z && ZV >= BEGV);
+  eassert (BEGV >= BEG);
+  eassert (ZV <= Z && ZV >= BEGV);
 
   rc = fn (a1, a2, a3, a4);
 
-  xassert (BEGV >= BEG);
-  xassert (ZV <= Z && ZV >= BEGV);
+  eassert (BEGV >= BEG);
+  eassert (ZV <= Z && ZV >= BEGV);
 
   unbind_to (count, Qnil);
   return rc;
@@ -9980,8 +10106,8 @@ with_echo_area_buffer_unwind_data (struct window *w)
     {
       XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
       ASET (vector, i, w->buffer); ++i;
-      ASET (vector, i, make_number (XMARKER (w->pointm)->charpos)); ++i;
-      ASET (vector, i, make_number (XMARKER (w->pointm)->bytepos)); ++i;
+      ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
+      ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
     }
   else
     {
@@ -9990,7 +10116,7 @@ with_echo_area_buffer_unwind_data (struct window *w)
        ASET (vector, i, Qnil);
     }
 
-  xassert (i == ASIZE (vector));
+  eassert (i == ASIZE (vector));
   return vector;
 }
 
@@ -10015,7 +10141,7 @@ unwind_with_echo_area_buffer (Lisp_Object vector)
       charpos = AREF (vector, 5);
       bytepos = AREF (vector, 6);
 
-      w->buffer = buffer;
+      wset_buffer (w, buffer);
       set_marker_both (w->pointm, buffer,
                       XFASTINT (charpos), XFASTINT (bytepos));
     }
@@ -10048,7 +10174,7 @@ setup_echo_area_for_printing (int multibyte_p)
 
       /* Switch to that buffer and clear it.  */
       set_buffer_internal (XBUFFER (echo_area_buffer[0]));
-      BVAR (current_buffer, truncate_lines) = Qnil;
+      bset_truncate_lines (current_buffer, Qnil);
 
       if (Z > BEG)
        {
@@ -10091,7 +10217,7 @@ setup_echo_area_for_printing (int multibyte_p)
        {
          /* Someone switched buffers between print requests.  */
          set_buffer_internal (XBUFFER (echo_area_buffer[0]));
-         BVAR (current_buffer, truncate_lines) = Qnil;
+         bset_truncate_lines (current_buffer, Qnil);
        }
     }
 }
@@ -10229,7 +10355,7 @@ resize_mini_window (struct window *w, int exact_p)
   struct frame *f = XFRAME (w->frame);
   int window_height_changed_p = 0;
 
-  xassert (MINI_WINDOW_P (w));
+  eassert (MINI_WINDOW_P (w));
 
   /* By default, start display at the beginning.  */
   set_marker_both (w->start, w->buffer,
@@ -10278,8 +10404,7 @@ resize_mini_window (struct window *w, int exact_p)
        max_height = total_height / 4;
 
       /* Correct that max. height if it's bogus.  */
-      max_height = max (1, max_height);
-      max_height = min (total_height, max_height);
+      max_height = clip_to_bounds (1, max_height, total_height);
 
       /* Find out the height of the text in the window.  */
       if (it.line_wrap == TRUNCATE)
@@ -10403,11 +10528,10 @@ current_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4)
    empty.  This is a relatively infrequent operation, so it's not
    worth optimizing.  */
 
-int
+bool
 push_message (void)
 {
-  Lisp_Object msg;
-  msg = current_message ();
+  Lisp_Object msg = current_message ();
   Vmessage_stack = Fcons (msg, Vmessage_stack);
   return STRINGP (msg);
 }
@@ -10420,7 +10544,7 @@ restore_message (void)
 {
   Lisp_Object msg;
 
-  xassert (CONSP (Vmessage_stack));
+  eassert (CONSP (Vmessage_stack));
   msg = XCAR (Vmessage_stack);
   if (STRINGP (msg))
     message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
@@ -10443,7 +10567,7 @@ pop_message_unwind (Lisp_Object dummy)
 static void
 pop_message (void)
 {
-  xassert (CONSP (Vmessage_stack));
+  eassert (CONSP (Vmessage_stack));
   Vmessage_stack = XCDR (Vmessage_stack);
 }
 
@@ -10456,7 +10580,7 @@ void
 check_message_stack (void)
 {
   if (!NILP (Vmessage_stack))
-    abort ();
+    emacs_abort ();
 }
 
 
@@ -10495,7 +10619,6 @@ truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4
   return 0;
 }
 
-
 /* Set the current message to a substring of S or STRING.
 
    If STRING is a Lisp string, set the message to the first NBYTES
@@ -10522,6 +10645,10 @@ set_message (const char *s, Lisp_Object string,
                         (intptr_t) s, string, nbytes, multibyte_p);
   message_buf_print = 0;
   help_echo_showing_p = 0;
+
+  if (STRINGP (Vdebug_on_message)
+      && fast_string_match (Vdebug_on_message, string) >= 0)
+    call_debugger (list2 (Qerror, string));
 }
 
 
@@ -10543,9 +10670,9 @@ set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multiby
       != !NILP (BVAR (current_buffer, enable_multibyte_characters)))
     Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
 
-  BVAR (current_buffer, truncate_lines) = message_truncate_lines ? Qt : Qnil;
+  bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
   if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
-    BVAR (current_buffer, bidi_paragraph_direction) = Qleft_to_right;
+    bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
 
   /* Insert new message at BEG.  */
   TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
@@ -10654,7 +10781,7 @@ clear_garbaged_frames (void)
            {
              if (f->resized_p)
                {
-                 Fredraw_frame (frame);
+                 redraw_frame (f);
                  f->force_flush_display_p = 1;
                }
              clear_current_matrices (f);
@@ -10701,8 +10828,7 @@ echo_area_display (int update_frame_p)
 #endif /* HAVE_WINDOW_SYSTEM */
 
   /* Redraw garbaged frames.  */
-  if (frame_garbaged)
-    clear_garbaged_frames ();
+  clear_garbaged_frames ();
 
   if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
     {
@@ -10775,8 +10901,52 @@ echo_area_display (int update_frame_p)
   return window_height_changed_p;
 }
 
+/* Nonzero if the current window's buffer is shown in more than one
+   window and was modified since last redisplay.  */
+
+static int
+buffer_shared_and_changed (void)
+{
+  return (buffer_window_count (current_buffer) > 1
+         && 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->buffer) != 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.  */
+
+static int
+window_buffer_changed (struct window *w)
+{
+  struct buffer *b = XBUFFER (w->buffer);
+
+  eassert (BUFFER_LIVE_P (b));
+
+  return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star)
+         || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active)))
+             != !NILP (w->region_showing)));
+}
+
+/* Nonzero if W has %c in its mode line and mode line should be updated.  */
+
+static int
+mode_line_update_needed (struct window *w)
+{
+  return (!NILP (w->column_number_displayed)
+         && !(PT == w->last_point && !window_outdated (w))
+         && (XFASTINT (w->column_number_displayed) != current_column ()));
+}
 
-\f
 /***********************************************************************
                     Mode Lines and Frame Titles
  ***********************************************************************/
@@ -10819,7 +10989,8 @@ static Lisp_Object mode_line_string_face_prop;
 static Lisp_Object Vmode_line_unwind_vector;
 
 static Lisp_Object
-format_mode_line_unwind_data (struct buffer *obuf,
+format_mode_line_unwind_data (struct frame *target_frame,
+                             struct buffer *obuf,
                              Lisp_Object owin,
                              int save_proptrans)
 {
@@ -10831,7 +11002,7 @@ format_mode_line_unwind_data (struct buffer *obuf,
   Vmode_line_unwind_vector = Qnil;
 
   if (NILP (vector))
-    vector = Fmake_vector (make_number (8), Qnil);
+    vector = Fmake_vector (make_number (10), Qnil);
 
   ASET (vector, 0, make_number (mode_line_target));
   ASET (vector, 1, make_number (MODE_LINE_NOPROP_LEN (0)));
@@ -10846,6 +11017,15 @@ format_mode_line_unwind_data (struct buffer *obuf,
     tmp = Qnil;
   ASET (vector, 6, tmp);
   ASET (vector, 7, owin);
+  if (target_frame)
+    {
+      /* Similarly to `with-selected-window', if the operation selects
+        a window on another frame, we must restore that frame's
+        selected window, and (for a tty) the top-frame.  */
+      ASET (vector, 8, target_frame->selected_window);
+      if (FRAME_TERMCAP_P (target_frame))
+       ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
+    }
 
   return vector;
 }
@@ -10853,6 +11033,10 @@ format_mode_line_unwind_data (struct buffer *obuf,
 static Lisp_Object
 unwind_format_mode_line (Lisp_Object vector)
 {
+  Lisp_Object old_window = AREF (vector, 7);
+  Lisp_Object target_frame_window = AREF (vector, 8);
+  Lisp_Object old_top_frame = AREF (vector, 9);
+
   mode_line_target = XINT (AREF (vector, 0));
   mode_line_noprop_ptr = mode_line_noprop_buf + XINT (AREF (vector, 1));
   mode_line_string_list = AREF (vector, 2);
@@ -10861,9 +11045,26 @@ unwind_format_mode_line (Lisp_Object vector)
   mode_line_string_face = AREF (vector, 4);
   mode_line_string_face_prop = AREF (vector, 5);
 
-  if (!NILP (AREF (vector, 7)))
-    /* Select window before buffer, since it may change the buffer.  */
-    Fselect_window (AREF (vector, 7), Qt);
+  /* Select window before buffer, since it may change the buffer.  */
+  if (!NILP (old_window))
+    {
+      /* If the operation that we are unwinding had selected a window
+        on a different frame, reset its frame-selected-window.  For a
+        text terminal, reset its top-frame if necessary.  */
+      if (!NILP (target_frame_window))
+       {
+         Lisp_Object frame
+           = WINDOW_FRAME (XWINDOW (target_frame_window));
+
+         if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
+           Fselect_window (target_frame_window, Qt);
+
+         if (!NILP (old_top_frame) && !EQ (old_top_frame, frame))
+           Fselect_frame (old_top_frame, Qt);
+       }
+
+      Fselect_window (old_window, Qt);
+    }
 
   if (!NILP (AREF (vector, 6)))
     {
@@ -10950,17 +11151,15 @@ x_consider_frame_title (Lisp_Object frame)
       || f->explicit_name)
     {
       /* Do we have more than one visible frame on this X display?  */
-      Lisp_Object tail;
-      Lisp_Object fmt;
+      Lisp_Object tail, other_frame, fmt;
       ptrdiff_t title_start;
       char *title;
       ptrdiff_t len;
       struct it it;
       ptrdiff_t count = SPECPDL_INDEX ();
 
-      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+      FOR_EACH_FRAME (tail, other_frame)
        {
-         Lisp_Object other_frame = XCAR (tail);
          struct frame *tf = XFRAME (other_frame);
 
          if (tf != f
@@ -10979,10 +11178,11 @@ x_consider_frame_title (Lisp_Object frame)
         mode_line_noprop_buf; then display the title.  */
       record_unwind_protect (unwind_format_mode_line,
                             format_mode_line_unwind_data
-                               (current_buffer, selected_window, 0));
+                              (f, current_buffer, selected_window, 0));
 
       Fselect_window (f->selected_window, Qt);
-      set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
+      set_buffer_internal_1
+       (XBUFFER (XWINDOW (f->selected_window)->buffer));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
 
       mode_line_target = MODE_LINE_TITLE;
@@ -11008,8 +11208,6 @@ x_consider_frame_title (Lisp_Object frame)
 
 #endif /* not HAVE_WINDOW_SYSTEM */
 
-
-
 \f
 /***********************************************************************
                              Menu Bars
@@ -11054,7 +11252,7 @@ prepare_menu_bars (void)
   /* Update the menu bar item lists, if appropriate.  This has to be
      done before any actual redisplay or generation of display lines.  */
   all_windows = (update_mode_lines
-                || buffer_shared > 1
+                || buffer_shared_and_changed ()
                 || windows_or_buffers_changed);
   if (all_windows)
     {
@@ -11102,8 +11300,8 @@ prepare_menu_bars (void)
 #ifdef HAVE_NS
           if (windows_or_buffers_changed
              && FRAME_NS_P (f))
-            ns_set_doc_edited (f, Fbuffer_modified_p
-                              (XWINDOW (f->selected_window)->buffer));
+            ns_set_doc_edited
+             (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->buffer));
 #endif
          UNGCPRO;
        }
@@ -11168,12 +11366,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
          /* This used to test w->update_mode_line, but we believe
             there is no need to recompute the menu in that case.  */
          || update_mode_lines
-         || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
-              < BUF_MODIFF (XBUFFER (w->buffer)))
-             != w->last_had_star)
-         || ((!NILP (Vtransient_mark_mode)
-              && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
-             != !NILP (w->region_showing)))
+         || window_buffer_changed (w))
        {
          struct buffer *prev = current_buffer;
          ptrdiff_t count = SPECPDL_INDEX ();
@@ -11205,7 +11398,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
            }
 
          XSETFRAME (Vmenu_updating_frame, f);
-         FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+         fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
 
          /* Redisplay the menu bar in case we changed it.  */
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
@@ -11299,11 +11492,11 @@ x_cursor_to (int vpos, int hpos, int y, int x)
      This will also set the cursor position of W.  */
   if (updated_window == NULL)
     {
-      BLOCK_INPUT;
+      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;
+      unblock_input ();
     }
 }
 
@@ -11325,11 +11518,18 @@ FRAME_PTR last_mouse_frame;
 
 int last_tool_bar_item;
 
-
+/* Select `frame' temporarily without running all the code in
+   do_switch_frame.
+   FIXME: Maybe do_switch_frame should be trimmed down similarly
+   when `norecord' is set.  */
 static Lisp_Object
-update_tool_bar_unwind (Lisp_Object frame)
+fast_set_selected_frame (Lisp_Object frame)
 {
-  selected_frame = frame;
+  if (!EQ (selected_frame, frame))
+    {
+      selected_frame = frame;
+      selected_window = XFRAME (frame)->selected_window;
+    }
   return Qnil;
 }
 
@@ -11366,12 +11566,7 @@ update_tool_bar (struct frame *f, int save_match_data)
       if (windows_or_buffers_changed
          || w->update_mode_line
          || update_mode_lines
-         || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
-              < BUF_MODIFF (XBUFFER (w->buffer)))
-             != w->last_had_star)
-         || ((!NILP (Vtransient_mark_mode)
-              && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
-             != !NILP (w->region_showing)))
+         || window_buffer_changed (w))
        {
          struct buffer *prev = current_buffer;
          ptrdiff_t count = SPECPDL_INDEX ();
@@ -11401,13 +11596,18 @@ update_tool_bar (struct frame *f, int save_match_data)
             before calling tool_bar_items, because the calculation of
             the tool-bar keymap uses the selected frame (see
             `tool-bar-make-keymap' in tool-bar.el).  */
-         record_unwind_protect (update_tool_bar_unwind, selected_frame);
+         eassert (EQ (selected_window,
+                      /* Since we only explicitly preserve selected_frame,
+                         check that selected_window would be redundant.  */
+                      XFRAME (selected_frame)->selected_window));
+         record_unwind_protect (fast_set_selected_frame, selected_frame);
          XSETFRAME (frame, f);
-         selected_frame = frame;
+         fast_set_selected_frame (frame);
 
          /* Build desired tool-bar items from keymaps.  */
-          new_tool_bar = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
-                                         &new_n_tool_bar);
+          new_tool_bar
+           = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
+                             &new_n_tool_bar);
 
          /* Redisplay the tool-bar if we changed it.  */
          if (new_n_tool_bar != f->n_tool_bar_items
@@ -11416,11 +11616,11 @@ update_tool_bar (struct frame *f, int save_match_data)
               /* Redisplay that happens asynchronously due to an expose event
                  may access f->tool_bar_items.  Make sure we update both
                  variables within BLOCK_INPUT so no such event interrupts.  */
-              BLOCK_INPUT;
-              f->tool_bar_items = new_tool_bar;
+              block_input ();
+              fset_tool_bar_items (f, new_tool_bar);
               f->n_tool_bar_items = new_n_tool_bar;
               w->update_mode_line = 1;
-              UNBLOCK_INPUT;
+              unblock_input ();
             }
 
          UNGCPRO;
@@ -11459,8 +11659,8 @@ build_desired_tool_bar_string (struct frame *f)
 
   /* Reuse f->desired_tool_bar_string, if possible.  */
   if (size < size_needed || NILP (f->desired_tool_bar_string))
-    f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
-                                              make_number (' '));
+    fset_desired_tool_bar_string
+      (f, Fmake_string (make_number (size_needed), make_number (' ')));
   else
     {
       props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
@@ -11473,7 +11673,8 @@ build_desired_tool_bar_string (struct frame *f)
      is the index of the item in F's tool-bar item vector.  */
   for (i = 0; i < f->n_tool_bar_items; ++i)
     {
-#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
+#define PROP(IDX) \
+  AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
 
       int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
       int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
@@ -11493,7 +11694,7 @@ build_desired_tool_bar_string (struct frame *f)
                   ? TOOL_BAR_IMAGE_DISABLED_SELECTED
                   : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
 
-         xassert (ASIZE (image) >= idx);
+         eassert (ASIZE (image) >= idx);
          image = AREF (image, idx);
        }
       else
@@ -11769,19 +11970,14 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
 
 DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
        0, 1, 0,
-       doc: /* Return the number of lines occupied by the tool bar of FRAME.  */)
+       doc: /* Return the number of lines occupied by the tool bar of FRAME.
+If FRAME is nil or omitted, use the selected frame.  */)
   (Lisp_Object frame)
 {
-  struct frame *f;
+  struct frame *f = decode_any_frame (frame);
   struct window *w;
   int nlines = 0;
 
-  if (NILP (frame))
-    frame = selected_frame;
-  else
-    CHECK_FRAME (frame);
-  f = XFRAME (frame);
-
   if (WINDOWP (f->tool_bar_window)
       && (w = XWINDOW (f->tool_bar_window),
          WINDOW_TOTAL_LINES (w) > 0))
@@ -12081,7 +12277,6 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
     {
       /* Show item in pressed state.  */
       show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
-      hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
       last_tool_bar_item = prop_idx;
     }
   else
@@ -12092,7 +12287,6 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
 
       /* Show item in released state.  */
       show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
-      hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
 
       key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
 
@@ -12161,7 +12355,6 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
       && last_tool_bar_item != prop_idx)
     return;
 
-  hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
 
   /* If tool-bar item is not enabled, don't highlight it.  */
@@ -12190,7 +12383,6 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
 
       /* Display it as active.  */
       show_mouse_face (hlinfo, draw);
-      hlinfo->mouse_face_image_state = draw;
     }
 
  set_help_echo:
@@ -12280,7 +12472,7 @@ hscroll_window_tree (Lisp_Object window)
                 inside the left margin and the window is already
                 hscrolled. */
              && ((!row_r2l_p
-                  && ((XFASTINT (w->hscroll)
+                  && ((w->hscroll
                        && w->cursor.x <= h_margin)
                       || (cursor_row->enabled_p
                           && cursor_row->truncated_on_right_p
@@ -12298,7 +12490,7 @@ hscroll_window_tree (Lisp_Object window)
                              are actually truncated on the left. */
                           && cursor_row->truncated_on_right_p
                           && w->cursor.x <= h_margin)
-                         || (XFASTINT (w->hscroll)
+                         || (w->hscroll
                              && (w->cursor.x >= text_area_width - h_margin))))))
            {
              struct it it;
@@ -12314,11 +12506,7 @@ hscroll_window_tree (Lisp_Object window)
              if (w == XWINDOW (selected_window))
                pt = PT;
              else
-               {
-                 pt = marker_position (w->pointm);
-                 pt = max (BEGV, pt);
-                 pt = min (ZV, pt);
-               }
+               pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
 
              /* Move iterator to pt starting at cursor_row->start in
                 a line with infinite width.  */
@@ -12359,15 +12547,15 @@ hscroll_window_tree (Lisp_Object window)
                  hscroll
                    = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
                }
-             hscroll = max (hscroll, XFASTINT (w->min_hscroll));
+             hscroll = max (hscroll, w->min_hscroll);
 
              /* Don't prevent redisplay optimizations if hscroll
                 hasn't changed, as it will unnecessarily slow down
                 redisplay.  */
-             if (XFASTINT (w->hscroll) != hscroll)
+             if (w->hscroll != hscroll)
                {
                  XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
-                 w->hscroll = make_number (hscroll);
+                 w->hscroll = hscroll;
                  hscrolled_p = 1;
                }
            }
@@ -12406,7 +12594,7 @@ hscroll_windows (Lisp_Object window)
    to a non-zero value.  This is sometimes handy to have in a debugger
    session.  */
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
 
 /* First and last unchanged row for try_window_id.  */
 
@@ -12436,23 +12624,21 @@ static void debug_method_add (struct window *, char const *, ...)
 static void
 debug_method_add (struct window *w, char const *fmt, ...)
 {
-  char buffer[512];
   char *method = w->desired_matrix->method;
   int len = strlen (method);
   int size = sizeof w->desired_matrix->method;
   int remaining = size - len - 1;
   va_list ap;
 
-  va_start (ap, fmt);
-  vsprintf (buffer, fmt, ap);
-  va_end (ap);
   if (len && remaining)
     {
       method[len] = '|';
       --remaining, ++len;
     }
 
-  strncpy (method + len, buffer, remaining);
+  va_start (ap, fmt);
+  vsnprintf (method + len, remaining + 1, fmt, ap);
+  va_end (ap);
 
   if (trace_redisplay_p)
     fprintf (stderr, "%p (%s): %s\n",
@@ -12461,7 +12647,7 @@ debug_method_add (struct window *w, char const *fmt, ...)
               && STRINGP (BVAR (XBUFFER (w->buffer), name)))
              ? SSDATA (BVAR (XBUFFER (w->buffer), name))
              : "no buffer"),
-            buffer);
+            method + len);
 }
 
 #endif /* GLYPH_DEBUG */
@@ -12472,15 +12658,14 @@ debug_method_add (struct window *w, char const *fmt, ...)
    buffer position, END is given as a distance from Z.  Used in
    redisplay_internal for display optimization.  */
 
-static inline int
+static int
 text_outside_line_unchanged_p (struct window *w,
                               ptrdiff_t start, ptrdiff_t end)
 {
   int unchanged_p = 1;
 
   /* If text or overlays have changed, see where.  */
-  if (XFASTINT (w->last_modified) < MODIFF
-      || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
+  if (window_outdated (w))
     {
       /* Gap in the line?  */
       if (GPT < start || Z - GPT < end)
@@ -12683,7 +12868,7 @@ overlay_arrow_at_row (struct it *it, struct glyph_row *row)
                    return make_number (fringe_bitmap);
                }
 #endif
-             return make_number (-1); /* Use default arrow bitmap */
+             return make_number (-1); /* Use default arrow bitmap */
            }
          return overlay_arrow_string_or_property (var);
        }
@@ -12733,7 +12918,7 @@ check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
 /* Reconsider the setting of B->clip_changed which is displayed
    in window W.  */
 
-static inline void
+static void
 reconsider_clip_changes (struct window *w, struct buffer *b)
 {
   if (b->clip_changed
@@ -12759,45 +12944,15 @@ reconsider_clip_changes (struct window *w, struct buffer *b)
        pt = marker_position (w->pointm);
 
       if ((w->current_matrix->buffer != XBUFFER (w->buffer)
-          || pt != XINT (w->last_point))
+          || pt != w->last_point)
          && check_point_in_composition (w->current_matrix->buffer,
-                                        XINT (w->last_point),
+                                        w->last_point,
                                         XBUFFER (w->buffer), pt))
        b->clip_changed = 1;
     }
 }
 \f
 
-/* Select FRAME to forward the values of frame-local variables into C
-   variables so that the redisplay routines can access those values
-   directly.  */
-
-static void
-select_frame_for_redisplay (Lisp_Object frame)
-{
-  Lisp_Object tail, tem;
-  Lisp_Object old = selected_frame;
-  struct Lisp_Symbol *sym;
-
-  xassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
-
-  selected_frame = frame;
-
-  do {
-    for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
-      if (CONSP (XCAR (tail))
-         && (tem = XCAR (XCAR (tail)),
-             SYMBOLP (tem))
-         && (sym = indirect_variable (XSYMBOL (tem)),
-             sym->redirect == SYMBOL_LOCALIZED)
-         && sym->val.blv->frame_local)
-       /* Use find_symbol_value rather than Fsymbol_value
-          to avoid an error if it is void.  */
-       find_symbol_value (tem);
-  } while (!EQ (frame, old) && (frame = old, 1));
-}
-
-
 #define STOP_POLLING                                   \
 do { if (! polling_stopped_here) stop_polling ();      \
        polling_stopped_here = 1; } while (0)
@@ -12823,13 +12978,14 @@ redisplay_internal (void)
   ptrdiff_t count, count1;
   struct frame *sf;
   int polling_stopped_here = 0;
-  Lisp_Object old_frame = selected_frame;
+  Lisp_Object tail, frame;
+  struct backtrace backtrace;
 
   /* Non-zero means redisplay has to consider all windows on all
      frames.  Zero means, only selected_window is considered.  */
   int consider_all_windows_p;
 
-  /* Non-zero means redisplay has to redisplay the miniwindow */
+  /* Non-zero means redisplay has to redisplay the miniwindow */
   int update_miniwindow_p = 0;
 
   TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
@@ -12859,36 +13015,28 @@ redisplay_internal (void)
   if (redisplaying_p)
     return;
 
-  /* Record a function that resets redisplaying_p to its old value
+  /* Record a function that clears redisplaying_p
      when we leave this function.  */
   count = SPECPDL_INDEX ();
-  record_unwind_protect (unwind_redisplay,
-                        Fcons (make_number (redisplaying_p), selected_frame));
-  ++redisplaying_p;
+  record_unwind_protect (unwind_redisplay, selected_frame);
+  redisplaying_p = 1;
   specbind (Qinhibit_free_realized_faces, Qnil);
 
-  {
-    Lisp_Object tail, frame;
+  /* Record this function, so it appears on the profiler's backtraces.  */
+  backtrace.next = backtrace_list;
+  backtrace.function = Qredisplay_internal;
+  backtrace.args = &Qnil;
+  backtrace.nargs = 0;
+  backtrace.debug_on_exit = 0;
+  backtrace_list = &backtrace;
 
-    FOR_EACH_FRAME (tail, frame)
-      {
-       struct frame *f = XFRAME (frame);
-       f->already_hscrolled_p = 0;
-      }
-  }
+  FOR_EACH_FRAME (tail, frame)
+    XFRAME (frame)->already_hscrolled_p = 0;
 
  retry:
   /* Remember the currently selected window.  */
   sw = w;
 
-  if (!EQ (old_frame, selected_frame)
-      && FRAME_LIVE_P (XFRAME (old_frame)))
-    /* When running redisplay, we play a bit fast-and-loose and allow e.g.
-       selected_frame and selected_window to be temporarily out-of-sync so
-       when we come back here via `goto retry', we need to resync because we
-       may need to run Elisp code (via prepare_menu_bars).  */
-    select_frame_for_redisplay (old_frame);
-
   pending = 0;
   reconsider_clip_changes (w, current_buffer);
   last_escape_glyph_frame = NULL;
@@ -12925,25 +13073,20 @@ redisplay_internal (void)
       FRAME_TTY (sf)->previous_frame = sf;
     }
 
-  /* Set the visible flags for all frames.  Do this before checking
-     for resized or garbaged frames; they want to know if their frames
-     are visible.  See the comment in frame.h for
-     FRAME_SAMPLE_VISIBILITY.  */
-  {
-    Lisp_Object tail, frame;
-
-    number_of_visible_frames = 0;
+  /* Set the visible flags for all frames.  Do this before checking for
+     resized or garbaged frames; they want to know if their frames are
+     visible.  See the comment in frame.h for FRAME_SAMPLE_VISIBILITY.  */
+  number_of_visible_frames = 0;
 
-    FOR_EACH_FRAME (tail, frame)
-      {
-       struct frame *f = XFRAME (frame);
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
 
-       FRAME_SAMPLE_VISIBILITY (f);
-       if (FRAME_VISIBLE_P (f))
-         ++number_of_visible_frames;
-       clear_desired_matrices (f);
-      }
-  }
+      FRAME_SAMPLE_VISIBILITY (f);
+      if (FRAME_VISIBLE_P (f))
+       ++number_of_visible_frames;
+      clear_desired_matrices (f);
+    }
 
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
@@ -12957,8 +13100,7 @@ redisplay_internal (void)
     }
 
   /* Clear frames marked as garbaged.  */
-  if (frame_garbaged)
-    clear_garbaged_frames ();
+  clear_garbaged_frames ();
 
   /* Build menubar and tool-bar items.  */
   if (NILP (Vmemory_full))
@@ -12971,7 +13113,7 @@ redisplay_internal (void)
   if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
     {
       w->update_mode_line = 1;
-      if (buffer_shared > 1)
+      if (buffer_shared_and_changed ())
        update_mode_lines++;
     }
 
@@ -12979,24 +13121,15 @@ redisplay_internal (void)
   count1 = SPECPDL_INDEX ();
   specbind (Qinhibit_point_motion_hooks, Qt);
 
-  /* If %c is in the mode line, update it if needed.  */
-  if (!NILP (w->column_number_displayed)
-      /* This alternative quickly identifies a common case
-        where no change is needed.  */
-      && !(PT == XFASTINT (w->last_point)
-          && XFASTINT (w->last_modified) >= MODIFF
-          && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
-      && (XFASTINT (w->column_number_displayed) != current_column ()))
+  if (mode_line_update_needed (w))
     w->update_mode_line = 1;
 
   unbind_to (count1, Qnil);
 
   FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
 
-  /* The variable buffer_shared is set in redisplay_window and
-     indicates that we redisplay a buffer in different windows.  See
-     there.  */
-  consider_all_windows_p = (update_mode_lines || buffer_shared > 1
+  consider_all_windows_p = (update_mode_lines
+                           || buffer_shared_and_changed ()
                            || cursor_type_changed);
 
   /* If specs for an arrow have changed, do thorough redisplay
@@ -13042,23 +13175,20 @@ redisplay_internal (void)
          /* If window configuration was changed, frames may have been
             marked garbaged.  Clear them or we will experience
             surprises wrt scrolling.  */
-         if (frame_garbaged)
-           clear_garbaged_frames ();
+         clear_garbaged_frames ();
        }
     }
   else if (EQ (selected_window, minibuf_window)
-          && (current_buffer->clip_changed
-              || XFASTINT (w->last_modified) < MODIFF
-              || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
+          && (current_buffer->clip_changed || window_outdated (w))
           && resize_mini_window (w, 0))
     {
       /* Resized active mini-window to fit the size of what it is
          showing if its contents might have changed.  */
       must_finish = 1;
-/* FIXME: this causes all frames to be updated, which seems unnecessary
-   since only the current frame needs to be considered.  This function needs
-   to be rewritten with two variables, consider_all_windows and
-   consider_all_frames.  */
+      /* FIXME: this causes all frames to be updated, which seems unnecessary
+        since only the current frame needs to be considered.  This function
+        needs to be rewritten with two variables, consider_all_windows and
+        consider_all_frames.  */
       consider_all_windows_p = 1;
       ++windows_or_buffers_changed;
       ++update_mode_lines;
@@ -13066,8 +13196,7 @@ redisplay_internal (void)
       /* If window configuration was changed, frames may have been
         marked garbaged.  Clear them or we will experience
         surprises wrt scrolling.  */
-      if (frame_garbaged)
-       clear_garbaged_frames ();
+      clear_garbaged_frames ();
     }
 
 
@@ -13114,9 +13243,7 @@ redisplay_internal (void)
              || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
        /* Former continuation line has disappeared by becoming empty.  */
        goto cancel;
-      else if (XFASTINT (w->last_modified) < MODIFF
-              || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
-              || MINI_WINDOW_P (w))
+      else if (window_outdated (w) || MINI_WINDOW_P (w))
        {
          /* We have to handle the case of continuation around a
             wide-column character (see the comment in indent.c around
@@ -13196,17 +13323,17 @@ redisplay_internal (void)
              if ((it.glyph_row - 1)->displays_text_p)
                {
                  if (XFASTINT (w->window_end_vpos) < this_line_vpos)
-                   XSETINT (w->window_end_vpos, this_line_vpos);
+                   wset_window_end_vpos (w, make_number (this_line_vpos));
                }
              else if (XFASTINT (w->window_end_vpos) == this_line_vpos
                       && this_line_vpos > 0)
-               XSETINT (w->window_end_vpos, this_line_vpos - 1);
-             w->window_end_valid = Qnil;
+               wset_window_end_vpos (w, make_number (this_line_vpos - 1));
+             wset_window_end_valid (w, Qnil);
 
              /* Update hint: No need to try to scroll in update_window.  */
              w->desired_matrix->no_scrolling_p = 1;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
              *w->desired_matrix->method = 0;
              debug_method_add (w, "optimization 1");
 #endif
@@ -13219,7 +13346,7 @@ redisplay_internal (void)
            goto cancel;
        }
       else if (/* Cursor position hasn't changed.  */
-              PT == XFASTINT (w->last_point)
+              PT == w->last_point
               /* Make sure the cursor was last displayed
                  in this window.  Otherwise we have to reposition it.  */
               && 0 <= w->cursor.vpos
@@ -13271,10 +13398,10 @@ redisplay_internal (void)
              && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
                  row->enabled_p))
            {
-             xassert (this_line_vpos == it.vpos);
-             xassert (this_line_y == it.current_y);
+             eassert (this_line_vpos == it.vpos);
+             eassert (this_line_y == it.current_y);
              set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
              *w->desired_matrix->method = 0;
              debug_method_add (w, "optimization 3");
 #endif
@@ -13290,7 +13417,7 @@ redisplay_internal (void)
     }
 
   CHARPOS (this_line_start_pos) = 0;
-  consider_all_windows_p |= buffer_shared > 1;
+  consider_all_windows_p |= buffer_shared_and_changed ();
   ++clear_face_cache_count;
 #ifdef HAVE_WINDOW_SYSTEM
   ++clear_image_cache_count;
@@ -13302,26 +13429,21 @@ redisplay_internal (void)
 
   if (consider_all_windows_p)
     {
-      Lisp_Object tail, frame;
-
       FOR_EACH_FRAME (tail, frame)
        XFRAME (frame)->updated_p = 0;
 
-      /* Recompute # windows showing selected buffer.  This will be
-        incremented each time such a window is displayed.  */
-      buffer_shared = 0;
-
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
 
+         /* We don't have to do anything for unselected terminal
+            frames.  */
+         if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+             && !EQ (FRAME_TTY (f)->top_frame, frame))
+           continue;
+
          if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
-             if (! EQ (frame, selected_frame))
-               /* Select the frame, for the sake of frame-local
-                  variables.  */
-               select_frame_for_redisplay (frame);
-
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
              if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
@@ -13371,12 +13493,6 @@ redisplay_internal (void)
            }
        }
 
-      if (!EQ (old_frame, selected_frame)
-         && FRAME_LIVE_P (XFRAME (old_frame)))
-       /* We played a bit fast-and-loose above and allowed selected_frame
-          and selected_window to be temporarily out-of-sync but let's make
-          sure this stays contained.  */
-       select_frame_for_redisplay (old_frame);
       eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
 
       if (!pending)
@@ -13506,7 +13622,6 @@ redisplay_internal (void)
      frames here explicitly.  */
   if (!pending)
     {
-      Lisp_Object tail, frame;
       int new_count = 0;
 
       FOR_EACH_FRAME (tail, frame)
@@ -13557,6 +13672,7 @@ redisplay_internal (void)
 #endif /* HAVE_WINDOW_SYSTEM */
 
  end_of_redisplay:
+  backtrace_list = backtrace.next;
   unbind_to (count, Qnil);
   RESUME_POLLING;
 }
@@ -13595,24 +13711,13 @@ redisplay_preserve_echo_area (int from_where)
 }
 
 
-/* Function registered with record_unwind_protect in
-   redisplay_internal.  Reset redisplaying_p to the value it had
-   before redisplay_internal was called, and clear
-   prevent_freeing_realized_faces_p.  It also selects the previously
-   selected frame, unless it has been deleted (by an X connection
-   failure during redisplay, for example).  */
+/* Function registered with record_unwind_protect in redisplay_internal.
+   Clear redisplaying_p.  Also select the previously selected frame.  */
 
 static Lisp_Object
-unwind_redisplay (Lisp_Object val)
+unwind_redisplay (Lisp_Object old_frame)
 {
-  Lisp_Object old_redisplaying_p, old_frame;
-
-  old_redisplaying_p = XCAR (val);
-  redisplaying_p = XFASTINT (old_redisplaying_p);
-  old_frame = XCDR (val);
-  if (! EQ (old_frame, selected_frame)
-      && FRAME_LIVE_P (XFRAME (old_frame)))
-    select_frame_for_redisplay (old_frame);
+  redisplaying_p = 0;
   return Qnil;
 }
 
@@ -13629,10 +13734,8 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p)
     {
       struct buffer *b = XBUFFER (w->buffer);
 
-      w->last_modified
-       = make_number (accurate_p ? BUF_MODIFF (b) : 0);
-      w->last_overlay_modified
-       = make_number (accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
+      w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
+      w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
       w->last_had_star
        = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
 
@@ -13654,15 +13757,15 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p)
          w->last_cursor_off_p = w->cursor_off_p;
 
          if (w == XWINDOW (selected_window))
-           w->last_point = make_number (BUF_PT (b));
+           w->last_point = BUF_PT (b);
          else
-           w->last_point = make_number (XMARKER (w->pointm)->charpos);
+           w->last_point = marker_position (w->pointm);
        }
     }
 
   if (accurate_p)
     {
-      w->window_end_valid = w->buffer;
+      wset_window_end_valid (w, w->buffer);
       w->update_mode_line = 0;
     }
 }
@@ -13834,7 +13937,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
   /* Don't even try doing anything if called for a mode-line or
      header-line row, since the rest of the code isn't prepared to
      deal with such calamities.  */
-  xassert (!row->mode_line_p);
+  eassert (!row->mode_line_p);
   if (row->mode_line_p)
     return 0;
 
@@ -13935,16 +14038,13 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                    break;
                  }
                /* See if we've found a better approximation to
-                  POS_BEFORE or to POS_AFTER.  Note that we want the
-                  first (leftmost) glyph of all those that are the
-                  closest from below, and the last (rightmost) of all
-                  those from above.  */
+                  POS_BEFORE or to POS_AFTER.  */
                if (0 > dpos && dpos > pos_before - pt_old)
                  {
                    pos_before = glyph->charpos;
                    glyph_before = glyph;
                  }
-               else if (0 < dpos && dpos <= pos_after - pt_old)
+               else if (0 < dpos && dpos < pos_after - pt_old)
                  {
                    pos_after = glyph->charpos;
                    glyph_after = glyph;
@@ -14028,7 +14128,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                    pos_before = glyph->charpos;
                    glyph_before = glyph;
                  }
-               else if (0 < dpos && dpos <= pos_after - pt_old)
+               else if (0 < dpos && dpos < pos_after - pt_old)
                  {
                    pos_after = glyph->charpos;
                    glyph_after = glyph;
@@ -14081,7 +14181,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
      GLYPH_BEFORE and GLYPH_AFTER.  */
   if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
        && BUFFERP (glyph->object) && glyph->charpos == pt_old)
-      && bpos_covered < pt_old)
+      && !(bpos_max < pt_old && pt_old <= bpos_covered))
     {
       /* An empty line has a single glyph whose OBJECT is zero and
         whose CHARPOS is the position of a newline on that line.
@@ -14090,7 +14190,12 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
         CHARPOS is zero or negative.  */
       int empty_line_p =
        (row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
-       && INTEGERP (glyph->object) && glyph->charpos > 0;
+       && INTEGERP (glyph->object) && glyph->charpos > 0
+       /* On a TTY, continued and truncated rows also have a glyph at
+          their end whose OBJECT is zero and whose CHARPOS is
+          positive (the continuation and truncation glyphs), but such
+          rows are obviously not "empty".  */
+       && !(row->continued_p || row->truncated_on_right_p);
 
       if (row->ends_in_ellipsis_p && pos_after == last_pos)
        {
@@ -14260,6 +14365,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
             the cursor is not on this line.  */
          if (cursor == NULL
              && (row->reversed_p ? glyph <= end : glyph >= end)
+             && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
              && STRINGP (end->object)
              && row->continued_p)
            return 0;
@@ -14289,6 +14395,21 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
  compute_x:
   if (cursor != NULL)
     glyph = cursor;
+  else if (glyph == glyphs_end
+          && pos_before == pos_after
+          && STRINGP ((row->reversed_p
+                       ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
+                       : row->glyphs[TEXT_AREA])->object))
+    {
+      /* If all the glyphs of this row came from strings, put the
+        cursor on the first glyph of the row.  This avoids having the
+        cursor outside of the text area in this very rare and hard
+        use case.  */
+      glyph =
+       row->reversed_p
+       ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
+       : row->glyphs[TEXT_AREA];
+    }
   if (x < 0)
     {
       struct glyph *g;
@@ -14297,7 +14418,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
       for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
        {
          if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
-           abort ();
+           emacs_abort ();
          x += g->pixel_width;
        }
     }
@@ -14411,14 +14532,14 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 
    We assume that the window's buffer is really current.  */
 
-static inline struct text_pos
+static struct text_pos
 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->buffer))
-    abort ();
+    emacs_abort ();
 
   if (!NILP (Vwindow_scroll_functions))
     {
@@ -14426,8 +14547,7 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
                            make_number (CHARPOS (startp)));
       SET_TEXT_POS_FROM_MARKER (startp, w->start);
       /* In case the hook functions switch buffers.  */
-      if (current_buffer != XBUFFER (w->buffer))
-       set_buffer_internal_1 (XBUFFER (w->buffer));
+      set_buffer_internal (XBUFFER (w->buffer));
     }
 
   return startp;
@@ -14527,7 +14647,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
   /* We will never try scrolling more than this number of lines.  */
   int scroll_limit = SCROLL_LIMIT;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   debug_method_add (w, "try_scrolling");
 #endif
 
@@ -14625,13 +14745,18 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          if (NUMBERP (aggressive))
            {
              double float_amount = XFLOATINT (aggressive) * height;
-             amount_to_scroll = float_amount;
-             if (amount_to_scroll == 0 && float_amount > 0)
-               amount_to_scroll = 1;
+             int aggressive_scroll = float_amount;
+             if (aggressive_scroll == 0 && float_amount > 0)
+               aggressive_scroll = 1;
              /* Don't let point enter the scroll margin near top of
-                the window.  */
-             if (amount_to_scroll > height - 2*this_scroll_margin + dy)
-               amount_to_scroll = height - 2*this_scroll_margin + dy;
+                the window.  This could happen if the value of
+                scroll_up_aggressively is too large and there are
+                non-zero margins, because scroll_up_aggressively
+                means put point that fraction of window height
+                _from_the_bottom_margin_.  */
+             if (aggressive_scroll + 2*this_scroll_margin > height)
+               aggressive_scroll = height - 2*this_scroll_margin;
+             amount_to_scroll = dy + aggressive_scroll;
            }
        }
 
@@ -14691,7 +14816,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          /* Compute the vertical distance from PT to the scroll
             margin position.  Move as far as scroll_max allows, or
             one screenful, or 10 screen lines, whichever is largest.
-            Give up if distance is greater than scroll_max.  */
+            Give up if distance is greater than scroll_max or if we
+            didn't reach the scroll margin position.  */
          SET_TEXT_POS (pos, PT, PT_BYTE);
          start_display (&it, w, pos);
          y0 = it.current_y;
@@ -14701,7 +14827,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
                      y_to_move, -1,
                      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
          dy = it.current_y - y0;
-         if (dy > scroll_max)
+         if (dy > scroll_max
+             || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
            return SCROLLING_FAILED;
 
          /* Compute new window start.  */
@@ -14719,15 +14846,16 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
              if (NUMBERP (aggressive))
                {
                  double float_amount = XFLOATINT (aggressive) * height;
-                 amount_to_scroll = float_amount;
-                 if (amount_to_scroll == 0 && float_amount > 0)
-                   amount_to_scroll = 1;
-                 amount_to_scroll -=
-                   this_scroll_margin - dy - FRAME_LINE_HEIGHT (f);
+                 int aggressive_scroll = float_amount;
+                 if (aggressive_scroll == 0 && float_amount > 0)
+                   aggressive_scroll = 1;
                  /* Don't let point enter the scroll margin near
-                    bottom of the window.  */
-                 if (amount_to_scroll > height - 2*this_scroll_margin + dy)
-                   amount_to_scroll = height - 2*this_scroll_margin + dy;
+                    bottom of the window, if the value of
+                    scroll_down_aggressively happens to be too
+                    large.  */
+                 if (aggressive_scroll + 2*this_scroll_margin > height)
+                   aggressive_scroll = height - 2*this_scroll_margin;
+                 amount_to_scroll = dy + aggressive_scroll;
                }
            }
 
@@ -14757,7 +14885,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
       if (!just_this_one_p
          || current_buffer->clip_changed
          || BEG_UNCHANGED < CHARPOS (startp))
-       w->base_line_number = Qnil;
+       wset_base_line_number (w, Qnil);
 
       /* If cursor ends up on a partially visible line,
         treat that as being off the bottom of the screen.  */
@@ -14879,11 +15007,16 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
   struct frame *f = XFRAME (w->frame);
   int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   if (inhibit_try_cursor_movement)
     return rc;
 #endif
 
+  /* Previously, there was a check for Lisp integer in the
+     if-statement below. Now, this field is converted to
+     ptrdiff_t, thus zero means invalid position in a buffer.  */
+  eassert (w->last_point > 0);
+
   /* Handle case where text has not changed, only point, and it has
      not moved off the frame.  */
   if (/* Point may be in this window.  */
@@ -14900,12 +15033,9 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
       /* Can't use this case if highlighting a region.  When a
          region exists, cursor movement has to do more than just
          set the cursor.  */
-      && !(!NILP (Vtransient_mark_mode)
-          && !NILP (BVAR (current_buffer, mark_active)))
+      && markpos_of_region () < 0
       && NILP (w->region_showing)
       && NILP (Vshow_trailing_whitespace)
-      /* Right after splitting windows, last_point may be nil.  */
-      && INTEGERP (w->last_point)
       /* This code is not used for mini-buffer for the sake of the case
         of redisplaying to replace an echo area message; since in
         that case the mini-buffer contents per se are usually
@@ -14926,7 +15056,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
       int this_scroll_margin, top_scroll_margin;
       struct glyph_row *row = NULL;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "cursor movement");
 #endif
 
@@ -14963,13 +15093,13 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
          int scroll_p = 0, must_scroll = 0;
          int last_y = window_text_bottom_y (w) - this_scroll_margin;
 
-         if (PT > XFASTINT (w->last_point))
+         if (PT > w->last_point)
            {
              /* Point has moved forward.  */
              while (MATRIX_ROW_END_CHARPOS (row) < PT
                     && MATRIX_ROW_BOTTOM_Y (row) < last_y)
                {
-                 xassert (row->enabled_p);
+                 eassert (row->enabled_p);
                  ++row;
                }
 
@@ -14998,7 +15128,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
                      && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
                scroll_p = 1;
            }
-         else if (PT < XFASTINT (w->last_point))
+         else if (PT < w->last_point)
            {
              /* Cursor has to be moved backward.  Note that PT >=
                 CHARPOS (startp) because of the outer if-statement.  */
@@ -15012,7 +15142,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
                     && (row->y > top_scroll_margin
                         || CHARPOS (startp) == BEGV))
                {
-                 xassert (row->enabled_p);
+                 eassert (row->enabled_p);
                  --row;
                }
 
@@ -15082,7 +15212,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
                      rc = CURSOR_MOVEMENT_MUST_SCROLL;
                      break;
                    }
-                 xassert (row->enabled_p);
+                 eassert (row->enabled_p);
                }
            }
          if (must_scroll)
@@ -15252,7 +15382,7 @@ set_vertical_scroll_bar (struct window *w)
    selected_window is redisplayed.
 
    We can return without actually redisplaying the window if
-   fonts_changed_p is nonzero.  In that case, redisplay_internal will
+   fonts_changed_p.  In that case, redisplay_internal will
    retry.  */
 
 static void
@@ -15283,8 +15413,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   opoint = lpoint;
 
   /* W must be a leaf window here.  */
-  xassert (!NILP (w->buffer));
-#if GLYPH_DEBUG
+  eassert (!NILP (w->buffer));
+#ifdef GLYPH_DEBUG
   *w->desired_matrix->method = 0;
 #endif
 
@@ -15344,8 +15474,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
     = (!NILP (w->window_end_valid)
        && !current_buffer->clip_changed
        && !current_buffer->prevent_redisplay_optimizations_p
-       && XFASTINT (w->last_modified) >= MODIFF
-       && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
+       && !window_outdated (w));
 
   /* Run the window-bottom-change-functions
      if it is possible that the text on the screen has changed
@@ -15367,8 +15496,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   buffer_unchanged_p
     = (!NILP (w->window_end_valid)
        && !current_buffer->clip_changed
-       && XFASTINT (w->last_modified) >= MODIFF
-       && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
+       && !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.  */
@@ -15379,46 +15507,24 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
       if (XMARKER (w->start)->buffer == current_buffer)
        compute_window_start_on_continuation_line (w);
 
-      w->window_end_valid = Qnil;
+      wset_window_end_valid (w, Qnil);
     }
 
   /* Some sanity checks.  */
   CHECK_WINDOW_END (w);
   if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
-    abort ();
+    emacs_abort ();
   if (BYTEPOS (opoint) < CHARPOS (opoint))
-    abort ();
-
-  /* If %c is in mode line, update it if needed.  */
-  if (!NILP (w->column_number_displayed)
-      /* This alternative quickly identifies a common case
-        where no change is needed.  */
-      && !(PT == XFASTINT (w->last_point)
-          && XFASTINT (w->last_modified) >= MODIFF
-          && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
-      && (XFASTINT (w->column_number_displayed) != current_column ()))
-    update_mode_line = 1;
+    emacs_abort ();
 
-  /* Count number of windows showing the selected buffer.  An indirect
-     buffer counts as its base buffer.  */
-  if (!just_this_one_p)
-    {
-      struct buffer *current_base, *window_base;
-      current_base = current_buffer;
-      window_base = XBUFFER (XWINDOW (selected_window)->buffer);
-      if (current_base->base_buffer)
-       current_base = current_base->base_buffer;
-      if (window_base->base_buffer)
-       window_base = window_base->base_buffer;
-      if (current_base == window_base)
-       buffer_shared++;
-    }
+  if (mode_line_update_needed (w))
+    update_mode_line = 1;
 
   /* Point refers normally to the selected window.  For any other
      window, set up appropriate value.  */
   if (!EQ (window, selected_window))
     {
-      ptrdiff_t new_pt = XMARKER (w->pointm)->charpos;
+      ptrdiff_t new_pt = marker_position (w->pointm);
       ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
       if (new_pt < BEGV)
        {
@@ -15446,8 +15552,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
     {
       struct Lisp_Char_Table *disptab = buffer_display_table ();
 
-      if (! disptab_matches_widthtab (disptab,
-                                      XVECTOR (BVAR (current_buffer, width_table))))
+      if (! disptab_matches_widthtab
+         (disptab, XVECTOR (BVAR (current_buffer, width_table))))
         {
           invalidate_region_cache (current_buffer,
                                    current_buffer->width_run_cache,
@@ -15490,11 +15596,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
       w->force_start = 0;
       w->vscroll = 0;
-      w->window_end_valid = Qnil;
+      wset_window_end_valid (w, Qnil);
 
       /* Forget any recorded base line for line number display.  */
       if (!buffer_unchanged_p)
-       w->base_line_number = Qnil;
+       wset_base_line_number (w, Qnil);
 
       /* Redisplay the mode line.  Select the buffer properly for that.
         Also, run the hook window-scroll-functions
@@ -15511,8 +15617,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          startp = run_window_scroll_functions (window, startp);
        }
 
-      w->last_modified = make_number (0);
-      w->last_overlay_modified = make_number (0);
+      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)
@@ -15544,6 +15650,34 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
             Move it back to a fully-visible line.  */
          new_vpos = window_box_height (w);
        }
+      else if (w->cursor.vpos >=0)
+       {
+         /* 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);
+         bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
+
+         /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
+            below, which finds the row to move point to, advances by
+            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);
+         else
+           {
+             int window_height = window_box_height (w);
+
+             if (header_line)
+               window_height += CURRENT_HEADER_LINE_HEIGHT (w);
+             if (w->cursor.y >= window_height - pixel_margin)
+               new_vpos = window_height - pixel_margin;
+           }
+       }
 
       /* If we need to move point for either of the above reasons,
         now actually do it.  */
@@ -15567,8 +15701,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
          /* If we are highlighting the region, then we just changed
             the region, so redisplay to show it.  */
-         if (!NILP (Vtransient_mark_mode)
-             && !NILP (BVAR (current_buffer, mark_active)))
+         if (0 <= markpos_of_region ())
            {
              clear_glyph_matrix (w->desired_matrix);
              if (!try_window (window, startp, 0))
@@ -15576,7 +15709,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
            }
        }
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "forced window start");
 #endif
       goto done;
@@ -15599,7 +15732,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          goto try_to_scroll;
 
        default:
-         abort ();
+         emacs_abort ();
        }
     }
   /* If current starting point was originally the beginning of a line
@@ -15608,7 +15741,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
           && !(CHARPOS (startp) <= BEGV
                || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
     {
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "recenter 1");
 #endif
       goto recenter;
@@ -15619,7 +15752,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
      not work.  It is 0 if unsuccessful for some other reason.  */
   else if ((tem = try_window_id (w)) != 0)
     {
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "try_window_id %d", tem);
 #endif
 
@@ -15637,8 +15770,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
           && (CHARPOS (startp) < ZV
               /* Avoid starting at end of buffer.  */
               || CHARPOS (startp) == BEGV
-              || (XFASTINT (w->last_modified) >= MODIFF
-                  && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
+              || !window_outdated (w)))
     {
       int d1, d2, d3, d4, d5, d6;
 
@@ -15676,7 +15808,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          goto force_start;
        }
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "same window start");
 #endif
 
@@ -15708,7 +15840,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
              || current_buffer->clip_changed
              || BEG_UNCHANGED < CHARPOS (startp))
            /* Forget any recorded base line for line number display.  */
-           w->base_line_number = Qnil;
+           wset_base_line_number (w, Qnil);
 
          if (!cursor_row_fully_visible_p (w, 1, 0))
            {
@@ -15725,8 +15857,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
  try_to_scroll:
 
-  w->last_modified = make_number (0);
-  w->last_overlay_modified = make_number (0);
+  w->last_modified = 0;
+  w->last_overlay_modified = 0;
 
   /* Redisplay the mode line.  Select the buffer properly for that.  */
   if (!update_mode_line)
@@ -15762,7 +15894,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          break;
 
        default:
-         abort ();
+         emacs_abort ();
        }
     }
 
@@ -15771,7 +15903,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
  recenter:
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   debug_method_add (w, "recenter");
 #endif
 
@@ -15779,7 +15911,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
   /* Forget any previously recorded base line for line number display.  */
   if (!buffer_unchanged_p)
-    w->base_line_number = Qnil;
+    wset_base_line_number (w, Qnil);
 
   /* Determine the window start relative to point.  */
   init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
@@ -15863,7 +15995,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
     }
   move_it_vertically_backward (&it, centering_position);
 
-  xassert (IT_CHARPOS (it) >= BEGV);
+  eassert (IT_CHARPOS (it) >= BEGV);
 
   /* The function move_it_vertically_backward may move over more
      than the specified y-distance.  If it->w is small, e.g. a
@@ -16037,8 +16169,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   if (!line_number_displayed
       && !BUFFERP (w->base_line_pos))
     {
-      w->base_line_pos = Qnil;
-      w->base_line_number = Qnil;
+      wset_base_line_pos (w, Qnil);
+      wset_base_line_number (w, Qnil);
     }
 
  finish_menu_bars:
@@ -16088,15 +16220,15 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
                                    || w->pseudo_window_p)))
     {
       update_begin (f);
-      BLOCK_INPUT;
+      block_input ();
       if (draw_window_fringes (w, 1))
        x_draw_vertical_border (w);
-      UNBLOCK_INPUT;
+      unblock_input ();
       update_end (f);
     }
 #endif /* HAVE_WINDOW_SYSTEM */
 
-  /* We go to this label, with fonts_changed_p nonzero,
+  /* We go to this label, with fonts_changed_p 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.  */
@@ -16212,25 +16344,26 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
      window_end_vpos to its row number.  */
   if (last_text_row)
     {
-      xassert (MATRIX_ROW_DISPLAYS_TEXT_P (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);
-      w->window_end_pos
-       = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-      w->window_end_vpos
-       = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
-      xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
-              ->displays_text_p);
+      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)));
+      eassert
+       (MATRIX_ROW (w->desired_matrix,
+                    XFASTINT (w->window_end_vpos))->displays_text_p);
     }
   else
     {
       w->window_end_bytepos = Z_BYTE - ZV_BYTE;
-      w->window_end_pos = make_number (Z - ZV);
-      w->window_end_vpos = make_number (0);
+      wset_window_end_pos (w, make_number (Z - ZV));
+      wset_window_end_vpos (w, make_number (0));
     }
 
   /* But that is not valid info until redisplay finishes.  */
-  w->window_end_valid = Qnil;
+  wset_window_end_valid (w, Qnil);
   return 1;
 }
 
@@ -16259,7 +16392,7 @@ try_window_reusing_current_matrix (struct window *w)
   struct glyph_row *start_row;
   int start_vpos, min_y, max_y;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   if (inhibit_try_window_reusing)
     return 0;
 #endif
@@ -16273,8 +16406,7 @@ try_window_reusing_current_matrix (struct window *w)
     return 0;
 
   /* Can't do this if region may have changed.  */
-  if ((!NILP (Vtransient_mark_mode)
-       && !NILP (BVAR (current_buffer, mark_active)))
+  if (0 <= markpos_of_region ()
       || !NILP (w->region_showing)
       || !NILP (Vshow_trailing_whitespace))
     return 0;
@@ -16454,34 +16586,36 @@ try_window_reusing_current_matrix (struct window *w)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
-         w->window_end_pos
-           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
-         w->window_end_vpos
-           = make_number (MATRIX_ROW_VPOS (last_reused_text_row,
-                                           w->current_matrix));
+         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)));
        }
       else if (last_text_row)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-         w->window_end_pos
-           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-         w->window_end_vpos
-           = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+         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)));
        }
       else
        {
          /* This window must be completely empty.  */
          w->window_end_bytepos = Z_BYTE - ZV_BYTE;
-         w->window_end_pos = make_number (Z - ZV);
-         w->window_end_vpos = make_number (0);
+         wset_window_end_pos (w, make_number (Z - ZV));
+         wset_window_end_vpos (w, make_number (0));
        }
-      w->window_end_valid = Qnil;
+      wset_window_end_valid (w, Qnil);
 
       /* Update hint: don't try scrolling again in update_window.  */
       w->desired_matrix->no_scrolling_p = 1;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "try_window_reusing_current_matrix 1");
 #endif
       return 1;
@@ -16528,7 +16662,7 @@ try_window_reusing_current_matrix (struct window *w)
        }
 
       /* Start displaying at the start of first_row_to_display.  */
-      xassert (first_row_to_display->y < yb);
+      eassert (first_row_to_display->y < yb);
       init_to_row_start (&it, w, first_row_to_display);
 
       nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
@@ -16600,7 +16734,7 @@ try_window_reusing_current_matrix (struct window *w)
        }
 
       /* Scroll the current matrix.  */
-      xassert (nrows_scrolled > 0);
+      eassert (nrows_scrolled > 0);
       rotate_matrix (w->current_matrix,
                     start_vpos,
                     MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
@@ -16625,28 +16759,33 @@ try_window_reusing_current_matrix (struct window *w)
            }
          if (row < bottom_row)
            {
-             struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
-             struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
-
-             /* Can't use this optimization with bidi-reordered glyph
-                rows, unless cursor is already at point. */
+             /* Can't simply scan the row for point with
+                bidi-reordered glyph rows.  Let set_cursor_from_row
+                figure out where to put the cursor, and if it fails,
+                give up.  */
              if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
                {
-                 if (!(w->cursor.hpos >= 0
-                       && w->cursor.hpos < row->used[TEXT_AREA]
-                       && BUFFERP (glyph->object)
-                       && glyph->charpos == PT))
-                   return 0;
+                 if (!set_cursor_from_row (w, row, w->current_matrix,
+                                           0, 0, 0, 0))
+                   {
+                     clear_glyph_matrix (w->desired_matrix);
+                     return 0;
+                   }
                }
              else
-               for (; glyph < end
-                      && (!BUFFERP (glyph->object)
-                          || glyph->charpos < PT);
-                    glyph++)
-                 {
-                   w->cursor.hpos++;
-                   w->cursor.x += glyph->pixel_width;
-                 }
+               {
+                 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
+                 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
+
+                 for (; glyph < end
+                        && (!BUFFERP (glyph->object)
+                            || glyph->charpos < PT);
+                      glyph++)
+                   {
+                     w->cursor.hpos++;
+                     w->cursor.x += glyph->pixel_width;
+                   }
+               }
            }
        }
 
@@ -16657,21 +16796,22 @@ try_window_reusing_current_matrix (struct window *w)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-         w->window_end_pos
-           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-         w->window_end_vpos
-           = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+         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)));
        }
       else
        {
-         w->window_end_vpos
-           = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
+         wset_window_end_vpos
+           (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled));
        }
 
-      w->window_end_valid = Qnil;
+      wset_window_end_valid (w, Qnil);
       w->desired_matrix->no_scrolling_p = 1;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "try_window_reusing_current_matrix 2");
 #endif
       return 1;
@@ -16712,7 +16852,7 @@ find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
   row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
   while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
     {
-      xassert (row->enabled_p);
+      eassert (row->enabled_p);
       row_found = row;
       if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
        break;
@@ -16874,9 +17014,9 @@ sync_frame_with_window_matrix_rows (struct window *w)
 
   /* Preconditions: W must be a leaf window and full-width.  Its frame
      must have a frame matrix.  */
-  xassert (NILP (w->hchild) && NILP (w->vchild));
-  xassert (WINDOW_FULL_WIDTH_P (w));
-  xassert (!FRAME_WINDOW_P (f));
+  eassert (NILP (w->hchild) && NILP (w->vchild));
+  eassert (WINDOW_FULL_WIDTH_P (w));
+  eassert (!FRAME_WINDOW_P (f));
 
   /* If W is a full-width window, glyph pointers in W's current matrix
      have, by definition, to be the same as glyph pointers in the
@@ -17039,7 +17179,7 @@ try_window_id (struct window *w)
   struct text_pos start;
   ptrdiff_t first_changed_charpos, last_changed_charpos;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   if (inhibit_try_window_id)
     return 0;
 #endif
@@ -17085,11 +17225,11 @@ try_window_id (struct window *w)
     GIVE_UP (5);
 
   /* Another way to prevent redisplay optimizations.  */
-  if (XFASTINT (w->last_modified) == 0)
+  if (w->last_modified == 0)
     GIVE_UP (6);
 
   /* Verify that window is not hscrolled.  */
-  if (XFASTINT (w->hscroll) != 0)
+  if (w->hscroll != 0)
     GIVE_UP (7);
 
   /* Verify that display wasn't paused.  */
@@ -17098,8 +17238,7 @@ try_window_id (struct window *w)
 
   /* Can't use this if highlighting a region because a cursor movement
      will do more than just set the cursor.  */
-  if (!NILP (Vtransient_mark_mode)
-      && !NILP (BVAR (current_buffer, mark_active)))
+  if (0 <= markpos_of_region ())
     GIVE_UP (9);
 
   /* Likewise if highlighting trailing whitespace.  */
@@ -17206,7 +17345,7 @@ try_window_id (struct window *w)
          if (row)
            set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
          else
-           abort ();
+           emacs_abort ();
          return 1;
        }
     }
@@ -17240,8 +17379,8 @@ try_window_id (struct window *w)
        {
          /* We have to compute the window end anew since text
             could have been added/removed after it.  */
-         w->window_end_pos
-           = make_number (Z - MATRIX_ROW_END_CHARPOS (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);
 
@@ -17250,7 +17389,7 @@ try_window_id (struct window *w)
          if (row)
            set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
          else
-           abort ();
+           emacs_abort ();
          return 2;
        }
     }
@@ -17313,7 +17452,7 @@ try_window_id (struct window *w)
       it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
       it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
 
-      xassert (it.hpos == 0 && it.current_x == 0);
+      eassert (it.hpos == 0 && it.current_x == 0);
     }
   else
     {
@@ -17343,7 +17482,7 @@ try_window_id (struct window *w)
   stop_pos = 0;
   if (first_unchanged_at_end_row)
     {
-      xassert (last_unchanged_at_beg_row == NULL
+      eassert (last_unchanged_at_beg_row == NULL
               || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
 
       /* If this is a continuation line, move forward to the next one
@@ -17366,19 +17505,19 @@ try_window_id (struct window *w)
                      + delta);
          first_unchanged_at_end_vpos
            = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
-         xassert (stop_pos >= Z - END_UNCHANGED);
+         eassert (stop_pos >= Z - END_UNCHANGED);
        }
     }
   else if (last_unchanged_at_beg_row == NULL)
     GIVE_UP (19);
 
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
 
   /* Either there is no unchanged row at the end, or the one we have
      now displays text.  This is a necessary condition for the window
      end pos calculation at the end of this function.  */
-  xassert (first_unchanged_at_end_row == NULL
+  eassert (first_unchanged_at_end_row == NULL
           || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
 
   debug_last_unchanged_at_beg_vpos
@@ -17387,7 +17526,7 @@ try_window_id (struct window *w)
        : -1);
   debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
 
-#endif /* GLYPH_DEBUG != 0 */
+#endif /* GLYPH_DEBUG */
 
 
   /* Display new lines.  Set last_text_row to the last new line
@@ -17573,15 +17712,15 @@ try_window_id (struct window *w)
     {
       rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
                     bottom_vpos, dvpos);
-      enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
-                               bottom_vpos, 0);
+      clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
+                              bottom_vpos);
     }
   else if (dvpos > 0)
     {
       rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
                     bottom_vpos, dvpos);
-      enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
-                               first_unchanged_at_end_vpos + dvpos, 0);
+      clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
+                              first_unchanged_at_end_vpos + dvpos);
     }
 
   /* For frame-based redisplay, make sure that current frame and window
@@ -17623,7 +17762,7 @@ try_window_id (struct window *w)
       struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
 
       /* If last_row is the window end line, it should display text.  */
-      xassert (last_row->displays_text_p);
+      eassert (last_row->displays_text_p);
 
       /* If window end line was partially visible before, begin
         displaying at that line.  Otherwise begin displaying with the
@@ -17670,27 +17809,28 @@ try_window_id (struct window *w)
         matrix.  Set row to the last row displaying text in current
         matrix starting at first_unchanged_at_end_row, after
         scrolling.  */
-      xassert (first_unchanged_at_end_row->displays_text_p);
+      eassert (first_unchanged_at_end_row->displays_text_p);
       row = find_last_row_displaying_text (w->current_matrix, &it,
                                           first_unchanged_at_end_row);
-      xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
+      eassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
 
-      w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (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);
-      w->window_end_vpos
-       = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
-      xassert (w->window_end_bytepos >= 0);
+      wset_window_end_vpos
+       (w, make_number (MATRIX_ROW_VPOS (row, w->current_matrix)));
+      eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "A"));
     }
   else if (last_text_row_at_end)
     {
-      w->window_end_pos
-       = make_number (Z - MATRIX_ROW_END_CHARPOS (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);
-      w->window_end_vpos
-       = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
-      xassert (w->window_end_bytepos >= 0);
+      wset_window_end_vpos
+       (w, make_number (MATRIX_ROW_VPOS (last_text_row_at_end,
+                                         desired_matrix)));
+      eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "B"));
     }
   else if (last_text_row)
@@ -17698,13 +17838,13 @@ 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.  */
-      w->window_end_pos
-       = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+      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);
-      w->window_end_vpos
-       = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
-      xassert (w->window_end_bytepos >= 0);
+      wset_window_end_vpos
+       (w, make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix)));
+      eassert (w->window_end_bytepos >= 0);
     }
   else if (first_unchanged_at_end_row == NULL
           && last_text_row == NULL
@@ -17730,21 +17870,21 @@ try_window_id (struct window *w)
            row  = current_row;
        }
 
-      xassert (row != NULL);
-      w->window_end_vpos = make_number (vpos + 1);
-      w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+      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_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
-      xassert (w->window_end_bytepos >= 0);
+      eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "C"));
     }
   else
-    abort ();
+    emacs_abort ();
 
   IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
            debug_end_vpos = XFASTINT (w->window_end_vpos));
 
   /* Record that display has not been completed.  */
-  w->window_end_valid = Qnil;
+  wset_window_end_valid (w, Qnil);
   w->desired_matrix->no_scrolling_p = 1;
   return 3;
 
@@ -17757,7 +17897,7 @@ try_window_id (struct window *w)
                        More debugging support
  ***********************************************************************/
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
 
 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
@@ -17944,7 +18084,7 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
 
       for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
        {
-         char *s = (char *) alloca (row->used[area] + 1);
+         char *s = alloca (row->used[area] + 1);
          int i;
 
          for (i = 0; i < row->used[area]; ++i)
@@ -18136,11 +18276,8 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
 }
 
 
-/* Insert truncation glyphs at the start of IT->glyph_row.  Truncation
-   glyphs are only inserted for terminal frames since we can't really
-   win with truncation glyphs when partially visible glyphs are
-   involved.  Which glyphs to insert is determined by
-   produce_special_glyphs.  */
+/* Insert truncation glyphs at the start of IT->glyph_row.  Which
+   glyphs to insert is determined by produce_special_glyphs.  */
 
 static void
 insert_left_trunc_glyphs (struct it *it)
@@ -18148,7 +18285,11 @@ insert_left_trunc_glyphs (struct it *it)
   struct it truncate_it;
   struct glyph *from, *end, *to, *toend;
 
-  xassert (!FRAME_WINDOW_P (it->f));
+  eassert (!FRAME_WINDOW_P (it->f)
+          || (!it->glyph_row->reversed_p
+              && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
+          || (it->glyph_row->reversed_p
+              && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
 
   /* Get the truncation glyphs.  */
   truncate_it = *it;
@@ -18163,20 +18304,65 @@ insert_left_trunc_glyphs (struct it *it)
   /* Overwrite glyphs from IT with truncation glyphs.  */
   if (!it->glyph_row->reversed_p)
     {
+      short tused = truncate_it.glyph_row->used[TEXT_AREA];
+
       from = truncate_it.glyph_row->glyphs[TEXT_AREA];
-      end = from + truncate_it.glyph_row->used[TEXT_AREA];
+      end = from + tused;
       to = it->glyph_row->glyphs[TEXT_AREA];
       toend = to + it->glyph_row->used[TEXT_AREA];
+      if (FRAME_WINDOW_P (it->f))
+       {
+         /* On GUI frames, when variable-size fonts are displayed,
+            the truncation glyphs may need more pixels than the row's
+            glyphs they overwrite.  We overwrite more glyphs to free
+            enough screen real estate, and enlarge the stretch glyph
+            on the right (see display_line), if there is one, to
+            preserve the screen position of the truncation glyphs on
+            the right.  */
+         int w = 0;
+         struct glyph *g = to;
+         short used;
+
+         /* The first glyph could be partially visible, in which case
+            it->glyph_row->x will be negative.  But we want the left
+            truncation glyphs to be aligned at the left margin of the
+            window, so we override the x coordinate at which the row
+            will begin.  */
+         it->glyph_row->x = 0;
+         while (g < toend && w < it->truncation_pixel_width)
+           {
+             w += g->pixel_width;
+             ++g;
+           }
+         if (g - to - tused > 0)
+           {
+             memmove (to + tused, g, (toend - g) * sizeof(*g));
+             it->glyph_row->used[TEXT_AREA] -= g - to - tused;
+           }
+         used = it->glyph_row->used[TEXT_AREA];
+         if (it->glyph_row->truncated_on_right_p
+             && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
+             && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
+             == STRETCH_GLYPH)
+           {
+             int extra = w - it->truncation_pixel_width;
+
+             it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
+           }
+       }
 
       while (from < end)
        *to++ = *from++;
 
       /* There may be padding glyphs left over.  Overwrite them too.  */
-      while (to < toend && CHAR_GLYPH_PADDING_P (*to))
+      if (!FRAME_WINDOW_P (it->f))
        {
-         from = truncate_it.glyph_row->glyphs[TEXT_AREA];
-         while (from < end)
-           *to++ = *from++;
+         while (to < toend && CHAR_GLYPH_PADDING_P (*to))
+           {
+             from = truncate_it.glyph_row->glyphs[TEXT_AREA];
+             while (from < end)
+               *to++ = *from++;
+           }
        }
 
       if (to > toend)
@@ -18184,22 +18370,48 @@ insert_left_trunc_glyphs (struct it *it)
     }
   else
     {
+      short tused = truncate_it.glyph_row->used[TEXT_AREA];
+
       /* In R2L rows, overwrite the last (rightmost) glyphs, and do
         that back to front.  */
       end = truncate_it.glyph_row->glyphs[TEXT_AREA];
       from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
       toend = it->glyph_row->glyphs[TEXT_AREA];
       to = toend + it->glyph_row->used[TEXT_AREA] - 1;
+      if (FRAME_WINDOW_P (it->f))
+       {
+         int w = 0;
+         struct glyph *g = to;
+
+         while (g >= toend && w < it->truncation_pixel_width)
+           {
+             w += g->pixel_width;
+             --g;
+           }
+         if (to - g - tused > 0)
+           to = g + tused;
+         if (it->glyph_row->truncated_on_right_p
+             && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
+             && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
+           {
+             int extra = w - it->truncation_pixel_width;
+
+             it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
+           }
+       }
 
       while (from >= end && to >= toend)
        *to-- = *from--;
-      while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
+      if (!FRAME_WINDOW_P (it->f))
        {
-         from =
-           truncate_it.glyph_row->glyphs[TEXT_AREA]
-           + truncate_it.glyph_row->used[TEXT_AREA] - 1;
-         while (from >= end && to >= toend)
-           *to-- = *from--;
+         while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
+           {
+             from =
+               truncate_it.glyph_row->glyphs[TEXT_AREA]
+               + truncate_it.glyph_row->used[TEXT_AREA] - 1;
+             while (from >= end && to >= toend)
+               *to-- = *from--;
+           }
        }
       if (from >= end)
        {
@@ -18281,8 +18493,8 @@ compute_line_metrics (struct it *it)
       for (i = 0; i < row->used[TEXT_AREA]; ++i)
        row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
 
-      xassert (row->pixel_width >= 0);
-      xassert (row->ascent >= 0 && row->height > 0);
+      eassert (row->pixel_width >= 0);
+      eassert (row->ascent >= 0 && row->height > 0);
 
       row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
                            || MATRIX_ROW_OVERLAPS_PRED_P (row));
@@ -18359,6 +18571,7 @@ append_space_for_newline (struct it *it, int default_face_p)
          int saved_char_to_display = it->char_to_display;
          int saved_x = it->current_x;
          int saved_face_id = it->face_id;
+         int saved_box_end = it->end_of_box_run_p;
          struct text_pos saved_pos;
          Lisp_Object saved_object;
          struct face *face;
@@ -18380,6 +18593,16 @@ append_space_for_newline (struct it *it, int default_face_p)
            it->face_id = it->saved_face_id;
          face = FACE_FROM_ID (it->f, it->face_id);
          it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
+         /* In R2L rows, we will prepend a stretch glyph that will
+            have the end_of_box_run_p flag set for it, so there's no
+            need for the appended newline glyph to have that flag
+            set.  */
+         if (it->glyph_row->reversed_p
+             /* But if the appended newline glyph goes all the way to
+                the end of the row, there will be no stretch glyph,
+                so leave the box flag set.  */
+             && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x)
+           it->end_of_box_run_p = 0;
 
          PRODUCE_GLYPHS (it);
 
@@ -18393,6 +18616,7 @@ append_space_for_newline (struct it *it, int default_face_p)
          it->len = saved_len;
          it->c = saved_c;
          it->char_to_display = saved_char_to_display;
+         it->end_of_box_run_p = saved_box_end;
          return 1;
        }
     }
@@ -18482,7 +18706,7 @@ extend_face_to_end_of_line (struct it *it)
          struct glyph *g;
          int row_width, stretch_ascent, stretch_width;
          struct text_pos saved_pos;
-         int saved_face_id, saved_avoid_cursor;
+         int saved_face_id, saved_avoid_cursor, saved_box_start;
 
          for (row_width = 0, g = row_start; g < row_end; g++)
            row_width += g->pixel_width;
@@ -18497,6 +18721,7 @@ extend_face_to_end_of_line (struct it *it)
              saved_avoid_cursor = it->avoid_cursor_p;
              it->avoid_cursor_p = 1;
              saved_face_id = it->face_id;
+             saved_box_start = it->start_of_box_run_p;
              /* The last row's stretch glyph should get the default
                 face, to avoid painting the rest of the window with
                 the region face, if the region ends at ZV.  */
@@ -18504,11 +18729,13 @@ extend_face_to_end_of_line (struct it *it)
                it->face_id = default_face->id;
              else
                it->face_id = face->id;
+             it->start_of_box_run_p = 0;
              append_stretch_glyph (it, make_number (0), stretch_width,
                                    it->ascent + it->descent, stretch_ascent);
              it->position = saved_pos;
              it->avoid_cursor_p = saved_avoid_cursor;
              it->face_id = saved_face_id;
+             it->start_of_box_run_p = saved_box_start;
            }
        }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -18755,7 +18982,7 @@ push_prefix_prop (struct it *it, Lisp_Object prop)
   struct text_pos pos =
     STRINGP (it->string) ? it->current.string_pos : it->current.pos;
 
-  xassert (it->method == GET_FROM_BUFFER
+  eassert (it->method == GET_FROM_BUFFER
           || it->method == GET_FROM_DISPLAY_VECTOR
           || it->method == GET_FROM_STRING);
 
@@ -18882,10 +19109,10 @@ unproduce_glyphs (struct it *it, int n)
 {
   struct glyph *glyph, *end;
 
-  xassert (it->glyph_row);
-  xassert (it->glyph_row->reversed_p);
-  xassert (it->area == TEXT_AREA);
-  xassert (n <= it->glyph_row->used[TEXT_AREA]);
+  eassert (it->glyph_row);
+  eassert (it->glyph_row->reversed_p);
+  eassert (it->area == TEXT_AREA);
+  eassert (n <= it->glyph_row->used[TEXT_AREA]);
 
   if (n > it->glyph_row->used[TEXT_AREA])
     n = it->glyph_row->used[TEXT_AREA];
@@ -19043,7 +19270,7 @@ find_row_edges (struct it *it, struct glyph_row *row,
        /* A line that is entirely from a string/image/stretch...  */
        row->maxpos = row->minpos;
       else
-       abort ();
+       emacs_abort ();
     }
   else
     row->maxpos = it->current.pos;
@@ -19074,7 +19301,7 @@ display_line (struct it *it)
   ptrdiff_t min_bpos IF_LINT (= 0), max_bpos IF_LINT (= 0);
 
   /* We always start displaying at hpos zero even if hscrolled.  */
-  xassert (it->hpos == 0 && it->current_x == 0);
+  eassert (it->hpos == 0 && it->current_x == 0);
 
   if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
       >= it->w->desired_matrix->nrows)
@@ -19085,7 +19312,7 @@ display_line (struct it *it)
     }
 
   /* Is IT->w showing the region?  */
-  it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
+  wset_region_showing (it->w, it->region_beg_charpos > 0 ? Qt : Qnil);
 
   /* Clear the result glyph row and enable it.  */
   prepare_desired_row (row);
@@ -19109,9 +19336,22 @@ display_line (struct it *it)
      if the first glyph is partially visible or if we hit a line end.  */
   if (it->current_x < it->first_visible_x)
     {
+      enum move_it_result move_result;
+
       this_line_min_pos = row->start.pos;
-      move_it_in_display_line_to (it, ZV, it->first_visible_x,
-                                 MOVE_TO_POS | MOVE_TO_X);
+      move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
+                                               MOVE_TO_POS | MOVE_TO_X);
+      /* If we are under a large hscroll, move_it_in_display_line_to
+        could hit the end of the line without reaching
+        it->first_visible_x.  Pretend that we did reach it.  This is
+        especially important on a TTY, where we will call
+        extend_face_to_end_of_line, which needs to know how many
+        blank glyphs to produce.  */
+      if (it->current_x < it->first_visible_x
+         && (move_result == MOVE_NEWLINE_OR_CR
+             || move_result == MOVE_POS_MATCH_OR_ZV))
+       it->current_x = it->first_visible_x;
+
       /* Record the smallest positions seen while we moved over
         display elements that are not visible.  This is needed by
         redisplay_internal for optimizing the case where the cursor
@@ -19312,13 +19552,19 @@ display_line (struct it *it)
                      new_x > it->last_visible_x
                      /* Or it fits exactly on a window system frame.  */
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f))))
+                         && FRAME_WINDOW_P (it->f)
+                         && (row->reversed_p
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
                {
                  /* End of a continued line.  */
 
                  if (it->hpos == 0
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f)))
+                         && FRAME_WINDOW_P (it->f)
+                         && (row->reversed_p
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
                    {
                      /* Current glyph is the only one on the line or
                         fits exactly on the line.  We must continue
@@ -19429,6 +19675,10 @@ display_line (struct it *it)
                         window system frames.  We leave the glyph in
                         this row and let it fill the row, but don't
                         consume the TAB.  */
+                     if ((row->reversed_p
+                          ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                          : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
+                       produce_special_glyphs (it, IT_CONTINUATION);
                      it->continuation_lines_width += it->last_visible_x;
                      row->ends_in_middle_of_char_p = 1;
                      row->continued_p = 1;
@@ -19446,12 +19696,15 @@ display_line (struct it *it)
                      row->used[TEXT_AREA] = n_glyphs_before + i;
 
                      /* Display continuation glyphs.  */
-                     if (!FRAME_WINDOW_P (it->f))
+                     it->current_x = x_before;
+                     it->continuation_lines_width += x;
+                     if (!FRAME_WINDOW_P (it->f)
+                         || (row->reversed_p
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
                        produce_special_glyphs (it, IT_CONTINUATION);
                      row->continued_p = 1;
 
-                     it->current_x = x_before;
-                     it->continuation_lines_width += x;
                      extend_face_to_end_of_line (it);
 
                      if (nglyphs > 1 && i > 0)
@@ -19493,7 +19746,7 @@ display_line (struct it *it)
                     move_it_in_display_line at the start of this
                     function, unless the text display area of the
                     window is empty.  */
-                 xassert (it->first_visible_x <= it->last_visible_x);
+                 eassert (it->first_visible_x <= it->last_visible_x);
                }
            }
          /* Even if this display element produced no glyphs at all,
@@ -19553,12 +19806,15 @@ display_line (struct it *it)
       /* If we truncate lines, we are done when the last displayed
         glyphs reach past the right margin of the window.  */
       if (it->line_wrap == TRUNCATE
-         && (FRAME_WINDOW_P (it->f)
+         && (FRAME_WINDOW_P (it->f) && WINDOW_RIGHT_FRINGE_WIDTH (it->w)
              ? (it->current_x >= it->last_visible_x)
              : (it->current_x > it->last_visible_x)))
        {
          /* Maybe add truncation glyphs.  */
-         if (!FRAME_WINDOW_P (it->f))
+         if (!FRAME_WINDOW_P (it->f)
+             || (row->reversed_p
+                 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
            {
              int i, n;
 
@@ -19583,7 +19839,16 @@ display_line (struct it *it)
                  i = row->used[TEXT_AREA] - (i + 1);
                }
 
-             for (n = row->used[TEXT_AREA]; i < n; ++i)
+             it->current_x = x_before;
+             if (!FRAME_WINDOW_P (it->f))
+               {
+                 for (n = row->used[TEXT_AREA]; i < n; ++i)
+                   {
+                     row->used[TEXT_AREA] = i;
+                     produce_special_glyphs (it, IT_TRUNCATION);
+                   }
+               }
+             else
                {
                  row->used[TEXT_AREA] = i;
                  produce_special_glyphs (it, IT_TRUNCATION);
@@ -19604,6 +19869,7 @@ display_line (struct it *it)
                  row->exact_window_width_line_p = 1;
                  goto at_end_of_line;
                }
+             it->current_x = x_before;
            }
 
          row->truncated_on_right_p = 1;
@@ -19611,7 +19877,6 @@ display_line (struct it *it)
          reseat_at_next_visible_line_start (it, 0);
          row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
          it->hpos = hpos_before;
-         it->current_x = x_before;
          break;
        }
     }
@@ -19624,7 +19889,10 @@ display_line (struct it *it)
   if (it->first_visible_x
       && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
     {
-      if (!FRAME_WINDOW_P (it->f))
+      if (!FRAME_WINDOW_P (it->f)
+         || (row->reversed_p
+             ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+             : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
        insert_left_trunc_glyphs (it);
       row->truncated_on_left_p = 1;
     }
@@ -19685,7 +19953,7 @@ display_line (struct it *it)
        }
       else
        {
-         xassert (INTEGERP (overlay_arrow_string));
+         eassert (INTEGERP (overlay_arrow_string));
          row->overlay_arrow_bitmap = XINT (overlay_arrow_string);
        }
       overlay_arrow_seen = 1;
@@ -19843,7 +20111,7 @@ See also `bidi-paragraph-direction'.  */)
          return Qright_to_left;
          break;
        default:
-         abort ();
+         emacs_abort ();
        }
     }
 }
@@ -19888,7 +20156,7 @@ display_menu_bar (struct window *w)
 #endif /* HAVE_NS */
 
 #ifdef USE_X_TOOLKIT
-  xassert (!FRAME_WINDOW_P (f));
+  eassert (!FRAME_WINDOW_P (f));
   init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
   it.first_visible_x = 0;
   it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
@@ -19898,7 +20166,7 @@ display_menu_bar (struct window *w)
       /* Menu bar lines are displayed in the desired matrix of the
         dummy window menu_bar_window.  */
       struct window *menu_w;
-      xassert (WINDOWP (f->menu_bar_window));
+      eassert (WINDOWP (f->menu_bar_window));
       menu_w = XWINDOW (f->menu_bar_window);
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
                     MENU_FACE_ID);
@@ -19921,10 +20189,6 @@ display_menu_bar (struct window *w)
      this.  */
   it.paragraph_embedding = L2R;
 
-  if (! mode_line_inverse_video)
-    /* Force the menu-bar to be displayed in the default face.  */
-    it.base_face_id = it.face_id = DEFAULT_FACE_ID;
-
   /* Clear all rows of the menu bar.  */
   for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
     {
@@ -20038,17 +20302,21 @@ redisplay_mode_lines (Lisp_Object window, int force)
 static int
 display_mode_lines (struct window *w)
 {
-  Lisp_Object old_selected_window, old_selected_frame;
+  Lisp_Object old_selected_window = selected_window;
+  Lisp_Object old_selected_frame = selected_frame;
+  Lisp_Object new_frame = w->frame;
+  Lisp_Object old_frame_selected_window = XFRAME (new_frame)->selected_window;
   int n = 0;
 
-  old_selected_frame = selected_frame;
-  selected_frame = w->frame;
-  old_selected_window = selected_window;
+  selected_frame = new_frame;
+  /* FIXME: If we were to allow the mode-line's computation changing the buffer
+     or window's point, then we'd need select_window_1 here as well.  */
   XSETWINDOW (selected_window, w);
+  XFRAME (new_frame)->selected_window = selected_window;
 
   /* These will be set while the mode line specs are processed.  */
   line_number_displayed = 0;
-  w->column_number_displayed = Qnil;
+  wset_column_number_displayed (w, Qnil);
 
   if (WINDOW_WANTS_MODELINE_P (w))
     {
@@ -20067,6 +20335,7 @@ display_mode_lines (struct window *w)
       ++n;
     }
 
+  XFRAME (new_frame)->selected_window = old_frame_selected_window;
   selected_frame = old_selected_frame;
   selected_window = old_selected_window;
   return n;
@@ -20094,17 +20363,13 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
 
   it.glyph_row->mode_line_p = 1;
 
-  if (! mode_line_inverse_video)
-    /* Force the mode-line to be displayed in the default face.  */
-    it.base_face_id = it.face_id = DEFAULT_FACE_ID;
-
   /* FIXME: This should be controlled by a user option.  But
      supporting such an option is not trivial, since the mode line is
      made up of many separate strings.  */
   it.paragraph_embedding = L2R;
 
   record_unwind_protect (unwind_format_mode_line,
-                        format_mode_line_unwind_data (NULL, Qnil, 0));
+                        format_mode_line_unwind_data (NULL, NULL, Qnil, 0));
 
   mode_line_target = MODE_LINE_DISPLAY;
 
@@ -20214,7 +20479,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
 
   depth++;
 
-  switch (SWITCH_ENUM_CAST (XTYPE (elt)))
+  switch (XTYPE (elt))
     {
     case Lisp_String:
       {
@@ -20772,10 +21037,8 @@ are the selected window and the WINDOW's buffer).  */)
   Lisp_Object str;
   int string_start = 0;
 
-  if (NILP (window))
-    window = selected_window;
-  CHECK_WINDOW (window);
-  w = XWINDOW (window);
+  w = decode_any_window (window);
+  XSETWINDOW (window, w);
 
   if (NILP (buffer))
     buffer = w->buffer;
@@ -20798,19 +21061,18 @@ are the selected window and the WINDOW's buffer).  */)
     : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
     : DEFAULT_FACE_ID;
 
-  if (XBUFFER (buffer) != current_buffer)
-    old_buffer = current_buffer;
+  old_buffer = current_buffer;
 
   /* Save things including mode_line_proptrans_alist,
      and set that to nil so that we don't alter the outer value.  */
   record_unwind_protect (unwind_format_mode_line,
                         format_mode_line_unwind_data
-                            (old_buffer, selected_window, 1));
+                          (XFRAME (WINDOW_FRAME (w)),
+                           old_buffer, selected_window, 1));
   mode_line_proptrans_alist = Qnil;
 
   Fselect_window (window, Qt);
-  if (old_buffer)
-    set_buffer_internal_1 (XBUFFER (buffer));
+  set_buffer_internal_1 (XBUFFER (buffer));
 
   init_iterator (&it, w, -1, -1, NULL, face_id);
 
@@ -21055,7 +21317,7 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_
        }
       else if (CHARACTERP (eoltype))
        {
-         unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
+         unsigned char *tmp = alloca (MAX_MULTIBYTE_LENGTH);
          int c = XFASTINT (eoltype);
          eol_str_len = CHAR_STRING (c, tmp);
          eol_str = tmp;
@@ -21089,6 +21351,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
   Lisp_Object obj;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
+  /* We are going to use f->decode_mode_spec_buffer as the buffer to
+     produce strings from numerical values, so limit preposterously
+     large values of FIELD_WIDTH to avoid overrunning the buffer's
+     end.  The size of the buffer is enough for FRAME_MESSAGE_BUF_SIZE
+     bytes plus the terminating null.  */
+  int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
   struct buffer *b = current_buffer;
 
   obj = Qnil;
@@ -21153,8 +21421,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        register int i;
 
        /* Let lots_of_dashes be a string of infinite length.  */
-       if (mode_line_target == MODE_LINE_NOPROP ||
-           mode_line_target == MODE_LINE_STRING)
+       if (mode_line_target == MODE_LINE_NOPROP
+           || mode_line_target == MODE_LINE_STRING)
          return "--";
        if (field_width <= 0
            || field_width > sizeof (lots_of_dashes))
@@ -21183,8 +21451,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
       else
        {
          ptrdiff_t col = current_column ();
-         w->column_number_displayed = make_number (col);
-         pint2str (decode_mode_spec_buf, field_width, col);
+         wset_column_number_displayed (w, make_number (col));
+         pint2str (decode_mode_spec_buf, width, col);
          return decode_mode_spec_buf;
        }
 
@@ -21215,14 +21483,14 @@ decode_mode_spec (struct window *w, register int c, int field_width,
     case 'i':
       {
        ptrdiff_t size = ZV - BEGV;
-       pint2str (decode_mode_spec_buf, field_width, size);
+       pint2str (decode_mode_spec_buf, width, size);
        return decode_mode_spec_buf;
       }
 
     case 'I':
       {
        ptrdiff_t size = ZV - BEGV;
-       pint2hrstr (decode_mode_spec_buf, field_width, size);
+       pint2hrstr (decode_mode_spec_buf, width, size);
        return decode_mode_spec_buf;
       }
 
@@ -21236,7 +21504,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        if (mode_line_target == MODE_LINE_TITLE)
          return "";
 
-       startpos = XMARKER (w->start)->charpos;
+       startpos = marker_position (w->start);
        startpos_byte = marker_byte_position (w->start);
        height = WINDOW_TOTAL_LINES (w);
 
@@ -21246,14 +21514,14 @@ decode_mode_spec (struct window *w, register int c, int field_width,
          goto no_value;
        /* But do forget it, if the window shows a different buffer now.  */
        else if (BUFFERP (w->base_line_pos))
-         w->base_line_pos = Qnil;
+         wset_base_line_pos (w, Qnil);
 
        /* If the buffer is very big, don't waste time.  */
        if (INTEGERP (Vline_number_display_limit)
            && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
          {
-           w->base_line_pos = Qnil;
-           w->base_line_number = Qnil;
+           wset_base_line_pos (w, Qnil);
+           wset_base_line_number (w, Qnil);
            goto no_value;
          }
 
@@ -21285,8 +21553,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
           go back past it.  */
        if (startpos == BUF_BEGV (b))
          {
-           w->base_line_number = make_number (topline);
-           w->base_line_pos = make_number (BUF_BEGV (b));
+           wset_base_line_number (w, make_number (topline));
+           wset_base_line_pos (w, make_number (BUF_BEGV (b)));
          }
        else if (nlines < height + 25 || nlines > height * 3 + 50
                 || linepos == BUF_BEGV (b))
@@ -21312,13 +21580,13 @@ decode_mode_spec (struct window *w, register int c, int field_width,
               give up on line numbers for this window.  */
            if (position == limit_byte && limit == startpos - distance)
              {
-               w->base_line_pos = w->buffer;
-               w->base_line_number = Qnil;
+               wset_base_line_pos (w, w->buffer);
+               wset_base_line_number (w, Qnil);
                goto no_value;
              }
 
-           w->base_line_number = make_number (topline - nlines);
-           w->base_line_pos = make_number (BYTE_TO_CHAR (position));
+           wset_base_line_number (w, make_number (topline - nlines));
+           wset_base_line_pos (w, make_number (BYTE_TO_CHAR (position)));
          }
 
        /* Now count lines from the start pos to point.  */
@@ -21329,12 +21597,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        line_number_displayed = 1;
 
        /* Make the string to show.  */
-       pint2str (decode_mode_spec_buf, field_width, topline + nlines);
+       pint2str (decode_mode_spec_buf, width, topline + nlines);
        return decode_mode_spec_buf;
     no_value:
         {
          char* p = decode_mode_spec_buf;
-         int pad = field_width - 2;
+         int pad = width - 2;
          while (pad-- > 0)
            *p++ = ' ';
          *p++ = '?';
@@ -21470,10 +21738,10 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        obj = Fget_buffer_process (Fcurrent_buffer ());
        if (PROCESSP (obj))
          {
-           p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
-                                        p, eol_flag);
-           p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
-                                        p, eol_flag);
+           p = decode_mode_spec_coding
+             (XPROCESS (obj)->decode_coding_system, p, eol_flag);
+           p = decode_mode_spec_coding
+             (XPROCESS (obj)->encode_coding_system, p, eol_flag);
          }
 #endif /* subprocesses */
 #endif /* 0 */
@@ -21755,7 +22023,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
            {
              /* Glyph is off the left margin of the display area.
                 Should not happen.  */
-             abort ();
+             emacs_abort ();
            }
 
          row->ascent = max (row->ascent, it->max_ascent);
@@ -21832,7 +22100,10 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
   if (it->first_visible_x
       && it_charpos > 0)
     {
-      if (!FRAME_WINDOW_P (it->f))
+      if (!FRAME_WINDOW_P (it->f)
+         || (row->reversed_p
+             ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+             : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
        insert_left_trunc_glyphs (it);
       row->truncated_on_left_p = 1;
     }
@@ -21993,7 +22264,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
   if (NILP (prop))
     return OK_PIXELS (0);
 
-  xassert (FRAME_LIVE_P (it->f));
+  eassert (FRAME_LIVE_P (it->f));
 
   if (SYMBOLP (prop))
     {
@@ -22174,7 +22445,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
 
 void
 dump_glyph_string (struct glyph_string *s)
@@ -22245,7 +22516,7 @@ init_glyph_string (struct glyph_string *s,
 /* Append the list of glyph strings with head H and tail T to the list
    with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the result.  */
 
-static inline void
+static void
 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
                           struct glyph_string *h, struct glyph_string *t)
 {
@@ -22265,7 +22536,7 @@ append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tai
    list with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the
    result.  */
 
-static inline void
+static void
 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
                            struct glyph_string *h, struct glyph_string *t)
 {
@@ -22284,7 +22555,7 @@ prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **ta
 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
    Set *HEAD and *TAIL to the resulting list.  */
 
-static inline void
+static void
 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
                     struct glyph_string *s)
 {
@@ -22299,7 +22570,7 @@ append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
    Value is a pointer to a realized face that is ready for display if
    DISPLAY_P is non-zero.  */
 
-static inline struct face *
+static struct face *
 get_char_face_and_encoding (struct frame *f, int c, int face_id,
                            XChar2b *char2b, int display_p)
 {
@@ -22320,7 +22591,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
   if (display_p)
 #endif
     {
-      xassert (face != NULL);
+      eassert (face != NULL);
       PREPARE_FACE_FOR_DISPLAY (f, face);
     }
 
@@ -22332,13 +22603,13 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
    The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
    a pointer to a realized face that is ready for display.  */
 
-static inline struct face *
+static struct face *
 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
                             XChar2b *char2b, int *two_byte_p)
 {
   struct face *face;
 
-  xassert (glyph->type == CHAR_GLYPH);
+  eassert (glyph->type == CHAR_GLYPH);
   face = FACE_FROM_ID (f, glyph->face_id);
 
   if (two_byte_p)
@@ -22360,7 +22631,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
     }
 
   /* Make sure X resources of the face are allocated.  */
-  xassert (face != NULL);
+  eassert (face != NULL);
   PREPARE_FACE_FOR_DISPLAY (f, face);
   return face;
 }
@@ -22369,7 +22640,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 /* Get glyph code of character C in FONT in the two-byte form CHAR2B.
    Return 1 if FONT has a glyph for C, otherwise return 0.  */
 
-static inline int
+static int
 get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
 {
   unsigned code;
@@ -22406,7 +22677,7 @@ fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
      glyph that requires the different face, add it to S.  */
   struct face *face;
 
-  xassert (s);
+  eassert (s);
 
   s->for_overlaps = overlaps;
   s->face = NULL;
@@ -22516,13 +22787,13 @@ fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
   struct glyph *glyph, *last;
   int voffset;
 
-  xassert (s->first_glyph->type == GLYPHLESS_GLYPH);
+  eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
   s->for_overlaps = overlaps;
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   voffset = glyph->voffset;
   s->face = FACE_FROM_ID (s->f, face_id);
-  s->font = s->face->font;
+  s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
   s->nchars = 1;
   s->width = glyph->pixel_width;
   glyph++;
@@ -22557,9 +22828,9 @@ fill_glyph_string (struct glyph_string *s, int face_id,
   int voffset;
   int glyph_not_available_p;
 
-  xassert (s->f == XFRAME (s->w->frame));
-  xassert (s->nchars == 0);
-  xassert (start >= 0 && end > start);
+  eassert (s->f == XFRAME (s->w->frame));
+  eassert (s->nchars == 0);
+  eassert (start >= 0 && end > start);
 
   s->for_overlaps = overlaps;
   glyph = s->row->glyphs[s->area] + start;
@@ -22582,7 +22853,7 @@ fill_glyph_string (struct glyph_string *s, int face_id,
                                               &two_byte_p);
       s->two_byte_p = two_byte_p;
       ++s->nchars;
-      xassert (s->nchars <= end - start);
+      eassert (s->nchars <= end - start);
       s->width += glyph->pixel_width;
       if (glyph++->padding_p != s->padding_p)
        break;
@@ -22603,7 +22874,7 @@ fill_glyph_string (struct glyph_string *s, int face_id,
   /* Adjust base line for subscript/superscript text.  */
   s->ybase += voffset;
 
-  xassert (s->face && s->face->gc);
+  eassert (s->face && s->face->gc);
   return glyph - s->row->glyphs[s->area];
 }
 
@@ -22613,9 +22884,9 @@ fill_glyph_string (struct glyph_string *s, int face_id,
 static void
 fill_image_glyph_string (struct glyph_string *s)
 {
-  xassert (s->first_glyph->type == IMAGE_GLYPH);
+  eassert (s->first_glyph->type == IMAGE_GLYPH);
   s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
-  xassert (s->img);
+  eassert (s->img);
   s->slice = s->first_glyph->slice.img;
   s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
   s->font = s->face->font;
@@ -22639,7 +22910,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
   struct glyph *glyph, *last;
   int voffset, face_id;
 
-  xassert (s->first_glyph->type == STRETCH_GLYPH);
+  eassert (s->first_glyph->type == STRETCH_GLYPH);
 
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
@@ -22663,7 +22934,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
 
   /* The case that face->gc == 0 is handled when drawing the glyph
      string by calling PREPARE_FACE_FOR_DISPLAY.  */
-  xassert (s->face);
+  eassert (s->face);
   return glyph - s->row->glyphs[s->area];
 }
 
@@ -22797,7 +23068,8 @@ right_overwritten (struct glyph_string *s)
     {
       int x = 0, i;
       struct glyph *glyphs = s->row->glyphs[s->area];
-      int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+      int first = (s->first_glyph - glyphs
+                  + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
       int end = s->row->used[s->area];
 
       for (i = first; i < end && s->right_overhang > x; ++i)
@@ -22820,7 +23092,8 @@ right_overwriting (struct glyph_string *s)
   int i, k, x;
   int end = s->row->used[s->area];
   struct glyph *glyphs = s->row->glyphs[s->area];
-  int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+  int first = (s->first_glyph - glyphs
+              + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
 
   k = -1;
   x = 0;
@@ -22841,7 +23114,7 @@ right_overwriting (struct glyph_string *s)
    first glyph following S.  LAST_X is the right-most x-position + 1
    in the drawing area.  */
 
-static inline void
+static void
 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
 {
   /* If the face of this glyph string has to be drawn to the end of
@@ -22928,7 +23201,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X)   \
      do                                                                            \
        {                                                                   \
-        s = (struct glyph_string *) alloca (sizeof *s);                    \
+        s = alloca (sizeof *s);                                            \
         INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);              \
         START = fill_stretch_glyph_string (s, START, END);                 \
         append_glyph_string (&HEAD, &TAIL, s);                             \
@@ -22948,7 +23221,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
      do                                                                        \
        {                                                               \
-        s = (struct glyph_string *) alloca (sizeof *s);                \
+        s = alloca (sizeof *s);                                        \
         INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);          \
         fill_image_glyph_string (s);                                   \
         append_glyph_string (&HEAD, &TAIL, s);                         \
@@ -22975,8 +23248,8 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
                                                                           \
         face_id = (row)->glyphs[area][START].face_id;                     \
                                                                           \
-        s = (struct glyph_string *) alloca (sizeof *s);                   \
-        char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b);     \
+        s = alloca (sizeof *s);                                           \
+        char2b = alloca ((END - START) * sizeof *char2b);                 \
         INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);           \
         append_glyph_string (&HEAD, &TAIL, s);                            \
         s->x = (X);                                                       \
@@ -23004,13 +23277,13 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
     struct glyph_string *first_s = NULL;                                   \
     int n;                                                                 \
                                                                            \
-    char2b = (XChar2b *) alloca ((sizeof *char2b) * cmp->glyph_len);       \
+    char2b = alloca (cmp->glyph_len * sizeof *char2b);                     \
                                                                            \
     /* Make glyph_strings for each glyph sequence that is drawable by      \
        the same face, and append them to HEAD/TAIL.  */                            \
     for (n = 0; n < cmp->glyph_len;)                                       \
       {                                                                            \
-       s = (struct glyph_string *) alloca (sizeof *s);                     \
+       s = alloca (sizeof *s);                                             \
        INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);             \
        append_glyph_string (&(HEAD), &(TAIL), s);                          \
        s->cmp = cmp;                                                       \
@@ -23038,9 +23311,8 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
     face_id = (row)->glyphs[area][START].face_id;                        \
     gstring = (composition_gstring_from_id                               \
               ((row)->glyphs[area][START].u.cmp.id));                    \
-    s = (struct glyph_string *) alloca (sizeof *s);                      \
-    char2b = (XChar2b *) alloca ((sizeof *char2b)                        \
-                                * LGSTRING_GLYPH_LEN (gstring));         \
+    s = alloca (sizeof *s);                                              \
+    char2b = alloca (LGSTRING_GLYPH_LEN (gstring) * sizeof *char2b);     \
     INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);              \
     append_glyph_string (&(HEAD), &(TAIL), s);                           \
     s->x = (X);                                                                  \
@@ -23059,7 +23331,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
                                                                            \
       face_id = (row)->glyphs[area][START].face_id;                        \
                                                                            \
-      s = (struct glyph_string *) alloca (sizeof *s);                      \
+      s = alloca (sizeof *s);                                              \
       INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);                \
       append_glyph_string (&HEAD, &TAIL, s);                               \
       s->x = (X);                                                          \
@@ -23118,7 +23390,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
              break;                                                    \
                                                                        \
            default:                                                    \
-             abort ();                                                 \
+             emacs_abort ();                                                   \
            }                                                           \
                                                                        \
          if (s)                                                        \
@@ -23168,8 +23440,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 
   /* Let's rather be paranoid than getting a SEGV.  */
   end = min (end, row->used[area]);
-  start = max (0, start);
-  start = min (end, start);
+  start = clip_to_bounds (0, start, end);
 
   /* Translate X to frame coordinates.  Set last_x to the right
      end of the drawing area.  */
@@ -23211,7 +23482,9 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 
       /* If mouse highlighting is on, we may need to draw adjacent
         glyphs using mouse-face highlighting.  */
-      if (area == TEXT_AREA && row->mouse_face_p)
+      if (area == TEXT_AREA && row->mouse_face_p
+         && hlinfo->mouse_face_beg_row >= 0
+         && hlinfo->mouse_face_end_row >= 0)
        {
          struct glyph_row *mouse_beg_row, *mouse_end_row;
 
@@ -23403,14 +23676,14 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 /* Store one glyph for IT->char_to_display in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
 
-static inline void
+static void
 append_glyph (struct it *it)
 {
   struct glyph *glyph;
   enum glyph_row_area area = it->area;
 
-  xassert (it->glyph_row);
-  xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
+  eassert (it->glyph_row);
+  eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
 
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
@@ -23446,8 +23719,18 @@ append_glyph (struct it *it)
       glyph->type = CHAR_GLYPH;
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+       {
+         /* In R2L rows, the left and the right box edges need to be
+            drawn in reverse direction.  */
+         glyph->right_box_line_p = it->start_of_box_run_p;
+         glyph->left_box_line_p = it->end_of_box_run_p;
+       }
+      else
+       {
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+       }
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
       glyph->glyph_not_available_p = it->glyph_not_available_p;
@@ -23459,7 +23742,7 @@ append_glyph (struct it *it)
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
          if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           abort ();
+           emacs_abort ();
          glyph->bidi_type = it->bidi_it.type;
        }
       else
@@ -23477,13 +23760,13 @@ append_glyph (struct it *it)
    IT->glyph_row.  Called from x_produce_glyphs when IT->glyph_row is
    non-null.  */
 
-static inline void
+static void
 append_composite_glyph (struct it *it)
 {
   struct glyph *glyph;
   enum glyph_row_area area = it->area;
 
-  xassert (it->glyph_row);
+  eassert (it->glyph_row);
 
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
@@ -23521,8 +23804,18 @@ append_composite_glyph (struct it *it)
        }
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+       {
+         /* In R2L rows, the left and the right box edges need to be
+            drawn in reverse direction.  */
+         glyph->right_box_line_p = it->start_of_box_run_p;
+         glyph->left_box_line_p = it->end_of_box_run_p;
+       }
+      else
+       {
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+       }
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
       glyph->padding_p = 0;
@@ -23533,7 +23826,7 @@ append_composite_glyph (struct it *it)
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
          if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           abort ();
+           emacs_abort ();
          glyph->bidi_type = it->bidi_it.type;
        }
       ++it->glyph_row->used[area];
@@ -23546,7 +23839,7 @@ append_composite_glyph (struct it *it)
 /* Change IT->ascent and IT->height according to the setting of
    IT->voffset.  */
 
-static inline void
+static void
 take_vertical_position_into_account (struct it *it)
 {
   if (it->voffset)
@@ -23575,10 +23868,10 @@ produce_image_glyph (struct it *it)
   int glyph_ascent, crop;
   struct glyph_slice slice;
 
-  xassert (it->what == IT_IMAGE);
+  eassert (it->what == IT_IMAGE);
 
   face = FACE_FROM_ID (it->f, it->face_id);
-  xassert (face);
+  eassert (face);
   /* Make sure X resources of the face is loaded.  */
   PREPARE_FACE_FOR_DISPLAY (it->f, face);
 
@@ -23593,7 +23886,7 @@ produce_image_glyph (struct it *it)
     }
 
   img = IMAGE_FROM_ID (it->f, it->image_id);
-  xassert (img);
+  eassert (img);
   /* Make sure X resources of the image is loaded.  */
   prepare_image_for_display (it->f, img);
 
@@ -23699,8 +23992,18 @@ produce_image_glyph (struct it *it)
          glyph->type = IMAGE_GLYPH;
          glyph->avoid_cursor_p = it->avoid_cursor_p;
          glyph->multibyte_p = it->multibyte_p;
-         glyph->left_box_line_p = it->start_of_box_run_p;
-         glyph->right_box_line_p = it->end_of_box_run_p;
+         if (it->glyph_row->reversed_p && area == TEXT_AREA)
+           {
+             /* In R2L rows, the left and the right box edges need to be
+                drawn in reverse direction.  */
+             glyph->right_box_line_p = it->start_of_box_run_p;
+             glyph->left_box_line_p = it->end_of_box_run_p;
+           }
+         else
+           {
+             glyph->left_box_line_p = it->start_of_box_run_p;
+             glyph->right_box_line_p = it->end_of_box_run_p;
+           }
          glyph->overlaps_vertically_p = 0;
           glyph->padding_p = 0;
          glyph->glyph_not_available_p = 0;
@@ -23712,7 +24015,7 @@ produce_image_glyph (struct it *it)
            {
              glyph->resolved_level = it->bidi_it.resolved_level;
              if ((it->bidi_it.type & 7) != it->bidi_it.type)
-               abort ();
+               emacs_abort ();
              glyph->bidi_type = it->bidi_it.type;
            }
          ++it->glyph_row->used[area];
@@ -23734,7 +24037,7 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
   struct glyph *glyph;
   enum glyph_row_area area = it->area;
 
-  xassert (ascent >= 0 && ascent <= height);
+  eassert (ascent >= 0 && ascent <= height);
 
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
@@ -23759,8 +24062,18 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
       glyph->type = STRETCH_GLYPH;
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+       {
+         /* In R2L rows, the left and the right box edges need to be
+            drawn in reverse direction.  */
+         glyph->right_box_line_p = it->start_of_box_run_p;
+         glyph->left_box_line_p = it->end_of_box_run_p;
+       }
+      else
+       {
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+       }
       glyph->overlaps_vertically_p = 0;
       glyph->padding_p = 0;
       glyph->glyph_not_available_p = 0;
@@ -23773,7 +24086,7 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
          if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           abort ();
+           emacs_abort ();
          glyph->bidi_type = it->bidi_it.type;
        }
       else
@@ -23827,24 +24140,23 @@ produce_stretch_glyph (struct it *it)
   Lisp_Object prop, plist;
   int width = 0, height = 0, align_to = -1;
   int zero_width_ok_p = 0;
-  int ascent = 0;
   double tem;
-  struct face *face = NULL;
   struct font *font = NULL;
 
 #ifdef HAVE_WINDOW_SYSTEM
+  int ascent = 0;
   int zero_height_ok_p = 0;
 
   if (FRAME_WINDOW_P (it->f))
     {
-      face = FACE_FROM_ID (it->f, it->face_id);
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
       font = face->font ? face->font : FRAME_FONT (it->f);
       PREPARE_FACE_FOR_DISPLAY (it->f, face);
     }
 #endif
 
   /* List should start with `space'.  */
-  xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
+  eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
   plist = XCDR (it->object);
 
   /* Compute the width of the stretch.  */
@@ -23983,6 +24295,102 @@ produce_stretch_glyph (struct it *it)
     it->nglyphs = width;
 }
 
+/* Get information about special display element WHAT in an
+   environment described by IT.  WHAT is one of IT_TRUNCATION or
+   IT_CONTINUATION.  Maybe produce glyphs for WHAT if IT has a
+   non-null glyph_row member.  This function ensures that fields like
+   face_id, c, len of IT are left untouched.  */
+
+static void
+produce_special_glyphs (struct it *it, enum display_element_type what)
+{
+  struct it temp_it;
+  Lisp_Object gc;
+  GLYPH glyph;
+
+  temp_it = *it;
+  temp_it.object = make_number (0);
+  memset (&temp_it.current, 0, sizeof temp_it.current);
+
+  if (what == IT_CONTINUATION)
+    {
+      /* Continuation glyph.  For R2L lines, we mirror it by hand.  */
+      if (it->bidi_it.paragraph_dir == R2L)
+       SET_GLYPH_FROM_CHAR (glyph, '/');
+      else
+       SET_GLYPH_FROM_CHAR (glyph, '\\');
+      if (it->dp
+         && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
+       {
+         /* FIXME: Should we mirror GC for R2L lines?  */
+         SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
+         spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
+       }
+    }
+  else if (what == IT_TRUNCATION)
+    {
+      /* Truncation glyph.  */
+      SET_GLYPH_FROM_CHAR (glyph, '$');
+      if (it->dp
+         && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
+       {
+         /* FIXME: Should we mirror GC for R2L lines?  */
+         SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
+         spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
+       }
+    }
+  else
+    emacs_abort ();
+
+#ifdef HAVE_WINDOW_SYSTEM
+  /* On a GUI frame, when the right fringe (left fringe for R2L rows)
+     is turned off, we precede the truncation/continuation glyphs by a
+     stretch glyph whose width is computed such that these special
+     glyphs are aligned at the window margin, even when very different
+     fonts are used in different glyph rows.  */
+  if (FRAME_WINDOW_P (temp_it.f)
+      /* init_iterator calls this with it->glyph_row == NULL, and it
+        wants only the pixel width of the truncation/continuation
+        glyphs.  */
+      && temp_it.glyph_row
+      /* insert_left_trunc_glyphs calls us at the beginning of the
+        row, and it has its own calculation of the stretch glyph
+        width.  */
+      && temp_it.glyph_row->used[TEXT_AREA] > 0
+      && (temp_it.glyph_row->reversed_p
+         ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
+         : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
+    {
+      int stretch_width = temp_it.last_visible_x - temp_it.current_x;
+
+      if (stretch_width > 0)
+       {
+         struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
+         struct font *font =
+           face->font ? face->font : FRAME_FONT (temp_it.f);
+         int stretch_ascent =
+           (((temp_it.ascent + temp_it.descent)
+             * FONT_BASE (font)) / FONT_HEIGHT (font));
+
+         append_stretch_glyph (&temp_it, make_number (0), stretch_width,
+                               temp_it.ascent + temp_it.descent,
+                               stretch_ascent);
+       }
+    }
+#endif
+
+  temp_it.dp = NULL;
+  temp_it.what = IT_CHARACTER;
+  temp_it.len = 1;
+  temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
+  temp_it.face_id = GLYPH_FACE (glyph);
+  temp_it.len = CHAR_BYTES (temp_it.c);
+
+  PRODUCE_GLYPHS (&temp_it);
+  it->pixel_width = temp_it.pixel_width;
+  it->nglyphs = temp_it.pixel_width;
+}
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Calculate line-height and line-spacing properties.
@@ -24117,8 +24525,18 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
       glyph->slice.glyphless.lower_yoff = lower_yoff;
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+       {
+         /* In R2L rows, the left and the right box edges need to be
+            drawn in reverse direction.  */
+         glyph->right_box_line_p = it->start_of_box_run_p;
+         glyph->left_box_line_p = it->end_of_box_run_p;
+       }
+      else
+       {
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+       }
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
       glyph->padding_p = 0;
@@ -24129,7 +24547,7 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
          if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           abort ();
+           emacs_abort ();
          glyph->bidi_type = it->bidi_it.type;
        }
       ++it->glyph_row->used[area];
@@ -24223,7 +24641,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
        }
       else
        {
-         xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
+         eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
          sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
          str = buf;
        }
@@ -24325,7 +24743,7 @@ x_produce_glyphs (struct it *it)
             Vglyphless_char_display.  */
          Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
 
-         xassert (it->what == IT_GLYPHLESS);
+         eassert (it->what == IT_GLYPHLESS);
          produce_glyphless_glyph (it, 1, STRINGP (acronym) ? acronym : Qnil);
          goto done;
        }
@@ -24650,7 +25068,7 @@ x_produce_glyphs (struct it *it)
          font_descent = FONT_DESCENT (font) - boff;
          font_height = FONT_HEIGHT (font);
 
-         cmp->font = (void *) font;
+         cmp->font = font;
 
          pcm = NULL;
          if (! font_not_found_p)
@@ -24950,7 +25368,7 @@ x_produce_glyphs (struct it *it)
  done:
   /* Accumulate dimensions.  Note: can't assume that it->descent > 0
      because this isn't true for images with `:ascent 100'.  */
-  xassert (it->ascent >= 0 && it->descent >= 0);
+  eassert (it->ascent >= 0 && it->descent >= 0);
   if (it->area == TEXT_AREA)
     it->current_x += it->pixel_width;
 
@@ -24979,7 +25397,7 @@ x_write_glyphs (struct glyph *start, int len)
 {
   int x, hpos, chpos = updated_window->phys_cursor.hpos;
 
-  xassert (updated_window && updated_row);
+  eassert (updated_window && 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.  */
@@ -24988,7 +25406,7 @@ x_write_glyphs (struct glyph *start, int len)
   if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
     chpos = updated_row->used[TEXT_AREA] - 1;
 
-  BLOCK_INPUT;
+  block_input ();
 
   /* Write glyphs.  */
 
@@ -25006,7 +25424,7 @@ x_write_glyphs (struct glyph *start, int len)
       && chpos < hpos + len)
     updated_window->phys_cursor_on_p = 0;
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* Advance the output cursor.  */
   output_cursor.hpos += len;
@@ -25028,8 +25446,8 @@ x_insert_glyphs (struct glyph *start, int len)
   int frame_x, frame_y;
   ptrdiff_t hpos;
 
-  xassert (updated_window && updated_row);
-  BLOCK_INPUT;
+  eassert (updated_window && updated_row);
+  block_input ();
   w = updated_window;
   f = XFRAME (WINDOW_FRAME (w));
 
@@ -25063,7 +25481,7 @@ x_insert_glyphs (struct glyph *start, int len)
   /* Advance the output cursor.  */
   output_cursor.hpos += len;
   output_cursor.x += shift_by_width;
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -25083,7 +25501,7 @@ x_clear_end_of_line (int to_x)
   int max_x, min_y, max_y;
   int from_x, from_y, to_y;
 
-  xassert (updated_window && updated_row);
+  eassert (updated_window && updated_row);
   f = XFRAME (w->frame);
 
   if (updated_row->full_width_p)
@@ -25132,10 +25550,10 @@ x_clear_end_of_line (int to_x)
   /* Prevent inadvertently clearing to end of the X window.  */
   if (to_x > from_x && to_y > from_y)
     {
-      BLOCK_INPUT;
+      block_input ();
       FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
                                        to_x - from_x, to_y - from_y);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -25462,7 +25880,7 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row,
 {
   int i, x;
 
-  BLOCK_INPUT;
+  block_input ();
 
   x = 0;
   for (i = 0; i < row->used[area];)
@@ -25490,7 +25908,7 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row,
        }
     }
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -25708,7 +26126,7 @@ display_and_set_cursor (struct window *w, int on,
       || (0 <= hpos && hpos < glyph_row->used[TEXT_AREA]))
     glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
 
-  xassert (interrupt_input_blocked);
+  eassert (input_blocked_p ());
 
   /* Set new_cursor_type to the cursor we want to be displayed.  */
   new_cursor_type = get_window_cursor_type (w, glyph,
@@ -25778,10 +26196,10 @@ update_window_cursor (struct window *w, int on)
       if (row->reversed_p && hpos >= row->used[TEXT_AREA])
        hpos = row->used[TEXT_AREA] - 1;
 
-      BLOCK_INPUT;
+      block_input ();
       display_and_set_cursor (w, on, hpos, vpos,
                              w->phys_cursor.x, w->phys_cursor.y);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -25959,10 +26377,10 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
          if (row->reversed_p && hpos >= row->used[TEXT_AREA])
            hpos = row->used[TEXT_AREA] - 1;
 
-         BLOCK_INPUT;
+         block_input ();
          display_and_set_cursor (w, 1, hpos, w->phys_cursor.vpos,
                                  w->phys_cursor.x, w->phys_cursor.y);
-         UNBLOCK_INPUT;
+         unblock_input ();
        }
 #endif /* HAVE_WINDOW_SYSTEM */
     }
@@ -26255,9 +26673,9 @@ mouse_face_from_buffer_pos (Lisp_Object window,
   ptrdiff_t ignore, pos;
   int x;
 
-  xassert (NILP (disp_string) || STRINGP (disp_string));
-  xassert (NILP (before_string) || STRINGP (before_string));
-  xassert (NILP (after_string) || STRINGP (after_string));
+  eassert (NILP (disp_string) || STRINGP (disp_string));
+  eassert (NILP (before_string) || STRINGP (before_string));
+  eassert (NILP (after_string) || STRINGP (after_string));
 
   /* Find the rows corresponding to START_CHARPOS and END_CHARPOS.  */
   rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
@@ -27295,12 +27713,6 @@ note_mouse_highlight (struct frame *f, int x, int y)
   if (hlinfo->mouse_face_defer)
     return;
 
-  if (gc_in_progress)
-    {
-      hlinfo->mouse_face_deferred_gc = 1;
-      return;
-    }
-
   /* Which window is that in?  */
   window = window_from_coordinates (f, x, y, &part, 1);
 
@@ -27361,8 +27773,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
   b = XBUFFER (w->buffer);
   if (part == ON_TEXT
       && EQ (w->window_end_valid, w->buffer)
-      && XFASTINT (w->last_modified) == BUF_MODIFF (b)
-      && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
+      && w->last_modified == BUF_MODIFF (b)
+      && w->last_overlay_modified == BUF_OVERLAY_MODIFF (b))
     {
       int hpos, vpos, dx, dy, area = LAST_AREA;
       ptrdiff_t pos;
@@ -27777,11 +28189,11 @@ x_clear_window_mouse_face (struct window *w)
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
   Lisp_Object window;
 
-  BLOCK_INPUT;
+  block_input ();
   XSETWINDOW (window, w);
   if (EQ (window, hlinfo->mouse_face_window))
     clear_mouse_face (hlinfo);
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -27873,7 +28285,7 @@ expose_area (struct window *w, struct glyph_row *row, XRectangle *r,
 static int
 expose_line (struct window *w, struct glyph_row *row, XRectangle *r)
 {
-  xassert (row->enabled_p);
+  eassert (row->enabled_p);
 
   if (row->mode_line_p || w->pseudo_window_p)
     draw_glyphs (w, 0, row, TEXT_AREA,
@@ -27913,7 +28325,7 @@ expose_overlaps (struct window *w,
   for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
     if (row->overlapping_p)
       {
-       xassert (row->enabled_p && !row->mode_line_p);
+       eassert (row->enabled_p && !row->mode_line_p);
 
        row->clip = r;
        if (row->used[LEFT_MARGIN_AREA])
@@ -28351,6 +28763,7 @@ syms_of_xdisp (void)
   staticpro (&Vmessage_stack);
 
   DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
+  DEFSYM (Qredisplay_internal, "redisplay_internal (C function)");
 
   message_dolog_marker1 = Fmake_marker ();
   staticpro (&message_dolog_marker1);
@@ -28359,7 +28772,7 @@ syms_of_xdisp (void)
   message_dolog_marker3 = Fmake_marker ();
   staticpro (&message_dolog_marker3);
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   defsubr (&Sdump_frame_glyph_matrix);
   defsubr (&Sdump_glyph_matrix);
   defsubr (&Sdump_glyph_row);
@@ -28449,7 +28862,7 @@ syms_of_xdisp (void)
   staticpro (&echo_area_buffer[0]);
   staticpro (&echo_area_buffer[1]);
 
-  Vmessages_buffer_name = make_pure_c_string ("*Messages*");
+  Vmessages_buffer_name = build_pure_c_string ("*Messages*");
   staticpro (&Vmessages_buffer_name);
 
   mode_line_proptrans_alist = Qnil;
@@ -28530,7 +28943,7 @@ See also `overlay-arrow-string'.  */);
   DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
     doc: /* String to display as an arrow in non-window frames.
 See also `overlay-arrow-position'.  */);
-  Voverlay_arrow_string = make_pure_c_string ("=>");
+  Voverlay_arrow_string = build_pure_c_string ("=>");
 
   DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
     doc: /* List of variables (symbols) which hold markers for overlay arrows.
@@ -28571,7 +28984,7 @@ of the top or bottom of the window.  */);
 Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI).  */);
   Vdisplay_pixels_per_inch = make_float (72.0);
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: /* Don't ask.  */);
 #endif
 
@@ -28590,12 +29003,6 @@ A value of nil means to respect the value of `truncate-lines'.
 If `word-wrap' is enabled, you might want to reduce this.  */);
   Vtruncate_partial_width_windows = make_number (50);
 
-  DEFVAR_BOOL ("mode-line-inverse-video", mode_line_inverse_video,
-    doc: /* When nil, display the mode-line/header-line/menu-bar in the default face.
-Any other value means to use the appropriate face, `mode-line',
-`header-line', or `menu' respectively.  */);
-  mode_line_inverse_video = 1;
-
   DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
     doc: /* Maximum buffer size for which line number should be displayed.
 If the buffer is bigger than this, the line number does not appear
@@ -28635,20 +29042,20 @@ and is used only on frames for which no explicit name has been set
 \(see `modify-frame-parameters').  */);
   Vicon_title_format
     = Vframe_title_format
-    = pure_cons (intern_c_string ("multiple-frames"),
-                pure_cons (make_pure_c_string ("%b"),
-                           pure_cons (pure_cons (empty_unibyte_string,
-                                                 pure_cons (intern_c_string ("invocation-name"),
-                                                            pure_cons (make_pure_c_string ("@"),
-                                                                       pure_cons (intern_c_string ("system-name"),
-                                                                                  Qnil)))),
-                                      Qnil)));
+    = listn (CONSTYPE_PURE, 3,
+            intern_c_string ("multiple-frames"),
+            build_pure_c_string ("%b"),
+            listn (CONSTYPE_PURE, 4,
+                   empty_unibyte_string,
+                   intern_c_string ("invocation-name"),
+                   build_pure_c_string ("@"),
+                   intern_c_string ("system-name")));
 
   DEFVAR_LISP ("message-log-max", Vmessage_log_max,
     doc: /* Maximum number of lines to keep in the message log buffer.
 If nil, disable message logging.  If t, log messages but don't truncate
 the buffer when it becomes large.  */);
-  Vmessage_log_max = make_number (100);
+  Vmessage_log_max = make_number (1000);
 
   DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
     doc: /* Functions called before redisplay, if window sizes have changed.
@@ -28888,7 +29295,7 @@ To add a prefix to continuation lines, use `wrap-prefix'.  */);
     doc: /* Non-nil means don't free realized faces.  Internal use only.  */);
   inhibit_free_realized_faces = 0;
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
               doc: /* Inhibit try_window_id display optimization.  */);
   inhibit_try_window_id = 0;
@@ -28962,6 +29369,10 @@ Its value should be an ASCII acronym string, `hex-code', `empty-box', or
   Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
   Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),
                              Qempty_box);
+
+  DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
+              doc: /* If non-nil, debug if a message matching this regexp is displayed.  */);
+  Vdebug_on_message = Qnil;
 }
 
 
@@ -28985,12 +29396,13 @@ init_xdisp (void)
 
       echo_area_window = minibuf_window;
 
-      XSETFASTINT (r->top_line, FRAME_TOP_MARGIN (f));
-      XSETFASTINT (r->total_lines, FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f));
-      XSETFASTINT (r->total_cols, FRAME_COLS (f));
-      XSETFASTINT (m->top_line, FRAME_LINES (f) - 1);
-      XSETFASTINT (m->total_lines, 1);
-      XSETFASTINT (m->total_cols, FRAME_COLS (f));
+      wset_top_line (r, make_number (FRAME_TOP_MARGIN (f)));
+      wset_total_lines
+       (r, make_number (FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f)));
+      wset_total_cols (r, make_number (FRAME_COLS (f)));
+      wset_top_line (m, make_number (FRAME_LINES (f) - 1));
+      wset_total_lines (m, make_number (1));
+      wset_total_cols (m, make_number (FRAME_COLS (f)));
 
       scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
       scratch_glyph_row.glyphs[TEXT_AREA + 1]
@@ -29005,7 +29417,7 @@ init_xdisp (void)
     /* Allocate the buffer for frame titles.
        Also used for `format-mode-line'.  */
     int size = 100;
-    mode_line_noprop_buf = (char *) xmalloc (size);
+    mode_line_noprop_buf = xmalloc (size);
     mode_line_noprop_buf_end = mode_line_noprop_buf + size;
     mode_line_noprop_ptr = mode_line_noprop_buf;
     mode_line_target = MODE_LINE_DISPLAY;
@@ -29014,11 +29426,7 @@ init_xdisp (void)
   help_echo_showing_p = 0;
 }
 
-/* Since w32 does not support atimers, it defines its own implementation of
-   the following three functions in w32fns.c.  */
-#ifndef WINDOWSNT
-
-/* Platform-independent portion of hourglass implementation. */
+/* Platform-independent portion of hourglass implementation.  */
 
 /* Cancel a currently active hourglass timer, and start a new one.  */
 void
@@ -29026,18 +29434,27 @@ start_hourglass (void)
 {
 #if defined (HAVE_WINDOW_SYSTEM)
   EMACS_TIME delay;
-  int secs = DEFAULT_HOURGLASS_DELAY, usecs = 0;
 
   cancel_hourglass ();
 
-  if (NUMBERP (Vhourglass_delay))
-    {
-      double duration = extract_float (Vhourglass_delay);
-      if (0 < duration)
-       duration_to_sec_usec (duration, &secs, &usecs);
-    }
+  if (INTEGERP (Vhourglass_delay)
+      && XINT (Vhourglass_delay) > 0)
+    delay = make_emacs_time (min (XINT (Vhourglass_delay),
+                                 TYPE_MAXIMUM (time_t)),
+                            0);
+  else if (FLOATP (Vhourglass_delay)
+          && XFLOAT_DATA (Vhourglass_delay) > 0)
+    delay = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (Vhourglass_delay));
+  else
+    delay = make_emacs_time (DEFAULT_HOURGLASS_DELAY, 0);
+
+#ifdef HAVE_NTGUI
+  {
+    extern void w32_note_current_window (void);
+    w32_note_current_window ();
+  }
+#endif /* HAVE_NTGUI */
 
-  EMACS_SET_SECS_USECS (delay, secs, usecs);
   hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
                                   show_hourglass, NULL);
 #endif
@@ -29060,4 +29477,3 @@ cancel_hourglass (void)
     hide_hourglass ();
 #endif
 }
-#endif /* ! WINDOWSNT  */