]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Auto-generate EXFUN using make-docfile
[gnu-emacs] / src / xdisp.c
index c3403031650dc61668ce43479b57738ee9b4a3c4..ae06355ac605f8334f5af8205be1029fab003f86 100644 (file)
@@ -1,6 +1,6 @@
 /* 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-2012 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -281,8 +281,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #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"
@@ -383,11 +383,21 @@ static Lisp_Object Qline_height;
 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) 0
 #endif /* HAVE_WINDOW_SYSTEM */
 
-/* Test if the display element loaded in IT is a space or tab
-   character.  This is used to determine word wrapping.  */
-
-#define IT_DISPLAYING_WHITESPACE(it)                           \
-  (it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t'))
+/* Test if the display element loaded in IT, or the underlying buffer
+   or string character, is a space or a TAB character.  This is used
+   to determine where word wrapping can occur.  */
+
+#define IT_DISPLAYING_WHITESPACE(it)                                   \
+  ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t'))       \
+   || ((STRINGP (it->string)                                           \
+       && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' '           \
+           || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t'))     \
+       || (it->s                                                       \
+          && (it->s[IT_BYTEPOS (*it)] == ' '                           \
+              || it->s[IT_BYTEPOS (*it)] == '\t'))                     \
+       || (IT_BYTEPOS (*it) < ZV_BYTE                                  \
+          && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' '                 \
+              || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))         \
 
 /* Name of the face used to highlight trailing whitespace.  */
 
@@ -617,10 +627,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;
 
@@ -741,6 +751,7 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 int redisplaying_p;
 
 static Lisp_Object Qinhibit_free_realized_faces;
+static Lisp_Object Qmode_line_default_help_echo;
 
 /* If a string, XTread_socket generates an event to display that string.
    (The display is done in read_char.)  */
@@ -839,6 +850,7 @@ static int try_cursor_movement (Lisp_Object, struct text_pos, int *);
 static int trailing_whitespace_p (ptrdiff_t);
 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
 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);
@@ -1013,7 +1025,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
@@ -1265,6 +1277,11 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
     }
 
   SET_TEXT_POS_FROM_MARKER (top, w->start);
+  /* Scrolling a minibuffer window via scroll bar when the echo area
+     shows long text sometimes resets the minibuffer contents behind
+     our backs.  */
+  if (CHARPOS (top) > ZV)
+    SET_TEXT_POS (top, BEGV, BEGV_BYTE);
 
   /* Compute exact mode line heights.  */
   if (WINDOW_WANTS_MODELINE_P (w))
@@ -1298,8 +1315,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
         glyph.  */
       int top_x = it.current_x;
       int top_y = it.current_y;
-      enum it_method it_method = it.method;
       /* Calling line_bottom_y may change it.method, it.position, etc.  */
+      enum it_method it_method = it.method;
       int bottom_y = (last_height = 0, line_bottom_y (&it));
       int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
 
@@ -1307,6 +1324,31 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
        visible_p = bottom_y > window_top_y;
       else if (top_y < it.last_visible_y)
        visible_p = 1;
+      if (bottom_y >= it.last_visible_y
+         && it.bidi_p && it.bidi_it.scan_dir == -1
+         && IT_CHARPOS (it) < charpos)
+       {
+         /* When the last line of the window is scanned backwards
+            under bidi iteration, we could be duped into thinking
+            that we have passed CHARPOS, when in fact move_it_to
+            simply stopped short of CHARPOS because it reached
+            last_visible_y.  To see if that's what happened, we call
+            move_it_to again with a slightly larger vertical limit,
+            and see if it actually moved vertically; if it did, we
+            didn't really reach CHARPOS, which is beyond window end.  */
+         struct it save_it = it;
+         /* Why 10? because we don't know how many canonical lines
+            will the height of the next line(s) be.  So we guess.  */
+         int ten_more_lines =
+           10 * FRAME_LINE_HEIGHT (XFRAME (WINDOW_FRAME (w)));
+
+         move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
+                     MOVE_TO_POS | MOVE_TO_Y);
+         if (it.current_y > top_y)
+           visible_p = 0;
+
+         it = save_it;
+       }
       if (visible_p)
        {
          if (it_method == GET_FROM_DISPLAY_VECTOR)
@@ -1370,6 +1412,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                  Lisp_Object startpos, endpos;
                  EMACS_INT start, end;
                  struct it it3;
+                 int it3_moved;
 
                  /* Find the first and the last buffer positions
                     covered by the display string.  */
@@ -1426,6 +1469,15 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                     begins.  */
                  start_display (&it3, w, top);
                  move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
+                 /* If it3_moved stays zero after the 'while' loop
+                    below, that means we already were at a newline
+                    before the loop (e.g., the display string begins
+                    with a newline), so we don't need to (and cannot)
+                    inspect the glyphs of it3.glyph_row, because
+                    PRODUCE_GLYPHS will not produce anything for a
+                    newline, and thus it3.glyph_row stays at its
+                    stale content it got at top of the window.  */
+                 it3_moved = 0;
                  /* Finally, advance the iterator until we hit the
                     first display element whose character position is
                     CHARPOS, or until the first newline from the
@@ -1437,6 +1489,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                      if (IT_CHARPOS (it3) == charpos
                          || ITERATOR_AT_END_OF_LINE_P (&it3))
                        break;
+                     it3_moved = 1;
                      set_iterator_to_next (&it3, 0);
                    }
                  top_x = it3.current_x - it3.pixel_width;
@@ -1447,7 +1500,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                     display string, move back over the glyphs
                     produced from the string, until we find the
                     rightmost glyph not from the string.  */
-                 if (IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
+                 if (it3_moved
+                     && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
                    {
                      struct glyph *g = it3.glyph_row->glyphs[TEXT_AREA]
                                        + it3.glyph_row->used[TEXT_AREA];
@@ -1457,7 +1511,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]);
                    }
                }
@@ -1508,8 +1562,8 @@ 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 -= w->hscroll * WINDOW_FRAME_COLUMN_WIDTH (w);
 
 #if 0
   /* Debugging code.  */
@@ -1552,7 +1606,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))
     {
@@ -1581,8 +1635,8 @@ static inline 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;
 }
@@ -1597,8 +1651,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)
     {
@@ -1654,8 +1708,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,
@@ -2413,23 +2467,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))
@@ -2441,7 +2495,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.  */
@@ -2453,7 +2507,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)
@@ -2467,7 +2521,7 @@ check_window_end (struct window *w)
 
 #define CHECK_WINDOW_END(W)    (void) 0
 
-#endif
+#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
 
 
 \f
@@ -2503,8 +2557,8 @@ init_iterator (struct it *it, struct window *w,
   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,
@@ -2643,7 +2697,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))
@@ -2665,14 +2719,14 @@ init_iterator (struct it *it, struct window *w,
       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;
        }
@@ -2706,7 +2760,7 @@ init_iterator (struct it *it, struct window *w,
   else
     {
       it->first_visible_x
-       = XFASTINT (it->w->hscroll) * FRAME_COLUMN_WIDTH (it->f);
+       = it->w->hscroll * FRAME_COLUMN_WIDTH (it->f);
       it->last_visible_x = (it->first_visible_x
                            + window_box_width (w, TEXT_AREA));
 
@@ -3002,7 +3056,7 @@ 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;
     }
@@ -3013,7 +3067,7 @@ 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));
     }
 
   /* Restore position in display vector translations, control
@@ -3022,7 +3076,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;
     }
 
@@ -3111,7 +3165,15 @@ handle_stop (struct it *it)
                 overlays even if the actual buffer text is replaced.  */
              if (!handle_overlay_change_p
                  || it->sp > 1
-                 || !get_overlay_strings_1 (it, 0, 0))
+                 /* Don't call get_overlay_strings_1 if we already
+                    have overlay strings loaded, because doing so
+                    will load them again and push the iterator state
+                    onto the stack one more time, which is not
+                    expected by the rest of the code that processes
+                    overlay strings.  */
+                 || (it->current.overlay_string_index < 0
+                     ? !get_overlay_strings_1 (it, 0, 0)
+                     : 0))
                {
                  if (it->ellipsis_p)
                    setup_for_ellipsis (it, 0);
@@ -3280,7 +3342,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)));
 }
@@ -3496,7 +3558,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);
@@ -3629,7 +3691,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
@@ -3643,7 +3706,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;
 
@@ -3676,7 +3740,9 @@ handle_face_prop (struct it *it)
             with, so that overlay strings appear in the same face as
             surrounding text, unless they specify their own
             faces.  */
-         base_face_id = underlying_face_id (it);
+         base_face_id = it->string_from_prefix_prop_p
+           ? DEFAULT_FACE_ID
+           : underlying_face_id (it);
        }
 
       new_face_id = face_at_string_position (it->w,
@@ -3724,7 +3790,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))
@@ -3747,7 +3813,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))
     {
@@ -3813,7 +3879,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);
@@ -3913,7 +3979,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,
@@ -4665,10 +4731,22 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          if (!FRAME_WINDOW_P (it->f))
            /* If we return here, POSITION has been advanced
               across the text with this property.  */
-           return 0;
+           {
+             /* Synchronize the bidi iterator with POSITION.  This is
+                needed because we are not going to push the iterator
+                on behalf of this display property, so there will be
+                no pop_it call to do this synchronization for us.  */
+             if (it->bidi_p)
+               {
+                 it->position = *position;
+                 iterate_out_of_display_property (it);
+                 *position = it->position;
+               }
+             return 1;
+           }
        }
       else if (!frame_window_p)
-       return 0;
+       return 1;
 
 #ifdef HAVE_WINDOW_SYSTEM
       value = XCAR (XCDR (spec));
@@ -4676,7 +4754,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          || !(fringe_bitmap = lookup_fringe_bitmap (value)))
        /* If we return here, POSITION has been advanced
           across the text with this property.  */
-       return 0;
+       {
+         if (it && it->bidi_p)
+           {
+             it->position = *position;
+             iterate_out_of_display_property (it);
+             *position = it->position;
+           }
+         return 1;
+       }
 
       if (it)
        {
@@ -4980,7 +5066,7 @@ string_buffer_position_lim (Lisp_Object string,
   Lisp_Object limit, prop, pos;
   int found = 0;
 
-  pos = make_number (from);
+  pos = make_number (max (from, BEGV));
 
   if (!back_p) /* looking forward */
     {
@@ -5151,7 +5237,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
@@ -5332,7 +5418,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));
 
@@ -5372,7 +5458,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));
 
@@ -5460,11 +5546,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
@@ -5484,7 +5570,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;
@@ -5550,14 +5636,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;
@@ -5584,6 +5670,7 @@ push_it (struct it *it, struct text_pos *position)
   p->font_height = it->font_height;
   p->voffset = it->voffset;
   p->string_from_display_prop_p = it->string_from_display_prop_p;
+  p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
   p->display_ellipsis_p = 0;
   p->line_wrap = it->line_wrap;
   p->bidi_p = it->bidi_p;
@@ -5599,11 +5686,11 @@ push_it (struct it *it, struct text_pos *position)
 static void
 iterate_out_of_display_property (struct it *it)
 {
-  int buffer_p = BUFFERP (it->object);
+  int buffer_p = !STRINGP (it->string);
   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
@@ -5642,7 +5729,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;
@@ -5693,6 +5780,7 @@ pop_it (struct it *it)
   it->font_height = p->font_height;
   it->voffset = p->voffset;
   it->string_from_display_prop_p = p->string_from_display_prop_p;
+  it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
   it->line_wrap = p->line_wrap;
   it->bidi_p = p->bidi_p;
   it->paragraph_embedding = p->paragraph_embedding;
@@ -5711,7 +5799,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)
@@ -5808,7 +5896,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
@@ -5947,8 +6035,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);
 }
@@ -5990,7 +6078,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);
@@ -6104,10 +6192,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;
@@ -6123,6 +6211,8 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
   it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
   it->sp = 0;
   it->string_from_display_prop_p = 0;
+  it->string_from_prefix_prop_p = 0;
+
   it->from_disp_prop_p = 0;
   it->face_before_selective_p = 0;
   if (it->bidi_p)
@@ -6178,7 +6268,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.  */
@@ -6195,7 +6285,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);
@@ -6438,7 +6528,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);
@@ -6763,6 +6853,16 @@ get_next_display_element (struct it *it)
               && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX);
        }
     }
+  /* If we reached the end of the object we've been iterating (e.g., a
+     display string or an overlay string), and there's something on
+     IT->stack, proceed with what's on the stack.  It doesn't make
+     sense to return zero if there's unprocessed stuff on the stack,
+     because otherwise that stuff will never be displayed.  */
+  if (!success_p && it->sp > 0)
+    {
+      set_iterator_to_next (it, 0);
+      success_p = get_next_display_element (it);
+    }
 
   /* Value is 0 if end of buffer or string reached.  */
   return success_p;
@@ -6881,7 +6981,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
        }
       else
        {
-         xassert (it->len != 0);
+         eassert (it->len != 0);
 
          if (!it->bidi_p)
            {
@@ -6909,7 +7009,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;
 
@@ -6944,7 +7044,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
          display vector entry (these entries may contain faces).  */
       it->face_id = it->saved_face_id;
 
-      if (it->dpvec + it->current.dpvec_index == it->dpend)
+      if (it->dpvec + it->current.dpvec_index >= it->dpend)
        {
          int recheck_faces = it->ellipsis_p;
 
@@ -6981,7 +7081,27 @@ 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
+        already exhausted, and all we want is pop the iterator
+        stack.  */
+      if (it->current.overlay_string_index >= 0)
+       {
+         /* This is an overlay string, so there's no padding with
+            spaces, and the number of characters in the string is
+            where the string ends.  */
+         if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
+           goto consider_string_end;
+       }
+      else
+       {
+         /* Not an overlay string.  There could be padding, so test
+            against it->end_charpos . */
+         if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
+           goto consider_string_end;
+       }
       if (it->cmp_it.id >= 0)
        {
          int i;
@@ -7110,7 +7230,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;
@@ -7121,7 +7241,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
       abort ();
     }
 
-  xassert (it->method != GET_FROM_STRING
+  eassert (it->method != GET_FROM_STRING
           || (STRINGP (it->string)
               && IT_STRING_CHARPOS (*it) >= 0));
 }
@@ -7141,7 +7261,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;
 
@@ -7259,7 +7379,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;
@@ -7289,9 +7409,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
@@ -7368,7 +7488,7 @@ next_element_from_string (struct it *it)
   if (it->current.overlay_string_index >= 0)
     {
       /* Get the next character from an overlay string.  In overlay
-        strings, There is no field width or padding with spaces to
+        strings, there is no field width or padding with spaces to
         do.  */
       if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
        {
@@ -7455,8 +7575,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;
@@ -7561,8 +7681,8 @@ 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
     {
@@ -7607,7 +7727,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
     {
@@ -7646,9 +7766,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));
 
@@ -7807,7 +7927,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;
 }
 
@@ -7821,7 +7941,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;
@@ -8236,9 +8356,9 @@ 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
-                            display line.*/
+                            On text terminals, newlines may overflow
+                            into the last glyph on the display
+                            line.*/
                          if (!FRAME_WINDOW_P (it->f)
                              || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                            {
@@ -8314,7 +8434,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;
        }
@@ -8588,8 +8708,18 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
                {
                  /* If TO_Y is in this line and TO_X was reached
                     above, we scanned too far.  We have to restore
-                    IT's settings to the ones before skipping.  */
+                    IT's settings to the ones before skipping.  But
+                    keep the more accurate values of max_ascent and
+                    max_descent we've found while skipping the rest
+                    of the line, for the sake of callers, such as
+                    pos_visible_p, that need to know the line
+                    height.  */
+                 int max_ascent = it->max_ascent;
+                 int max_descent = it->max_descent;
+
                  RESTORE_IT (it, &it_backup, backup_data);
+                 it->max_ascent = max_ascent;
+                 it->max_descent = max_descent;
                  reached = 6;
                }
              else
@@ -8754,7 +8884,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);
 
@@ -8797,11 +8927,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;
@@ -8966,7 +9096,6 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
     {
       /* DVPOS == 0 means move to the start of the screen line.  */
       move_it_vertically_backward (it, 0);
-      xassert (it->current_x == 0 && it->hpos == 0);
       /* Let next call to line_bottom_y calculate real line height */
       last_height = 0;
     }
@@ -8974,7 +9103,20 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
     {
       move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
       if (!IT_POS_VALID_AFTER_MOVE_P (it))
-       move_it_to (it, IT_CHARPOS (*it) + 1, -1, -1, -1, MOVE_TO_POS);
+       {
+         /* Only move to the next buffer position if we ended up in a
+            string from display property, not in an overlay string
+            (before-string or after-string).  That is because the
+            latter don't conceal the underlying buffer position, so
+            we can ask to move the iterator to the exact position we
+            are interested in.  Note that, even if we are already at
+            IT_CHARPOS (*it), the call below is not a no-op, as it
+            will detect that we are at the end of the string, pop the
+            iterator, and compute it->current_x and it->hpos
+            correctly.  */
+         move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
+                     -1, -1, -1, MOVE_TO_POS);
+       }
     }
   else
     {
@@ -9223,12 +9365,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);
                    }
@@ -9625,7 +9765,7 @@ vmessage (const char *m, va_list ap)
              len = doprnt (FRAME_MESSAGE_BUF (f),
                            FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap);
 
-             message2 (FRAME_MESSAGE_BUF (f), len, 0);
+             message2 (FRAME_MESSAGE_BUF (f), len, 1);
            }
          else
            message1 (0);
@@ -9802,13 +9942,13 @@ with_echo_area_buffer (struct window *w, int which,
   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;
@@ -9850,7 +9990,7 @@ with_echo_area_buffer_unwind_data (struct window *w)
        ASET (vector, i, Qnil);
     }
 
-  xassert (i == ASIZE (vector));
+  eassert (i == ASIZE (vector));
   return vector;
 }
 
@@ -10089,7 +10229,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,
@@ -10280,7 +10420,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));
@@ -10303,7 +10443,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);
 }
 
@@ -10679,7 +10819,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)
 {
@@ -10691,7 +10832,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)));
@@ -10706,6 +10847,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;
 }
@@ -10713,6 +10863,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);
@@ -10721,9 +10875,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)))
     {
@@ -10839,7 +11010,7 @@ 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));
@@ -10868,8 +11039,6 @@ x_consider_frame_title (Lisp_Object frame)
 
 #endif /* not HAVE_WINDOW_SYSTEM */
 
-
-
 \f
 /***********************************************************************
                              Menu Bars
@@ -11030,7 +11199,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
          || update_mode_lines
          || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
               < BUF_MODIFF (XBUFFER (w->buffer)))
-             != !NILP (w->last_had_star))
+             != w->last_had_star)
          || ((!NILP (Vtransient_mark_mode)
               && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
              != !NILP (w->region_showing)))
@@ -11082,11 +11251,11 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
          else
            /* On a terminal screen, the menu bar is an ordinary screen
               line, and this makes it get updated.  */
-           w->update_mode_line = Qt;
+           w->update_mode_line = 1;
 #else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
          /* In the non-toolkit version, the menu bar is an ordinary screen
             line, and this makes it get updated.  */
-         w->update_mode_line = Qt;
+         w->update_mode_line = 1;
 #endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
 
          unbind_to (count, Qnil);
@@ -11224,11 +11393,11 @@ update_tool_bar (struct frame *f, int save_match_data)
         the rest of the redisplay algorithm is about the same as
         windows_or_buffers_changed anyway.  */
       if (windows_or_buffers_changed
-         || !NILP (w->update_mode_line)
+         || w->update_mode_line
          || update_mode_lines
          || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
               < BUF_MODIFF (XBUFFER (w->buffer)))
-             != !NILP (w->last_had_star))
+             != w->last_had_star)
          || ((!NILP (Vtransient_mark_mode)
               && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
              != !NILP (w->region_showing)))
@@ -11279,7 +11448,7 @@ update_tool_bar (struct frame *f, int save_match_data)
               BLOCK_INPUT;
               f->tool_bar_items = new_tool_bar;
               f->n_tool_bar_items = new_n_tool_bar;
-              w->update_mode_line = Qt;
+              w->update_mode_line = 1;
               UNBLOCK_INPUT;
             }
 
@@ -11353,7 +11522,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
@@ -12140,7 +12309,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
@@ -12158,7 +12327,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;
@@ -12219,15 +12388,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;
                }
            }
@@ -12266,7 +12435,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.  */
 
@@ -12339,8 +12508,8 @@ text_outside_line_unchanged_p (struct window *w,
   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 (w->last_modified < MODIFF
+      || w->last_overlay_modified < OVERLAY_MODIFF)
     {
       /* Gap in the line?  */
       if (GPT < start || Z - GPT < end)
@@ -12619,9 +12788,9 @@ 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;
     }
@@ -12639,7 +12808,7 @@ select_frame_for_redisplay (Lisp_Object frame)
   Lisp_Object old = selected_frame;
   struct Lisp_Symbol *sym;
 
-  xassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
+  eassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
 
   selected_frame = frame;
 
@@ -12689,6 +12858,9 @@ redisplay_internal (void)
      frames.  Zero means, only selected_window is considered.  */
   int consider_all_windows_p;
 
+  /* Non-zero means redisplay has to redisplay the miniwindow */
+  int update_miniwindow_p = 0;
+
   TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
 
   /* No redisplay if running in batch mode or frame is not yet fully
@@ -12825,9 +12997,9 @@ redisplay_internal (void)
     update_mode_lines++;
 
   /* Detect case that we need to write or remove a star in the mode line.  */
-  if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
+  if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
     {
-      w->update_mode_line = Qt;
+      w->update_mode_line = 1;
       if (buffer_shared > 1)
        update_mode_lines++;
     }
@@ -12840,11 +13012,11 @@ redisplay_internal (void)
   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)
+      && !(PT == w->last_point
+          && w->last_modified >= MODIFF
+          && w->last_overlay_modified >= OVERLAY_MODIFF)
       && (XFASTINT (w->column_number_displayed) != current_column ()))
-    w->update_mode_line = Qt;
+    w->update_mode_line = 1;
 
   unbind_to (count1, Qnil);
 
@@ -12875,6 +13047,10 @@ redisplay_internal (void)
          && !MINI_WINDOW_P (XWINDOW (selected_window))))
     {
       int window_height_changed_p = echo_area_display (0);
+
+      if (message_cleared_p)
+       update_miniwindow_p = 1;
+
       must_finish = 1;
 
       /* If we don't display the current message, don't clear the
@@ -12901,8 +13077,8 @@ redisplay_internal (void)
     }
   else if (EQ (selected_window, minibuf_window)
           && (current_buffer->clip_changed
-              || XFASTINT (w->last_modified) < MODIFF
-              || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
+              || w->last_modified < MODIFF
+              || w->last_overlay_modified < OVERLAY_MODIFF)
           && resize_mini_window (w, 0))
     {
       /* Resized active mini-window to fit the size of what it is
@@ -12911,7 +13087,7 @@ redisplay_internal (void)
 /* 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_frames.  */
       consider_all_windows_p = 1;
       ++windows_or_buffers_changed;
       ++update_mode_lines;
@@ -12943,7 +13119,7 @@ redisplay_internal (void)
   tlendpos = this_line_end_pos;
   if (!consider_all_windows_p
       && CHARPOS (tlbufpos) > 0
-      && NILP (w->update_mode_line)
+      && !w->update_mode_line
       && !current_buffer->clip_changed
       && !current_buffer->prevent_redisplay_optimizations_p
       && FRAME_VISIBLE_P (XFRAME (w->frame))
@@ -12951,8 +13127,8 @@ redisplay_internal (void)
       /* Make sure recorded data applies to current buffer, etc.  */
       && this_line_buffer == current_buffer
       && current_buffer == XBUFFER (w->buffer)
-      && NILP (w->force_start)
-      && NILP (w->optional_new_start)
+      && !w->force_start
+      && !w->optional_new_start
       /* Point must be on the line that we have info recorded about.  */
       && PT >= CHARPOS (tlbufpos)
       && PT <= Z - CHARPOS (tlendpos)
@@ -12967,8 +13143,8 @@ 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
+      else if (w->last_modified < MODIFF
+              || w->last_overlay_modified < OVERLAY_MODIFF
               || MINI_WINDOW_P (w))
        {
          /* We have to handle the case of continuation around a
@@ -13059,7 +13235,7 @@ redisplay_internal (void)
              /* 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
@@ -13072,7 +13248,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
@@ -13097,7 +13273,8 @@ redisplay_internal (void)
         then we can't just move the cursor.  */
       else if (! (!NILP (Vtransient_mark_mode)
                  && !NILP (BVAR (current_buffer, mark_active)))
-              && (EQ (selected_window, BVAR (current_buffer, last_selected_window))
+              && (EQ (selected_window,
+                      BVAR (current_buffer, last_selected_window))
                   || highlight_nonselected_windows)
               && NILP (w->region_showing)
               && NILP (Vshow_trailing_whitespace)
@@ -13123,10 +13300,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
@@ -13167,6 +13344,12 @@ redisplay_internal (void)
        {
          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))
@@ -13250,7 +13433,7 @@ redisplay_internal (void)
     }
   else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
     {
-      Lisp_Object mini_window;
+      Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
       struct frame *mini_frame;
 
       displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
@@ -13259,6 +13442,10 @@ redisplay_internal (void)
       internal_condition_case_1 (redisplay_window_1, selected_window,
                                 list_of_error,
                                 redisplay_window_error);
+      if (update_miniwindow_p)
+       internal_condition_case_1 (redisplay_window_1, mini_window,
+                                  list_of_error,
+                                  redisplay_window_error);
 
       /* Compare desired and current matrices, perform output.  */
 
@@ -13477,12 +13664,10 @@ 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) ? Qt : Qnil;
+       = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
 
       if (accurate_p)
        {
@@ -13502,16 +13687,16 @@ 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 = XMARKER (w->pointm)->charpos;
        }
     }
 
   if (accurate_p)
     {
       w->window_end_valid = w->buffer;
-      w->update_mode_line = Qnil;
+      w->update_mode_line = 0;
     }
 }
 
@@ -13679,6 +13864,13 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
      comes from a text property, not from an overlay.  */
   int string_from_text_prop = 0;
 
+  /* 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.  */
+  eassert (!row->mode_line_p);
+  if (row->mode_line_p)
+    return 0;
+
   /* Skip over glyphs not having an object at the start and the end of
      the row.  These are special glyphs like truncation marks on
      terminal frames.  */
@@ -13776,16 +13968,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;
@@ -13801,16 +13990,31 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 
            chprop = Fget_char_property (make_number (glyph_pos), Qcursor,
                                         glyph->object);
+           if (!NILP (chprop))
+             {
+               /* If the string came from a `display' text property,
+                  look up the buffer position of that property and
+                  use that position to update bpos_max, as if we
+                  actually saw such a position in one of the row's
+                  glyphs.  This helps with supporting integer values
+                  of `cursor' property on the display string in
+                  situations where most or all of the row's buffer
+                  text is completely covered by display properties,
+                  so that no glyph with valid buffer positions is
+                  ever seen in the row.  */
+               ptrdiff_t prop_pos =
+                 string_buffer_position_lim (glyph->object, pos_before,
+                                             pos_after, 0);
+
+               if (prop_pos >= pos_before)
+                 bpos_max = prop_pos - 1;
+             }
            if (INTEGERP (chprop))
              {
                bpos_covered = bpos_max + XINT (chprop);
                /* If the `cursor' property covers buffer positions up
                   to and including point, we should display cursor on
-                  this glyph.  Note that overlays and text properties
-                  with string values stop bidi reordering, so every
-                  buffer position to the left of the string is always
-                  smaller than any position to the right of the
-                  string.  Therefore, if a `cursor' property on one
+                  this glyph.  Note that, if a `cursor' property on one
                   of the string's characters has an integer value, we
                   will break out of the loop below _before_ we get to
                   the position match above.  IOW, integer values of
@@ -13854,7 +14058,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;
@@ -13870,6 +14074,15 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 
            chprop = Fget_char_property (make_number (glyph_pos), Qcursor,
                                         glyph->object);
+           if (!NILP (chprop))
+             {
+               ptrdiff_t prop_pos =
+                 string_buffer_position_lim (glyph->object, pos_before,
+                                             pos_after, 0);
+
+               if (prop_pos >= pos_before)
+                 bpos_max = prop_pos - 1;
+             }
            if (INTEGERP (chprop))
              {
                bpos_covered = bpos_max + XINT (chprop);
@@ -14007,15 +14220,18 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                      || pos <= tem)
                    {
                      /* If the string from which this glyph came is
-                        found in the buffer at point, then we've
-                        found the glyph we've been looking for.  If
-                        it comes from an overlay (tem == 0), and it
-                        has the `cursor' property on one of its
+                        found in the buffer at point, or at position
+                        that is closer to point than pos_after, then
+                        we've found the glyph we've been looking for.
+                        If it comes from an overlay (tem == 0), and
+                        it has the `cursor' property on one of its
                         glyphs, record that glyph as a candidate for
                         displaying the cursor.  (As in the
                         unidirectional version, we will display the
                         cursor on the last candidate we find.)  */
-                     if (tem == 0 || tem == pt_old)
+                     if (tem == 0
+                         || tem == pt_old
+                         || (tem - pt_old > 0 && tem < pos_after))
                        {
                          /* The glyphs from this string could have
                             been reordered.  Find the one with the
@@ -14053,7 +14269,8 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                                }
                            }
 
-                         if (tem == pt_old)
+                         if (tem == pt_old
+                             || (tem - pt_old > 0 && tem < pos_after))
                            goto compute_x;
                        }
                      if (tem)
@@ -14073,6 +14290,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;
@@ -14102,6 +14320,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;
@@ -14340,7 +14573,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
 
@@ -14692,11 +14925,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.  */
@@ -14717,8 +14955,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
           && !NILP (BVAR (current_buffer, mark_active)))
       && 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
@@ -14739,7 +14975,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
 
@@ -14776,13 +15012,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;
                }
 
@@ -14811,7 +15047,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.  */
@@ -14825,7 +15061,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;
                }
 
@@ -14871,6 +15107,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
          else if (rc != CURSOR_MOVEMENT_SUCCESS
                   && !NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
            {
+             struct glyph_row *row1;
+
              /* If rows are bidi-reordered and point moved, back up
                 until we find a row that does not belong to a
                 continuation line.  This is because we must consider
@@ -14881,24 +15119,28 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
              /* FIXME: Revisit this when glyph ``spilling'' in
                 continuation lines' rows is implemented for
                 bidi-reordered rows.  */
-             while (MATRIX_ROW_CONTINUATION_LINE_P (row))
+             for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+                  MATRIX_ROW_CONTINUATION_LINE_P (row);
+                  --row)
                {
                  /* If we hit the beginning of the displayed portion
                     without finding the first row of a continued
                     line, give up.  */
-                 if (row <= w->current_matrix->rows)
+                 if (row <= row1)
                    {
                      rc = CURSOR_MOVEMENT_MUST_SCROLL;
                      break;
                    }
-                 xassert (row->enabled_p);
-                 --row;
+                 eassert (row->enabled_p);
                }
            }
          if (must_scroll)
            ;
          else if (rc != CURSOR_MOVEMENT_SUCCESS
              && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
+             /* Make sure this isn't a header line by any chance, since
+                then MATRIX_ROW_PARTIALLY_VISIBLE_P might yield non-zero.  */
+             && !row->mode_line_p
              && make_cursor_line_fully_visible_p)
            {
              if (PT == MATRIX_ROW_END_CHARPOS (row)
@@ -15090,8 +15332,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
 
@@ -15099,7 +15341,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   reconsider_clip_changes (w, buffer);
 
   /* Has the mode line to be updated?  */
-  update_mode_line = (!NILP (w->update_mode_line)
+  update_mode_line = (w->update_mode_line
                      || update_mode_lines
                      || buffer->clip_changed
                      || buffer->prevent_redisplay_optimizations_p);
@@ -15151,8 +15393,8 @@ 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);
+       && w->last_modified >= MODIFF
+       && w->last_overlay_modified >= OVERLAY_MODIFF);
 
   /* Run the window-bottom-change-functions
      if it is possible that the text on the screen has changed
@@ -15174,8 +15416,8 @@ 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);
+       && w->last_modified >= MODIFF
+       && w->last_overlay_modified >= OVERLAY_MODIFF);
 
   /* When windows_or_buffers_changed is non-zero, we can't rely on
      the window end being valid, so set it to nil there.  */
@@ -15200,9 +15442,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   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)
+      && !(PT == w->last_point
+          && w->last_modified >= MODIFF
+          && w->last_overlay_modified >= OVERLAY_MODIFF)
       && (XFASTINT (w->column_number_displayed) != current_column ()))
     update_mode_line = 1;
 
@@ -15271,32 +15513,31 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
   /* If someone specified a new starting point but did not insist,
      check whether it can be used.  */
-  if (!NILP (w->optional_new_start)
+  if (w->optional_new_start
       && CHARPOS (startp) >= BEGV
       && CHARPOS (startp) <= ZV)
     {
-      w->optional_new_start = Qnil;
+      w->optional_new_start = 0;
       start_display (&it, w, startp);
       move_it_to (&it, PT, 0, it.last_visible_y, -1,
                  MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
       if (IT_CHARPOS (it) == PT)
-       w->force_start = Qt;
+       w->force_start = 1;
       /* IT may overshoot PT if text at PT is invisible.  */
       else if (IT_CHARPOS (it) > PT && CHARPOS (startp) <= PT)
-       w->force_start = Qt;
+       w->force_start = 1;
     }
 
  force_start:
 
   /* Handle case where place to start displaying has been specified,
      unless the specified location is outside the accessible range.  */
-  if (!NILP (w->force_start)
-      || w->frozen_window_start_p)
+  if (w->force_start || w->frozen_window_start_p)
     {
       /* We set this later on if we have to adjust point.  */
       int new_vpos = -1;
 
-      w->force_start = Qnil;
+      w->force_start = 0;
       w->vscroll = 0;
       w->window_end_valid = Qnil;
 
@@ -15315,12 +15556,12 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          || ! NILP (Vwindow_scroll_functions))
        {
          update_mode_line = 1;
-         w->update_mode_line = Qt;
+         w->update_mode_line = 1;
          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)
@@ -15333,7 +15574,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
         the scroll margin (bug#148) -- cyd  */
       if (!try_window (window, startp, 0))
        {
-         w->force_start = Qt;
+         w->force_start = 1;
          clear_glyph_matrix (w->desired_matrix);
          goto need_larger_matrices;
        }
@@ -15384,7 +15625,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;
@@ -15412,11 +15653,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
     }
   /* If current starting point was originally the beginning of a line
      but no longer is, find a new starting point.  */
-  else if (!NILP (w->start_at_line_beg)
+  else if (w->start_at_line_beg
           && !(CHARPOS (startp) <= BEGV
                || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
     {
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "recenter 1");
 #endif
       goto recenter;
@@ -15427,7 +15668,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
 
@@ -15445,8 +15686,8 @@ 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)))
+              || (w->last_modified >= MODIFF
+                  && w->last_overlay_modified >= OVERLAY_MODIFF)))
     {
       int d1, d2, d3, d4, d5, d6;
 
@@ -15459,7 +15700,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
         new window start, since that would change the position under
         the mouse, resulting in an unwanted mouse-movement rather
         than a simple mouse-click.  */
-      if (NILP (w->start_at_line_beg)
+      if (!w->start_at_line_beg
          && NILP (do_mouse_tracking)
          && CHARPOS (startp) > BEGV
          && CHARPOS (startp) > BEG + beg_unchanged
@@ -15479,12 +15720,12 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
             See bug#9324.  */
          && pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &d6))
        {
-         w->force_start = Qt;
+         w->force_start = 1;
          SET_TEXT_POS_FROM_MARKER (startp, w->start);
          goto force_start;
        }
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
       debug_method_add (w, "same window start");
 #endif
 
@@ -15533,14 +15774,14 @@ 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)
     {
       update_mode_line = 1;
-      w->update_mode_line = Qt;
+      w->update_mode_line = 1;
     }
 
   /* Try to scroll by specified few lines.  */
@@ -15579,7 +15820,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
  recenter:
 
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
   debug_method_add (w, "recenter");
 #endif
 
@@ -15609,7 +15850,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
             accessible region of the buffer.  This can happen when we
             have just switched to a different buffer and/or changed
             its restriction.  In that case, startp is initialized to
-            the character position 1 (BEG) because we did not yet
+            the character position 1 (BEGV) because we did not yet
             have chance to display the buffer even once.  */
          && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
        {
@@ -15618,7 +15859,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
          SAVE_IT (it1, it, it1data);
          start_display (&it1, w, startp);
-         move_it_vertically (&it1, margin);
+         move_it_vertically (&it1, margin * FRAME_LINE_HEIGHT (f));
          margin_pos = IT_CHARPOS (it1);
          RESTORE_IT (&it, &it, it1data);
        }
@@ -15671,7 +15912,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
@@ -15795,9 +16036,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
  done:
 
   SET_TEXT_POS_FROM_MARKER (startp, w->start);
-  w->start_at_line_beg = ((CHARPOS (startp) == BEGV
-                          || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
-                         ? Qt : Qnil);
+  w->start_at_line_beg = (CHARPOS (startp) == BEGV
+                           || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
 
   /* Display the mode line, if we must.  */
   if ((update_mode_line
@@ -16014,21 +16254,21 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
   /* If bottom moved off end of frame, change mode line percentage.  */
   if (XFASTINT (w->window_end_pos) <= 0
       && Z != IT_CHARPOS (it))
-    w->update_mode_line = Qt;
+    w->update_mode_line = 1;
 
   /* Set window_end_pos to the offset of the last character displayed
      on the window from the end of current_buffer.  Set
      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))
+      eassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
               ->displays_text_p);
     }
   else
@@ -16068,7 +16308,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
@@ -16290,7 +16530,7 @@ try_window_reusing_current_matrix (struct window *w)
       /* 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;
@@ -16329,12 +16569,15 @@ try_window_reusing_current_matrix (struct window *w)
           ++first_row_to_display)
        {
          if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
-             && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
+             && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
+                 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
+                     && first_row_to_display->ends_at_zv_p
+                     && pt_row == NULL)))
            pt_row = first_row_to_display;
        }
 
       /* 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)
@@ -16406,7 +16649,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),
@@ -16421,7 +16664,9 @@ try_window_reusing_current_matrix (struct window *w)
       if (pt_row)
        {
          for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
-              row < bottom_row && PT >= MATRIX_ROW_END_CHARPOS (row);
+              row < bottom_row
+                && PT >= MATRIX_ROW_END_CHARPOS (row)
+                && !row->ends_at_zv_p;
               row++)
            {
              w->cursor.vpos++;
@@ -16475,7 +16720,7 @@ try_window_reusing_current_matrix (struct window *w)
       w->window_end_valid = 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;
@@ -16516,7 +16761,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;
@@ -16562,7 +16807,15 @@ find_last_unchanged_at_beg_row (struct window *w)
             continued.  */
          && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
               && (row->continued_p
-                  || row->exact_window_width_line_p)))
+                  || row->exact_window_width_line_p))
+         /* If ROW->end is beyond ZV, then ROW->end is outdated and
+            needs to be recomputed, so don't consider this row as
+            unchanged.  This happens when the last line was
+            bidi-reordered and was killed immediately before this
+            redisplay cycle.  In that case, ROW->end stores the
+            buffer position of the first visual-order character of
+            the killed text, which is now beyond ZV.  */
+         && CHARPOS (row->end.pos) <= ZV)
        row_found = row;
 
       /* Stop if last visible row.  */
@@ -16670,9 +16923,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
@@ -16835,7 +17088,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
@@ -16881,11 +17134,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.  */
@@ -17109,7 +17362,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
     {
@@ -17139,7 +17392,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
@@ -17162,19 +17415,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
@@ -17183,7 +17436,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
@@ -17419,7 +17672,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
@@ -17466,16 +17719,16 @@ 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));
       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);
+      eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "A"));
     }
   else if (last_text_row_at_end)
@@ -17486,7 +17739,7 @@ try_window_id (struct window *w)
        = 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);
+      eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "B"));
     }
   else if (last_text_row)
@@ -17500,7 +17753,7 @@ try_window_id (struct window *w)
        = 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);
+      eassert (w->window_end_bytepos >= 0);
     }
   else if (first_unchanged_at_end_row == NULL
           && last_text_row == NULL
@@ -17526,11 +17779,11 @@ try_window_id (struct window *w)
            row  = current_row;
        }
 
-      xassert (row != NULL);
+      eassert (row != NULL);
       w->window_end_vpos = make_number (vpos + 1);
       w->window_end_pos = 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
@@ -17553,7 +17806,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 +18197,7 @@ 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));
 
   /* Get the truncation glyphs.  */
   truncate_it = *it;
@@ -18077,8 +18330,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));
@@ -18168,8 +18421,10 @@ append_space_for_newline (struct it *it, int default_face_p)
          it->c = it->char_to_display = ' ';
          it->len = 1;
 
+         /* If the default face was remapped, be sure to use the
+            remapped face for the appended newline. */
          if (default_face_p)
-           it->face_id = DEFAULT_FACE_ID;
+           it->face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
          else if (it->face_before_selective_p)
            it->face_id = it->saved_face_id;
          face = FACE_FROM_ID (it->f, it->face_id);
@@ -18205,7 +18460,7 @@ append_space_for_newline (struct it *it, int default_face_p)
 static void
 extend_face_to_end_of_line (struct it *it)
 {
-  struct face *face;
+  struct face *face, *default_face;
   struct frame *f = it->f;
 
   /* If line is already filled, do nothing.  Non window-system frames
@@ -18219,6 +18474,9 @@ extend_face_to_end_of_line (struct it *it)
         && !it->glyph_row->continued_p))
     return;
 
+  /* The default face, possibly remapped. */
+  default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
+
   /* Face extension extends the background and box of IT->face_id
      to the end of the line.  If the background equals the background
      of the frame, we don't have to do anything.  */
@@ -18256,7 +18514,7 @@ extend_face_to_end_of_line (struct it *it)
       if (it->glyph_row->used[TEXT_AREA] == 0)
        {
          it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
-         it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
+         it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
          it->glyph_row->used[TEXT_AREA] = 1;
        }
 #ifdef HAVE_WINDOW_SYSTEM
@@ -18292,7 +18550,7 @@ extend_face_to_end_of_line (struct it *it)
                 face, to avoid painting the rest of the window with
                 the region face, if the region ends at ZV.  */
              if (it->glyph_row->ends_at_zv_p)
-               it->face_id = DEFAULT_FACE_ID;
+               it->face_id = default_face->id;
              else
                it->face_id = face->id;
              append_stretch_glyph (it, make_number (0), stretch_width,
@@ -18325,7 +18583,7 @@ extend_face_to_end_of_line (struct it *it)
         avoid painting the rest of the window with the region face,
         if the region ends at ZV.  */
       if (it->glyph_row->ends_at_zv_p)
-       it->face_id = DEFAULT_FACE_ID;
+       it->face_id = default_face->id;
       else
        it->face_id = face->id;
 
@@ -18458,9 +18716,11 @@ cursor_row_p (struct glyph_row *row)
       /* Suppose the row ends on a string.
         Unless the row is continued, that means it ends on a newline
         in the string.  If it's anything other than a display string
-        (e.g. a before-string from an overlay), we don't want the
+        (e.g., a before-string from an overlay), we don't want the
         cursor there.  (This heuristic seems to give the optimal
-        behavior for the various types of multi-line strings.)  */
+        behavior for the various types of multi-line strings.)
+        One exception: if the string has `cursor' property on one of
+        its characters, we _do_ want the cursor there.  */
       if (CHARPOS (row->end.string_pos) >= 0)
        {
          if (row->continued_p)
@@ -18482,6 +18742,25 @@ cursor_row_p (struct glyph_row *row)
                    result =
                      (!NILP (prop)
                       && display_prop_string_p (prop, glyph->object));
+                   /* If there's a `cursor' property on one of the
+                      string's characters, this row is a cursor row,
+                      even though this is not a display string.  */
+                   if (!result)
+                     {
+                       Lisp_Object s = glyph->object;
+
+                       for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
+                         {
+                           ptrdiff_t gpos = glyph->charpos;
+
+                           if (!NILP (Fget_char_property (make_number (gpos),
+                                                          Qcursor, s)))
+                             {
+                               result = 1;
+                               break;
+                             }
+                         }
+                     }
                    break;
                  }
            }
@@ -18520,12 +18799,12 @@ cursor_row_p (struct glyph_row *row)
    `line-prefix' and `wrap-prefix' properties.  */
 
 static int
-push_display_prop (struct it *it, Lisp_Object prop)
+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);
 
@@ -18544,6 +18823,7 @@ push_display_prop (struct it *it, Lisp_Object prop)
        }
 
       it->string = prop;
+      it->string_from_prefix_prop_p = 1;
       it->multibyte_p = STRING_MULTIBYTE (it->string);
       it->current.overlay_string_index = -1;
       IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
@@ -18630,7 +18910,7 @@ handle_line_prefix (struct it *it)
       if (NILP (prefix))
        prefix = Vline_prefix;
     }
-  if (! NILP (prefix) && push_display_prop (it, prefix))
+  if (! NILP (prefix) && push_prefix_prop (it, prefix))
     {
       /* If the prefix is wider than the window, and we try to wrap
         it, it would acquire its own wrap prefix, and so on till the
@@ -18651,10 +18931,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];
@@ -18843,7 +19123,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)
@@ -18967,8 +19247,13 @@ display_line (struct it *it)
          /* A row that displays right-to-left text must always have
             its last face extended all the way to the end of line,
             even if this row ends in ZV, because we still write to
-            the screen left to right.  */
-         if (row->reversed_p)
+            the screen left to right.  We also need to extend the
+            last face if the default face is remapped to some
+            different face, otherwise the functions that clear
+            portions of the screen will clear with the default face's
+            background color.  */
+         if (row->reversed_p
+             || lookup_basic_face (it->f, DEFAULT_FACE_ID) != DEFAULT_FACE_ID)
            extend_face_to_end_of_line (it);
          break;
        }
@@ -19257,7 +19542,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,
@@ -19449,7 +19734,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;
@@ -19652,7 +19937,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);
@@ -19662,7 +19947,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);
@@ -19868,7 +20153,7 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
   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;
 
@@ -20569,7 +20854,8 @@ are the selected window and the WINDOW's buffer).  */)
      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 (XWINDOW (window))),
+                           old_buffer, selected_window, 1));
   mode_line_proptrans_alist = Qnil;
 
   Fselect_window (window, Qt);
@@ -20776,8 +21062,7 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_
 
   if (!VECTORP (val))          /* Not yet decided.  */
     {
-      if (multibyte)
-       *buf++ = '-';
+      *buf++ = multibyte ? '-' : ' ';
       if (eol_flag)
        eoltype = eol_mnemonic_undecided;
       /* Don't mention EOL conversion if it isn't decided.  */
@@ -20790,8 +21075,9 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_
       attrs = AREF (val, 0);
       eolvalue = AREF (val, 2);
 
-      if (multibyte)
-       *buf++ = XFASTINT (CODING_ATTR_MNEMONIC (attrs));
+      *buf++ = multibyte
+       ? XFASTINT (CODING_ATTR_MNEMONIC (attrs))
+       : ' ';
 
       if (eol_flag)
        {
@@ -21757,7 +22043,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))
     {
@@ -21856,7 +22142,9 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
            return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
        }
 
-      prop = Fbuffer_local_value (prop, it->w->buffer);
+      prop = buffer_local_value_1 (prop, it->w->buffer);
+      if (EQ (prop, Qunbound))
+       prop = Qnil;
     }
 
   if (INTEGERP (prop) || FLOATP (prop))
@@ -21906,7 +22194,9 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
              return OK_PIXELS (pixels);
            }
 
-         car = Fbuffer_local_value (car, it->w->buffer);
+         car = buffer_local_value_1 (car, it->w->buffer);
+         if (EQ (car, Qunbound))
+           car = Qnil;
        }
 
       if (INTEGERP (car) || FLOATP (car))
@@ -21934,7 +22224,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)
@@ -22080,7 +22370,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);
     }
 
@@ -22098,7 +22388,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 {
   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)
@@ -22120,7 +22410,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;
 }
@@ -22166,7 +22456,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;
@@ -22276,7 +22566,7 @@ 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;
@@ -22317,9 +22607,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;
@@ -22342,7 +22632,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;
@@ -22363,7 +22653,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];
 }
 
@@ -22373,9 +22663,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;
@@ -22399,7 +22689,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;
@@ -22423,7 +22713,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];
 }
 
@@ -23169,8 +23459,8 @@ 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])
@@ -23243,7 +23533,7 @@ 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])
@@ -23335,10 +23625,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);
 
@@ -23353,7 +23643,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);
 
@@ -23494,7 +23784,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])
@@ -23604,7 +23894,7 @@ produce_stretch_glyph (struct it *it)
 #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,11 +24273,11 @@ 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;
        }
-      for (len = 0; str[len] && ASCII_BYTE_P (str[len]); len++)
+      for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++)
        code[len] = font->driver->encode_char (font, str[len]);
       upper_len = (len + 1) / 2;
       font->driver->text_extents (font, code, upper_len,
@@ -24085,7 +24375,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;
        }
@@ -24710,7 +25000,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;
 
@@ -24739,7 +25029,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.  */
@@ -24788,7 +25078,7 @@ x_insert_glyphs (struct glyph *start, int len)
   int frame_x, frame_y;
   ptrdiff_t hpos;
 
-  xassert (updated_window && updated_row);
+  eassert (updated_window && updated_row);
   BLOCK_INPUT;
   w = updated_window;
   f = XFRAME (WINDOW_FRAME (w));
@@ -24843,7 +25133,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)
@@ -25468,7 +25758,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 (interrupt_input_blocked);
 
   /* Set new_cursor_type to the cursor we want to be displayed.  */
   new_cursor_type = get_window_cursor_type (w, glyph,
@@ -25605,7 +25895,7 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
       return;
     }
 #endif
-#if defined (HAVE_GPM) || defined (MSDOS)
+#if defined (HAVE_GPM) || defined (MSDOS) || defined (WINDOWSNT)
   tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
 #endif
 }
@@ -26015,9 +26305,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);
@@ -26727,12 +27017,12 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
   int dx, dy, width, height;
   ptrdiff_t charpos;
   Lisp_Object string, object = Qnil;
-  Lisp_Object pos, help;
+  Lisp_Object pos IF_LINT (= Qnil), help;
 
   Lisp_Object mouse_face;
   int original_x_pixel = x;
   struct glyph * glyph = NULL, * row_start_glyph = NULL;
-  struct glyph_row *row;
+  struct glyph_row *row IF_LINT (= 0);
 
   if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
     {
@@ -26800,7 +27090,6 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
              if (!NILP (help))
                {
                  help_echo_string = help;
-                 /* Is this correct?  ++kfs */
                  XSETWINDOW (help_echo_window, w);
                  help_echo_object = w->buffer;
                  help_echo_pos = charpos;
@@ -26813,14 +27102,20 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
 #endif /* HAVE_WINDOW_SYSTEM */
 
   if (STRINGP (string))
+    pos = make_number (charpos);
+
+  /* Set the help text and mouse pointer.  If the mouse is on a part
+     of the mode line without any text (e.g. past the right edge of
+     the mode line text), use the default help text and pointer.  */
+  if (STRINGP (string) || area == ON_MODE_LINE)
     {
-      pos = make_number (charpos);
-      /* If we're on a string with `help-echo' text property, arrange
-        for the help to be displayed.  This is done by setting the
-        global variable help_echo_string to the help string.  */
+      /* Arrange to display the help by setting the global variables
+        help_echo_string, help_echo_object, and help_echo_pos.  */
       if (NILP (help))
        {
-         help = Fget_text_property (pos, Qhelp_echo, string);
+         if (STRINGP (string))
+           help = Fget_text_property (pos, Qhelp_echo, string);
+
          if (!NILP (help))
            {
              help_echo_string = help;
@@ -26828,31 +27123,56 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
              help_echo_object = string;
              help_echo_pos = charpos;
            }
+         else if (area == ON_MODE_LINE)
+           {
+             Lisp_Object default_help
+               = buffer_local_value_1 (Qmode_line_default_help_echo,
+                                       w->buffer);
+
+             if (STRINGP (default_help))
+               {
+                 help_echo_string = default_help;
+                 XSETWINDOW (help_echo_window, w);
+                 help_echo_object = Qnil;
+                 help_echo_pos = -1;
+               }
+           }
        }
 
 #ifdef HAVE_WINDOW_SYSTEM
+      /* Change the mouse pointer according to what is under it.  */
       if (FRAME_WINDOW_P (f))
        {
          dpyinfo = FRAME_X_DISPLAY_INFO (f);
-         cursor  = FRAME_X_OUTPUT (f)->nontext_cursor;
-         if (NILP (pointer))
-           pointer = Fget_text_property (pos, Qpointer, string);
-
-         /* Change the mouse pointer according to what is under X/Y.  */
-         if (NILP (pointer)
-             && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)))
+         if (STRINGP (string))
            {
-             Lisp_Object map;
-             map = Fget_text_property (pos, Qlocal_map, string);
-             if (!KEYMAPP (map))
-               map = Fget_text_property (pos, Qkeymap, string);
-             if (!KEYMAPP (map))
-               cursor = dpyinfo->vertical_scroll_bar_cursor;
+             cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+
+             if (NILP (pointer))
+               pointer = Fget_text_property (pos, Qpointer, string);
+
+             /* Change the mouse pointer according to what is under X/Y.  */
+             if (NILP (pointer)
+                 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)))
+               {
+                 Lisp_Object map;
+                 map = Fget_text_property (pos, Qlocal_map, string);
+                 if (!KEYMAPP (map))
+                   map = Fget_text_property (pos, Qkeymap, string);
+                 if (!KEYMAPP (map))
+                   cursor = dpyinfo->vertical_scroll_bar_cursor;
+               }
            }
+         else
+           /* Default mode-line pointer.  */
+           cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
        }
 #endif
+    }
 
-     /* Change the mouse face according to what is under X/Y.  */
+  /* Change the mouse face according to what is under X/Y.  */
+  if (STRINGP (string))
+    {
       mouse_face = Fget_text_property (pos, Qmouse_face, string);
       if (!NILP (mouse_face)
          && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))
@@ -27091,8 +27411,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;
@@ -27603,7 +27923,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,
@@ -27643,7 +27963,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])
@@ -28089,7 +28409,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);
@@ -28193,6 +28513,8 @@ syms_of_xdisp (void)
   Vmode_line_unwind_vector = Qnil;
   staticpro (&Vmode_line_unwind_vector);
 
+  DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
+
   help_echo_string = Qnil;
   staticpro (&help_echo_string);
   help_echo_object = Qnil;
@@ -28208,14 +28530,14 @@ syms_of_xdisp (void)
 
 #ifdef HAVE_WINDOW_SYSTEM
   DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
-    doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
+    doc: /* Non-nil means draw block cursor as wide as the glyph under it.
 For example, if a block cursor is over a tab, it will be drawn as
 wide as that tab on the display.  */);
   x_stretch_cursor_p = 0;
 #endif
 
   DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
-    doc: /* *Non-nil means highlight trailing whitespace.
+    doc: /* Non-nil means highlight trailing whitespace.
 The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
@@ -28235,7 +28557,7 @@ A value of nil means no special handling of these characters.  */);
   Vnobreak_char_display = Qt;
 
   DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
-    doc: /* *The pointer shape to show in void text areas.
+    doc: /* The pointer shape to show in void text areas.
 A value of nil means to show the text pointer.  Other options are `arrow',
 `text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'.  */);
   Vvoid_text_area_pointer = Qarrow;
@@ -28268,14 +28590,14 @@ where to display overlay arrows.  */);
     = Fcons (intern_c_string ("overlay-arrow-position"), Qnil);
 
   DEFVAR_INT ("scroll-step", emacs_scroll_step,
-    doc: /* *The number of lines to try scrolling a window by when point moves out.
+    doc: /* The number of lines to try scrolling a window by when point moves out.
 If that fails to bring point back on frame, point is centered instead.
 If this is zero, point is always centered after it moves off frame.
 If you want scrolling to always be a line at a time, you should set
 `scroll-conservatively' to a large value rather than set this to 1.  */);
 
   DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
-    doc: /* *Scroll up to this many lines, to bring point back on screen.
+    doc: /* Scroll up to this many lines, to bring point back on screen.
 If point moves off-screen, redisplay will scroll by up to
 `scroll-conservatively' lines in order to bring point just barely
 onto the screen again.  If that cannot be done, then redisplay
@@ -28289,7 +28611,7 @@ A value of zero means always recenter point if it moves off screen.  */);
   scroll_conservatively = 0;
 
   DEFVAR_INT ("scroll-margin", scroll_margin,
-    doc: /* *Number of lines of margin at the top and bottom of a window.
+    doc: /* Number of lines of margin at the top and bottom of a window.
 Recenter the window whenever point gets within this many lines
 of the top or bottom of the window.  */);
   scroll_margin = 0;
@@ -28299,7 +28621,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
 
@@ -28325,20 +28647,20 @@ Any other value means to use the appropriate face, `mode-line',
   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.
+    doc: /* Maximum buffer size for which line number should be displayed.
 If the buffer is bigger than this, the line number does not appear
 in the mode line.  A value of nil means no limit.  */);
   Vline_number_display_limit = Qnil;
 
   DEFVAR_INT ("line-number-display-limit-width",
              line_number_display_limit_width,
-    doc: /* *Maximum line width (in characters) for line number display.
+    doc: /* Maximum line width (in characters) for line number display.
 If the average length of the lines near point is bigger than this, then the
 line number may be omitted from the mode line.  */);
   line_number_display_limit_width = 200;
 
   DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
-    doc: /* *Non-nil means highlight region even in nonselected windows.  */);
+    doc: /* Non-nil means highlight region even in nonselected windows.  */);
   highlight_nonselected_windows = 0;
 
   DEFVAR_BOOL ("multiple-frames", multiple_frames,
@@ -28410,7 +28732,7 @@ See `set-window-redisplay-end-trigger'.  */);
   Vredisplay_end_trigger_functions = Qnil;
 
   DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
-     doc: /* *Non-nil means autoselect window with mouse pointer.
+     doc: /* Non-nil means autoselect window with mouse pointer.
 If nil, do not autoselect windows.
 A positive number means delay autoselection by that many seconds: a
 window is autoselected only after the mouse has remained in that
@@ -28430,7 +28752,7 @@ When customizing this variable make sure that the actual value of
   Vmouse_autoselect_window = Qnil;
 
   DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
-    doc: /* *Non-nil means automatically resize tool-bars.
+    doc: /* Non-nil means automatically resize tool-bars.
 This dynamically changes the tool-bar's height to the minimum height
 that is needed to make all tool-bar items visible.
 If value is `grow-only', the tool-bar's height is only increased
@@ -28438,15 +28760,15 @@ automatically; to decrease the tool-bar height, use \\[recenter].  */);
   Vauto_resize_tool_bars = Qt;
 
   DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
-    doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them.  */);
+    doc: /* Non-nil means raise tool-bar buttons when the mouse moves over them.  */);
   auto_raise_tool_bar_buttons_p = 1;
 
   DEFVAR_BOOL ("make-cursor-line-fully-visible", make_cursor_line_fully_visible_p,
-    doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible.  */);
+    doc: /* Non-nil means to scroll (recenter) cursor line if it is not fully visible.  */);
   make_cursor_line_fully_visible_p = 1;
 
   DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
-    doc: /* *Border below tool-bar in pixels.
+    doc: /* Border below tool-bar in pixels.
 If an integer, use it as the height of the border.
 If it is one of `internal-border-width' or `border-width', use the
 value of the corresponding frame parameter.
@@ -28454,7 +28776,7 @@ Otherwise, no border is added below the tool-bar.  */);
   Vtool_bar_border = Qinternal_border_width;
 
   DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
-    doc: /* *Margin around tool-bar buttons in pixels.
+    doc: /* Margin around tool-bar buttons in pixels.
 If an integer, use that for both horizontal and vertical margins.
 Otherwise, value should be a pair of integers `(HORZ . VERT)' with
 HORZ specifying the horizontal margin, and VERT specifying the
@@ -28462,7 +28784,7 @@ vertical margin.  */);
   Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
 
   DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
-    doc: /* *Relief thickness of tool-bar buttons.  */);
+    doc: /* Relief thickness of tool-bar buttons.  */);
   tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
 
   DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
@@ -28473,11 +28795,13 @@ It can be one of
  both             - show both, text below image
  both-horiz       - show text to the right of the image
  text-image-horiz - show text to the left of the image
- any other        - use system default or image if no system default.  */);
+ any other        - use system default or image if no system default.
+
+This variable only affects the GTK+ toolkit version of Emacs.  */);
   Vtool_bar_style = Qnil;
 
   DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
-    doc: /* *Maximum number of characters a label can have to be shown.
+    doc: /* Maximum number of characters a label can have to be shown.
 The tool bar style must also show labels for this to have any effect, see
 `tool-bar-style'.  */);
   tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
@@ -28492,7 +28816,7 @@ fontified regions the property `fontified'.  */);
 
   DEFVAR_BOOL ("unibyte-display-via-language-environment",
                unibyte_display_via_language_environment,
-    doc: /* *Non-nil means display unibyte text according to language environment.
+    doc: /* Non-nil means display unibyte text according to language environment.
 Specifically, this means that raw bytes in the range 160-255 decimal
 are displayed by converting them to the equivalent multibyte characters
 according to the current language environment.  As a result, they are
@@ -28503,7 +28827,7 @@ but does not change the fact they are interpreted as raw bytes.  */);
   unibyte_display_via_language_environment = 0;
 
   DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
-    doc: /* *Maximum height for resizing mini-windows (the minibuffer and the echo area).
+    doc: /* Maximum height for resizing mini-windows (the minibuffer and the echo area).
 If a float, it specifies a fraction of the mini-window frame's height.
 If an integer, it specifies a number of lines.  */);
   Vmax_mini_window_height = make_float (0.25);
@@ -28537,12 +28861,12 @@ point visible.  */);
   DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
 
   DEFVAR_INT ("hscroll-margin", hscroll_margin,
-    doc: /* *How many columns away from the window edge point is allowed to get
+    doc: /* How many columns away from the window edge point is allowed to get
 before automatic hscrolling will horizontally scroll the window.  */);
   hscroll_margin = 5;
 
   DEFVAR_LISP ("hscroll-step", Vhscroll_step,
-    doc: /* *How many columns to scroll the window when point gets too close to the edge.
+    doc: /* How many columns to scroll the window when point gets too close to the edge.
 When point is less than `hscroll-margin' columns from the window
 edge, automatic hscrolling will scroll the window by the amount of columns
 determined by this variable.  If its value is a positive integer, scroll that
@@ -28614,7 +28938,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;
@@ -28629,7 +28953,7 @@ To add a prefix to continuation lines, use `wrap-prefix'.  */);
 #endif /* GLYPH_DEBUG */
 
   DEFVAR_INT ("overline-margin", overline_margin,
-              doc: /* *Space between overline and text, in pixels.
+              doc: /* Space between overline and text, in pixels.
 The default value is 2: the height of the overline (1 pixel) plus 1 pixel
 margin to the character height.  */);
   overline_margin = 2;
@@ -28650,7 +28974,7 @@ cursor shapes.  */);
   display_hourglass_p = 1;
 
   DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
-              doc: /* *Seconds to wait before displaying an hourglass pointer when Emacs is busy.  */);
+              doc: /* Seconds to wait before displaying an hourglass pointer when Emacs is busy.  */);
   Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
 
   hourglass_atimer = NULL;
@@ -28746,32 +29070,26 @@ init_xdisp (void)
 
 /* Platform-independent portion of hourglass implementation. */
 
-/* Return non-zero if hourglass timer has been started or hourglass is
-   shown.  */
-int
-hourglass_started (void)
-{
-  return hourglass_shown_p || hourglass_atimer != NULL;
-}
-
 /* Cancel a currently active hourglass timer, and start a new one.  */
 void
 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)
+    EMACS_SET_SECS_NSECS (delay,
+                         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
+    EMACS_SET_SECS_NSECS (delay, DEFAULT_HOURGLASS_DELAY, 0);
 
-  EMACS_SET_SECS_USECS (delay, secs, usecs);
   hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
                                   show_hourglass, NULL);
 #endif