]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
; Merge from origin/emacs-25
[gnu-emacs] / src / xdisp.c
index acb275481adec4587da78568abb22eb41a91e60e..e78d3d6f5b6cb588ada3c028c1c330dc24da07e5 100644 (file)
@@ -7,8 +7,8 @@ This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -1813,7 +1813,7 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
         cache and mode line face are not yet initialized.  */
       if (FRAME_FACE_CACHE (f))
        {
         cache and mode line face are not yet initialized.  */
       if (FRAME_FACE_CACHE (f))
        {
-         struct face *face = FACE_FROM_ID (f, face_id);
+         struct face *face = FACE_OPT_FROM_ID (f, face_id);
          if (face)
            {
              if (face->font)
          if (face)
            {
              if (face->font)
@@ -2918,7 +2918,7 @@ init_iterator (struct it *it, struct window *w,
 
       /* If we have a boxed mode line, make the first character appear
         with a left box line.  */
 
       /* If we have a boxed mode line, make the first character appear
         with a left box line.  */
-      face = FACE_FROM_ID (it->f, remapped_base_face_id);
+      face = FACE_OPT_FROM_ID (it->f, remapped_base_face_id);
       if (face && face->box != FACE_NO_BOX)
        it->start_of_box_run_p = true;
     }
       if (face && face->box != FACE_NO_BOX)
        it->start_of_box_run_p = true;
     }
@@ -2946,7 +2946,7 @@ init_iterator (struct it *it, struct window *w,
         character properties needed for reordering are not yet
         available.  */
       it->bidi_p =
         character properties needed for reordering are not yet
         available.  */
       it->bidi_p =
-       NILP (Vpurify_flag)
+       !redisplay__inhibit_bidi
        && !NILP (BVAR (current_buffer, bidi_display_reordering))
        && it->multibyte_p;
 
        && !NILP (BVAR (current_buffer, bidi_display_reordering))
        && it->multibyte_p;
 
@@ -3877,9 +3877,9 @@ handle_face_prop (struct it *it)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
          /* If it->face_id is -1, old_face below will be NULL, see
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
          /* If it->face_id is -1, old_face below will be NULL, see
-            the definition of FACE_FROM_ID.  This will happen if this
+            the definition of FACE_OPT_FROM_ID.  This will happen if this
             is the initial call that gets the face.  */
             is the initial call that gets the face.  */
-         struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
+         struct face *old_face = FACE_OPT_FROM_ID (it->f, it->face_id);
 
          /* If the value of face_id of the iterator is -1, we have to
             look in front of IT's position and see whether there is a
 
          /* If the value of face_id of the iterator is -1, we have to
             look in front of IT's position and see whether there is a
@@ -3888,7 +3888,7 @@ handle_face_prop (struct it *it)
            {
              int prev_face_id = face_before_it_pos (it);
 
            {
              int prev_face_id = face_before_it_pos (it);
 
-             old_face = FACE_FROM_ID (it->f, prev_face_id);
+             old_face = FACE_OPT_FROM_ID (it->f, prev_face_id);
            }
 
          /* If the new face has a box, but the old face does not,
            }
 
          /* If the new face has a box, but the old face does not,
@@ -3988,7 +3988,7 @@ handle_face_prop (struct it *it)
       if (new_face_id != it->face_id)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
       if (new_face_id != it->face_id)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
-         struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
+         struct face *old_face = FACE_OPT_FROM_ID (it->f, it->face_id);
 
          /* If new face has a box but old face hasn't, this is the
             start of a run of characters with box, i.e. it has a
 
          /* If new face has a box but old face hasn't, this is the
             start of a run of characters with box, i.e. it has a
@@ -4847,7 +4847,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          it->font_height = XCAR (XCDR (spec));
          if (!NILP (it->font_height))
            {
          it->font_height = XCAR (XCDR (spec));
          if (!NILP (it->font_height))
            {
-             struct face *face = FACE_FROM_ID (it->f, it->face_id);
              int new_height = -1;
 
              if (CONSP (it->font_height)
              int new_height = -1;
 
              if (CONSP (it->font_height)
@@ -4866,6 +4865,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                {
                  /* Call function with current height as argument.
                     Value is the new height.  */
                {
                  /* Call function with current height as argument.
                     Value is the new height.  */
+                 struct face *face = FACE_FROM_ID (it->f, it->face_id);
                  Lisp_Object height;
                  height = safe_call1 (it->font_height,
                                       face->lface[LFACE_HEIGHT_INDEX]);
                  Lisp_Object height;
                  height = safe_call1 (it->font_height,
                                       face->lface[LFACE_HEIGHT_INDEX]);
@@ -4887,6 +4887,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                  /* Evaluate IT->font_height with `height' bound to the
                     current specified height to get the new height.  */
                  ptrdiff_t count = SPECPDL_INDEX ();
                  /* Evaluate IT->font_height with `height' bound to the
                     current specified height to get the new height.  */
                  ptrdiff_t count = SPECPDL_INDEX ();
+                 struct face *face = FACE_FROM_ID (it->f, it->face_id);
 
                  specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
                  value = safe_eval (it->font_height);
 
                  specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
                  value = safe_eval (it->font_height);
@@ -6096,7 +6097,7 @@ pop_it (struct it *it)
       break;
     case GET_FROM_STRING:
       {
       break;
     case GET_FROM_STRING:
       {
-       struct face *face = FACE_FROM_ID (it->f, it->face_id);
+       struct face *face = FACE_OPT_FROM_ID (it->f, it->face_id);
 
        /* Restore the face_box_p flag, since it could have been
           overwritten by the face of the object that we just finished
 
        /* Restore the face_box_p flag, since it could have been
           overwritten by the face of the object that we just finished
@@ -6641,7 +6642,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
      loading loadup.el, as the necessary character property tables are
      not yet available.  */
   it->bidi_p =
      loading loadup.el, as the necessary character property tables are
      not yet available.  */
   it->bidi_p =
-    NILP (Vpurify_flag)
+    !redisplay__inhibit_bidi
     && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
 
   if (s == NULL)
     && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
 
   if (s == NULL)
@@ -6777,7 +6778,7 @@ static next_element_function const get_next_element[NUM_IT_METHODS] =
    || ((IT)->cmp_it.stop_pos == (CHARPOS)                              \
        && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS,      \
                                 END_CHARPOS, (IT)->w,                  \
    || ((IT)->cmp_it.stop_pos == (CHARPOS)                              \
        && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS,      \
                                 END_CHARPOS, (IT)->w,                  \
-                                FACE_FROM_ID ((IT)->f, (IT)->face_id), \
+                                FACE_OPT_FROM_ID ((IT)->f, (IT)->face_id),     \
                                 (IT)->string)))
 
 
                                 (IT)->string)))
 
 
@@ -7080,6 +7081,19 @@ get_next_display_element (struct it *it)
                  goto display_control;
                }
 
                  goto display_control;
                }
 
+             /* Handle non-ascii hyphens in the mode where it only
+                gets highlighting.  */
+
+             if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
+               {
+                 /* Merge `nobreak-space' into the current face.  */
+                 face_id = merge_faces (it->f, Qnobreak_hyphen, 0,
+                                        it->face_id);
+                 XSETINT (it->ctl_chars[0], '-');
+                 ctl_len = 1;
+                 goto display_control;
+               }
+
              /* Handle sequences that start with the "escape glyph".  */
 
              /* the default escape glyph is \.  */
              /* Handle sequences that start with the "escape glyph".  */
 
              /* the default escape glyph is \.  */
@@ -7096,15 +7110,6 @@ get_next_display_element (struct it *it)
                         ? merge_faces (it->f, Qt, lface_id, it->face_id)
                         : merge_escape_glyph_face (it));
 
                         ? merge_faces (it->f, Qt, lface_id, it->face_id)
                         : merge_escape_glyph_face (it));
 
-             /* Draw non-ASCII hyphen with just highlighting: */
-
-             if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
-               {
-                 XSETINT (it->ctl_chars[0], '-');
-                 ctl_len = 1;
-                 goto display_control;
-               }
-
              /* Draw non-ASCII space/hyphen with escape glyph: */
 
              if (nonascii_space_p || nonascii_hyphen_p)
              /* Draw non-ASCII space/hyphen with escape glyph: */
 
              if (nonascii_space_p || nonascii_hyphen_p)
@@ -7202,7 +7207,7 @@ get_next_display_element (struct it *it)
       if (it->method == GET_FROM_STRING && it->sp)
        {
          int face_id = underlying_face_id (it);
       if (it->method == GET_FROM_STRING && it->sp)
        {
          int face_id = underlying_face_id (it);
-         struct face *face = FACE_FROM_ID (it->f, face_id);
+         struct face *face = FACE_OPT_FROM_ID (it->f, face_id);
 
          if (face)
            {
 
          if (face)
            {
@@ -7229,18 +7234,21 @@ get_next_display_element (struct it *it)
                {
                  ptrdiff_t ignore;
                  int next_face_id;
                {
                  ptrdiff_t ignore;
                  int next_face_id;
+                 bool text_from_string = false;
+                 /* Normally, the next buffer location is stored in
+                    IT->current.pos...  */
                  struct text_pos pos = it->current.pos;
 
                  struct text_pos pos = it->current.pos;
 
-                 /* For a string from a display property, the next
-                    buffer position is stored in the 'position'
+                 /* ...but for a string from a display property, the
+                    next buffer position is stored in the 'position'
                     member of the iteration stack slot below the
                     current one, see handle_single_display_spec.  By
                     member of the iteration stack slot below the
                     current one, see handle_single_display_spec.  By
-                    contrast, it->current.pos was not yet updated
-                    to point to that buffer position; that will
-                    happen in pop_it, after we finish displaying the
-                    current string.  Note that we already checked
-                    above that it->sp is positive, so subtracting one
-                    from it is safe.  */
+                    contrast, it->current.pos was not yet updated to
+                    point to that buffer position; that will happen
+                    in pop_it, after we finish displaying the current
+                    string.  Note that we already checked above that
+                    it->sp is positive, so subtracting one from it is
+                    safe.  */
                  if (it->from_disp_prop_p)
                    {
                      int stackp = it->sp - 1;
                  if (it->from_disp_prop_p)
                    {
                      int stackp = it->sp - 1;
@@ -7249,19 +7257,49 @@ get_next_display_element (struct it *it)
                      while (stackp >= 0
                             && STRINGP ((it->stack + stackp)->string))
                        stackp--;
                      while (stackp >= 0
                             && STRINGP ((it->stack + stackp)->string))
                        stackp--;
-                     eassert (stackp >= 0);
-                     pos = (it->stack + stackp)->position;
+                     if (stackp < 0)
+                       {
+                         /* If no stack slot was found for iterating
+                            a buffer, we are displaying text from a
+                            string, most probably the mode line or
+                            the header line, and that string has a
+                            display string on some of its
+                            characters.  */
+                         text_from_string = true;
+                         pos = it->stack[it->sp - 1].position;
+                       }
+                     else
+                       pos = (it->stack + stackp)->position;
                    }
                  else
                    INC_TEXT_POS (pos, it->multibyte_p);
 
                    }
                  else
                    INC_TEXT_POS (pos, it->multibyte_p);
 
-                 if (CHARPOS (pos) >= ZV)
+                 if (text_from_string)
+                   {
+                     Lisp_Object base_string = it->stack[it->sp - 1].string;
+
+                     if (CHARPOS (pos) >= SCHARS (base_string) - 1)
+                       it->end_of_box_run_p = true;
+                     else
+                       {
+                         next_face_id
+                           = face_at_string_position (it->w, base_string,
+                                                      CHARPOS (pos), 0,
+                                                      &ignore, face_id, false);
+                         it->end_of_box_run_p
+                           = (FACE_FROM_ID (it->f, next_face_id)->box
+                              == FACE_NO_BOX);
+                       }
+                   }
+                 else if (CHARPOS (pos) >= ZV)
                    it->end_of_box_run_p = true;
                  else
                    {
                    it->end_of_box_run_p = true;
                  else
                    {
-                     next_face_id = face_at_buffer_position
-                       (it->w, CHARPOS (pos), &ignore,
-                        CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, false, -1);
+                     next_face_id =
+                       face_at_buffer_position (it->w, CHARPOS (pos), &ignore,
+                                                CHARPOS (pos)
+                                                + TEXT_PROP_DISTANCE_LIMIT,
+                                                false, -1);
                      it->end_of_box_run_p
                        = (FACE_FROM_ID (it->f, next_face_id)->box
                           == FACE_NO_BOX);
                      it->end_of_box_run_p
                        = (FACE_FROM_ID (it->f, next_face_id)->box
                           == FACE_NO_BOX);
@@ -7702,8 +7740,8 @@ next_element_from_display_vector (struct it *it)
       /* Glyphs in the display vector could have the box face, so we
         need to set the related flags in the iterator, as
         appropriate.  */
       /* Glyphs in the display vector could have the box face, so we
         need to set the related flags in the iterator, as
         appropriate.  */
-      this_face = FACE_FROM_ID (it->f, it->face_id);
-      prev_face = FACE_FROM_ID (it->f, prev_face_id);
+      this_face = FACE_OPT_FROM_ID (it->f, it->face_id);
+      prev_face = FACE_OPT_FROM_ID (it->f, prev_face_id);
 
       /* Is this character the first character of a box-face run?  */
       it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
 
       /* Is this character the first character of a box-face run?  */
       it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
@@ -7728,7 +7766,7 @@ next_element_from_display_vector (struct it *it)
                                            it->saved_face_id);
            }
        }
                                            it->saved_face_id);
            }
        }
-      next_face = FACE_FROM_ID (it->f, next_face_id);
+      next_face = FACE_OPT_FROM_ID (it->f, next_face_id);
       it->end_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
                              && (!next_face
                                  || next_face->box == FACE_NO_BOX));
       it->end_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
                              && (!next_face
                                  || next_face->box == FACE_NO_BOX));
@@ -8772,6 +8810,8 @@ move_it_in_display_line_to (struct it *it,
                              ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
                              : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
                {
                              ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
                              : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
                {
+                 bool moved_forward = false;
+
                  if (/* IT->hpos == 0 means the very first glyph
                         doesn't fit on the line, e.g. a wide image.  */
                      it->hpos == 0
                  if (/* IT->hpos == 0 means the very first glyph
                         doesn't fit on the line, e.g. a wide image.  */
                      it->hpos == 0
@@ -8790,16 +8830,37 @@ move_it_in_display_line_to (struct it *it,
                             now that we know it fits in this row.  */
                          if (BUFFER_POS_REACHED_P ())
                            {
                             now that we know it fits in this row.  */
                          if (BUFFER_POS_REACHED_P ())
                            {
+                             bool can_wrap = true;
+
+                             /* If we are at a whitespace character
+                                that barely fits on this screen line,
+                                but the next character is also
+                                whitespace, we cannot wrap here.  */
+                             if (it->line_wrap == WORD_WRAP
+                                 && wrap_it.sp >= 0
+                                 && may_wrap
+                                 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+                               {
+                                 struct it tem_it;
+                                 void *tem_data = NULL;
+
+                                 SAVE_IT (tem_it, *it, tem_data);
+                                 set_iterator_to_next (it, true);
+                                 if (get_next_display_element (it)
+                                     && IT_DISPLAYING_WHITESPACE (it))
+                                   can_wrap = false;
+                                 RESTORE_IT (it, &tem_it, tem_data);
+                               }
                              if (it->line_wrap != WORD_WRAP
                                  || wrap_it.sp < 0
                              if (it->line_wrap != WORD_WRAP
                                  || wrap_it.sp < 0
-                                 /* If we've just found whitespace to
-                                    wrap, effectively ignore the
-                                    previous wrap point -- it is no
-                                    longer relevant, but we won't
-                                    have an opportunity to update it,
-                                    since we've reached the edge of
-                                    this screen line.  */
-                                 || (may_wrap
+                                 /* If we've just found whitespace
+                                    where we can wrap, effectively
+                                    ignore the previous wrap point --
+                                    it is no longer relevant, but we
+                                    won't have an opportunity to
+                                    update it, since we've reached
+                                    the edge of this screen line.  */
+                                 || (may_wrap && can_wrap
                                      && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
                                {
                                  it->hpos = hpos_before_this_char;
                                      && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
                                {
                                  it->hpos = hpos_before_this_char;
@@ -8842,6 +8903,7 @@ move_it_in_display_line_to (struct it *it,
                                  result = MOVE_POS_MATCH_OR_ZV;
                                  break;
                                }
                                  result = MOVE_POS_MATCH_OR_ZV;
                                  break;
                                }
+                             moved_forward = true;
                              if (BUFFER_POS_REACHED_P ())
                                {
                                  if (ITERATOR_AT_END_OF_LINE_P (it))
                              if (BUFFER_POS_REACHED_P ())
                                {
                                  if (ITERATOR_AT_END_OF_LINE_P (it))
@@ -8869,7 +8931,14 @@ move_it_in_display_line_to (struct it *it,
                     longer relevant, but we won't have an opportunity
                     to update it, since we are done with this screen
                     line.  */
                     longer relevant, but we won't have an opportunity
                     to update it, since we are done with this screen
                     line.  */
-                 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+                 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
+                     /* If the character after the one which set the
+                        may_wrap flag is also whitespace, we can't
+                        wrap here, since the screen line cannot be
+                        wrapped in the middle of whitespace.
+                        Therefore, wrap_it _is_ relevant in that
+                        case.  */
+                     && !(moved_forward && IT_DISPLAYING_WHITESPACE (it)))
                    {
                      /* If we've found TO_X, go back there, as we now
                         know the last word fits on this screen line.  */
                    {
                      /* If we've found TO_X, go back there, as we now
                         know the last word fits on this screen line.  */
@@ -9050,9 +9119,18 @@ move_it_in_display_line_to (struct it *it,
 
 #undef BUFFER_POS_REACHED_P
 
 
 #undef BUFFER_POS_REACHED_P
 
-  /* If we scanned beyond to_pos and didn't find a point to wrap at,
-     restore the saved iterator.  */
-  if (atpos_it.sp >= 0)
+  /* If we scanned beyond TO_POS, restore the saved iterator either to
+     the wrap point (if found), or to atpos/atx location.  We decide which
+     data to use to restore the saved iterator state by their X coordinates,
+     since buffer positions might increase non-monotonically with screen
+     coordinates due to bidi reordering.  */
+  if (result == MOVE_LINE_CONTINUED
+      && it->line_wrap == WORD_WRAP
+      && wrap_it.sp >= 0
+      && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
+         || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
+    RESTORE_IT (it, &wrap_it, wrap_data);
+  else if (atpos_it.sp >= 0)
     RESTORE_IT (it, &atpos_it, atpos_data);
   else if (atx_it.sp >= 0)
     RESTORE_IT (it, &atx_it, atx_data);
     RESTORE_IT (it, &atpos_it, atpos_data);
   else if (atx_it.sp >= 0)
     RESTORE_IT (it, &atx_it, atx_data);
@@ -9794,26 +9872,28 @@ the maximum pixel-height of all text lines.
 
 The optional argument FROM, if non-nil, specifies the first text
 position and defaults to the minimum accessible position of the buffer.
 
 The optional argument FROM, if non-nil, specifies the first text
 position and defaults to the minimum accessible position of the buffer.
-If FROM is t, use the minimum accessible position that is not a newline
-character.  TO, if non-nil, specifies the last text position and
+If FROM is t, use the minimum accessible position that starts a
+non-empty line.  TO, if non-nil, specifies the last text position and
 defaults to the maximum accessible position of the buffer.  If TO is t,
 defaults to the maximum accessible position of the buffer.  If TO is t,
-use the maximum accessible position that is not a newline character.
+use the maximum accessible position that ends a non-empty line.
 
 The optional argument X-LIMIT, if non-nil, specifies the maximum text
 width that can be returned.  X-LIMIT nil or omitted, means to use the
 
 The optional argument X-LIMIT, if non-nil, specifies the maximum text
 width that can be returned.  X-LIMIT nil or omitted, means to use the
-pixel-width of WINDOW's body; use this if you do not intend to change
-the width of WINDOW.  Use the maximum width WINDOW may assume if you
-intend to change WINDOW's width.  In any case, text whose x-coordinate
-is beyond X-LIMIT is ignored.  Since calculating the width of long lines
-can take some time, it's always a good idea to make this argument as
-small as possible; in particular, if the buffer contains long lines that
-shall be truncated anyway.
+pixel-width of WINDOW's body; use this if you want to know how high
+WINDOW should be become in order to fit all of its buffer's text with
+the width of WINDOW unaltered.  Use the maximum width WINDOW may assume
+if you intend to change WINDOW's width.  In any case, text whose
+x-coordinate is beyond X-LIMIT is ignored.  Since calculating the width
+of long lines can take some time, it's always a good idea to make this
+argument as small as possible; in particular, if the buffer contains
+long lines that shall be truncated anyway.
 
 The optional argument Y-LIMIT, if non-nil, specifies the maximum text
 
 The optional argument Y-LIMIT, if non-nil, specifies the maximum text
-height that can be returned.  Text lines whose y-coordinate is beyond
-Y-LIMIT are ignored.  Since calculating the text height of a large
-buffer can take some time, it makes sense to specify this argument if
-the size of the buffer is unknown.
+height (excluding the height of the mode- or header-line, if any) that
+can be returned.  Text lines whose y-coordinate is beyond Y-LIMIT are
+ignored.  Since calculating the text height of a large buffer can take
+some time, it makes sense to specify this argument if the size of the
+buffer is large or unknown.
 
 Optional argument MODE-AND-HEADER-LINE nil or omitted means do not
 include the height of the mode- or header-line of WINDOW in the return
 
 Optional argument MODE-AND-HEADER-LINE nil or omitted means do not
 include the height of the mode- or header-line of WINDOW in the return
@@ -9831,7 +9911,7 @@ include the height of both, if present, in the return value.  */)
   ptrdiff_t start, end, pos;
   struct text_pos startp;
   void *itdata = NULL;
   ptrdiff_t start, end, pos;
   struct text_pos startp;
   void *itdata = NULL;
-  int c, max_y = -1, x = 0, y = 0;
+  int c, max_x = 0, max_y = 0, x = 0, y = 0;
 
   CHECK_BUFFER (buffer);
   b = XBUFFER (buffer);
 
   CHECK_BUFFER (buffer);
   b = XBUFFER (buffer);
@@ -9876,11 +9956,13 @@ include the height of both, if present, in the return value.  */)
       end = max (start, min (XINT (to), ZV));
     }
 
       end = max (start, min (XINT (to), ZV));
     }
 
-  if (!NILP (y_limit))
-    {
-      CHECK_NUMBER (y_limit);
-      max_y = min (XINT (y_limit), INT_MAX);
-    }
+  if (!NILP (x_limit) && RANGED_INTEGERP (0, x_limit, INT_MAX))
+    max_x = XINT (x_limit);
+
+  if (NILP (y_limit))
+    max_y = INT_MAX;
+  else if (RANGED_INTEGERP (0, y_limit, INT_MAX))
+    max_y = XINT (y_limit);
 
   itdata = bidi_shelve_cache ();
   SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
 
   itdata = bidi_shelve_cache ();
   SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
@@ -9890,27 +9972,30 @@ include the height of both, if present, in the return value.  */)
     x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
   else
     {
     x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
   else
     {
-      CHECK_NUMBER (x_limit);
-      it.last_visible_x = min (XINT (x_limit), INFINITY);
+      it.last_visible_x = max_x;
       /* Actually, we never want move_it_to stop at to_x.  But to make
         sure that move_it_in_display_line_to always moves far enough,
       /* Actually, we never want move_it_to stop at to_x.  But to make
         sure that move_it_in_display_line_to always moves far enough,
-        we set it to INT_MAX and specify MOVE_TO_X.  */
-      x = move_it_to (&it, end, INT_MAX, max_y, -1,
-                     MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+        we set it to INT_MAX and specify MOVE_TO_X.  Also bound width
+        value by X-LIMIT.  */
+      x = min (move_it_to (&it, end, INT_MAX, max_y, -1,
+                          MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y),
+              max_x);
     }
 
     }
 
-  y = it.current_y + it.max_ascent + it.max_descent;
+  /* Subtract height of header-line which was counted automatically by
+     start_display.  */
+  y = min (it.current_y + it.max_ascent + it.max_descent
+          - WINDOW_HEADER_LINE_HEIGHT (w),
+          max_y);
 
 
-  if (!EQ (mode_and_header_line, Qheader_line)
-      && !EQ (mode_and_header_line, Qt))
-    /* Do not count the header-line which was counted automatically by
-       start_display.  */
-    y = y - WINDOW_HEADER_LINE_HEIGHT (w);
+  if (EQ (mode_and_header_line, Qheader_line)
+      || EQ (mode_and_header_line, Qt))
+    /* Re-add height of header-line as requested.  */
+    y = y + WINDOW_HEADER_LINE_HEIGHT (w);
 
   if (EQ (mode_and_header_line, Qmode_line)
       || EQ (mode_and_header_line, Qt))
 
   if (EQ (mode_and_header_line, Qmode_line)
       || EQ (mode_and_header_line, Qt))
-    /* Do count the mode-line which is not included automatically by
-       start_display.  */
+    /* Add height of mode-line as requested.  */
     y = y + WINDOW_MODE_LINE_HEIGHT (w);
 
   bidi_unshelve_cache (itdata, false);
     y = y + WINDOW_MODE_LINE_HEIGHT (w);
 
   bidi_unshelve_cache (itdata, false);
@@ -10488,25 +10573,21 @@ update_echo_area (void)
 static void
 ensure_echo_area_buffers (void)
 {
 static void
 ensure_echo_area_buffers (void)
 {
-  int i;
-
-  for (i = 0; i < 2; ++i)
+  for (int i = 0; i < 2; i++)
     if (!BUFFERP (echo_buffer[i])
        || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
       {
     if (!BUFFERP (echo_buffer[i])
        || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
       {
-       char name[30];
-       Lisp_Object old_buffer;
-       int j;
-
-       old_buffer = echo_buffer[i];
-       echo_buffer[i] = Fget_buffer_create
-         (make_formatted_string (name, " *Echo Area %d*", i));
+       Lisp_Object old_buffer = echo_buffer[i];
+       static char const name_fmt[] = " *Echo Area %d*";
+       char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
+       AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
+       echo_buffer[i] = Fget_buffer_create (lname);
        bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
        /* to force word wrap in echo area -
           it was decided to postpone this*/
        /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
 
        bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
        /* to force word wrap in echo area -
           it was decided to postpone this*/
        /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
 
-       for (j = 0; j < 2; ++j)
+       for (int j = 0; j < 2; j++)
          if (EQ (old_buffer, echo_area_buffer[j]))
            echo_area_buffer[j] = echo_buffer[i];
       }
          if (EQ (old_buffer, echo_area_buffer[j]))
            echo_area_buffer[j] = echo_buffer[i];
       }
@@ -10524,8 +10605,8 @@ ensure_echo_area_buffers (void)
    suitable buffer from echo_buffer[] and clear it.
 
    If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
    suitable buffer from echo_buffer[] and clear it.
 
    If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
-   that the current message becomes the last displayed one, make
-   choose a suitable buffer for echo_area_buffer[0], and clear it.
+   that the current message becomes the last displayed one, choose a
+   suitable buffer for echo_area_buffer[0], and clear it.
 
    Value is what FN returns.  */
 
 
    Value is what FN returns.  */
 
@@ -10559,7 +10640,7 @@ with_echo_area_buffer (struct window *w, int which,
        echo_area_buffer[this_one] = Qnil;
     }
 
        echo_area_buffer[this_one] = Qnil;
     }
 
-  /* Choose a suitable buffer from echo_buffer[] is we don't
+  /* Choose a suitable buffer from echo_buffer[] if we don't
      have one.  */
   if (NILP (echo_area_buffer[this_one]))
     {
      have one.  */
   if (NILP (echo_area_buffer[this_one]))
     {
@@ -11232,6 +11313,7 @@ clear_garbaged_frames (void)
   if (frame_garbaged)
     {
       Lisp_Object tail, frame;
   if (frame_garbaged)
     {
       Lisp_Object tail, frame;
+      struct frame *sf = SELECTED_FRAME ();
 
       FOR_EACH_FRAME (tail, frame)
        {
 
       FOR_EACH_FRAME (tail, frame)
        {
@@ -11239,7 +11321,13 @@ clear_garbaged_frames (void)
 
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
 
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
-             if (f->resized_p)
+             if (f->resized_p
+                 /* It makes no sense to redraw a non-selected TTY
+                    frame, since that will actually clear the
+                    selected frame, and might leave the selected
+                    frame with corrupted display, if it happens not
+                    to be marked garbaged.  */
+                 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
                redraw_frame (f);
              else
                clear_current_matrices (f);
                redraw_frame (f);
              else
                clear_current_matrices (f);
@@ -13461,7 +13549,7 @@ redisplay_internal (void)
   specbind (Qinhibit_free_realized_faces, Qnil);
 
   /* Record this function, so it appears on the profiler's backtraces.  */
   specbind (Qinhibit_free_realized_faces, Qnil);
 
   /* Record this function, so it appears on the profiler's backtraces.  */
-  record_in_backtrace (Qredisplay_internal, 0, 0);
+  record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
 
   FOR_EACH_FRAME (tail, frame)
     XFRAME (frame)->already_hscrolled_p = false;
 
   FOR_EACH_FRAME (tail, frame)
     XFRAME (frame)->already_hscrolled_p = false;
@@ -16999,7 +17087,16 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
            ignore_mouse_drag_p = true;
 #endif
         }
            ignore_mouse_drag_p = true;
 #endif
         }
+      ptrdiff_t count1 = SPECPDL_INDEX ();
+      /* x_consider_frame_title calls select-frame, which calls
+        resize_mini_window, which could resize the mini-window and by
+        that undo the effect of this redisplay cycle wrt minibuffer
+        and echo-area display.  Binding inhibit-redisplay to t makes
+        the call to resize_mini_window a no-op, thus avoiding the
+        adverse side effects.  */
+      specbind (Qinhibit_redisplay, Qt);
       x_consider_frame_title (w->frame);
       x_consider_frame_title (w->frame);
+      unbind_to (count1, Qnil);
 #endif
     }
 
 #endif
     }
 
@@ -18606,7 +18703,7 @@ try_window_id (struct window *w)
       eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
       row = find_last_row_displaying_text (w->current_matrix, &it,
                                           first_unchanged_at_end_row);
       eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
       row = find_last_row_displaying_text (w->current_matrix, &it,
                                           first_unchanged_at_end_row);
-      eassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
+      eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
       adjust_window_ends (w, row, true);
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "A"));
       adjust_window_ends (w, row, true);
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "A"));
@@ -18636,10 +18733,9 @@ try_window_id (struct window *w)
       struct glyph_row *current_row = current_matrix->rows + vpos;
       struct glyph_row *desired_row = desired_matrix->rows + vpos;
 
       struct glyph_row *current_row = current_matrix->rows + vpos;
       struct glyph_row *desired_row = desired_matrix->rows + vpos;
 
-      for (row = NULL;
-          row == NULL && vpos >= first_vpos;
-          --vpos, --current_row, --desired_row)
+      for (row = NULL; !row; --vpos, --current_row, --desired_row)
        {
        {
+         eassert (first_vpos <= vpos);
          if (desired_row->enabled_p)
            {
              if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
          if (desired_row->enabled_p)
            {
              if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
@@ -18649,7 +18745,6 @@ try_window_id (struct window *w)
            row  = current_row;
        }
 
            row  = current_row;
        }
 
-      eassert (row != NULL);
       w->window_end_vpos = vpos + 1;
       w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
       w->window_end_vpos = vpos + 1;
       w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
@@ -19574,15 +19669,14 @@ extend_face_to_end_of_line (struct it *it)
     return;
 
   /* The default face, possibly remapped. */
     return;
 
   /* The default face, possibly remapped. */
-  default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
+  default_face = FACE_OPT_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.  */
 
   /* 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.  */
-  if (it->face_before_selective_p)
-    face = FACE_FROM_ID (f, it->saved_face_id);
-  else
-    face = FACE_FROM_ID (f, it->face_id);
+  face = FACE_OPT_FROM_ID (f, (it->face_before_selective_p
+                              ? it->saved_face_id
+                              : it->face_id));
 
   if (FRAME_WINDOW_P (f)
       && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
 
   if (FRAME_WINDOW_P (f)
       && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
@@ -21180,7 +21274,7 @@ See also `bidi-paragraph-direction'.  */)
       || NILP (BVAR (buf, enable_multibyte_characters))
       /* When we are loading loadup.el, the character property tables
         needed for bidi iteration are not yet available.  */
       || NILP (BVAR (buf, enable_multibyte_characters))
       /* When we are loading loadup.el, the character property tables
         needed for bidi iteration are not yet available.  */
-      || !NILP (Vpurify_flag))
+      || redisplay__inhibit_bidi)
     return Qleft_to_right;
   else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
     return BVAR (buf, bidi_paragraph_direction);
     return Qleft_to_right;
   else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
     return BVAR (buf, bidi_paragraph_direction);
@@ -21304,7 +21398,7 @@ the `bidi-class' property of a character.  */)
          /* When we are loading loadup.el, the character property
             tables needed for bidi iteration are not yet
             available.  */
          /* When we are loading loadup.el, the character property
             tables needed for bidi iteration are not yet
             available.  */
-         || !NILP (Vpurify_flag))
+         || redisplay__inhibit_bidi)
        return Qnil;
 
       validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
        return Qnil;
 
       validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
@@ -21332,7 +21426,7 @@ the `bidi-class' property of a character.  */)
          /* When we are loading loadup.el, the character property
             tables needed for bidi iteration are not yet
             available.  */
          /* When we are loading loadup.el, the character property
             tables needed for bidi iteration are not yet
             available.  */
-         || !NILP (Vpurify_flag))
+         || redisplay__inhibit_bidi)
        return Qnil;
 
       set_buffer_temp (buf);
        return Qnil;
 
       set_buffer_temp (buf);
@@ -24556,7 +24650,6 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
   face = FACE_FROM_ID (f, glyph->face_id);
 
   /* Make sure X resources of the face are allocated.  */
   face = FACE_FROM_ID (f, glyph->face_id);
 
   /* Make sure X resources of the face are allocated.  */
-  eassert (face != NULL);
   prepare_face_for_display (f, face);
 
   if (face->font)
   prepare_face_for_display (f, face);
 
   if (face->font)
@@ -24688,7 +24781,7 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id,
   s->cmp_id = glyph->u.cmp.id;
   s->cmp_from = glyph->slice.cmp.from;
   s->cmp_to = glyph->slice.cmp.to + 1;
   s->cmp_id = glyph->u.cmp.id;
   s->cmp_from = glyph->slice.cmp.from;
   s->cmp_to = glyph->slice.cmp.to + 1;
-  s->face = FACE_FROM_ID (s->f, face_id);
+  s->face = FACE_OPT_FROM_ID (s->f, face_id);
   lgstring = composition_gstring_from_id (s->cmp_id);
   s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
   glyph++;
   lgstring = composition_gstring_from_id (s->cmp_id);
   s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
   glyph++;
@@ -25281,7 +25374,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
   do {                                                                     \
     int face_id = (row)->glyphs[area][START].face_id;                      \
 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
   do {                                                                     \
     int face_id = (row)->glyphs[area][START].face_id;                      \
-    struct face *base_face = FACE_FROM_ID (f, face_id);                            \
+    struct face *base_face = FACE_OPT_FROM_ID (f, face_id);                \
     ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id;                \
     struct composition *cmp = composition_table[cmp_id];                   \
     XChar2b *char2b;                                                       \
     ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id;                \
     struct composition *cmp = composition_table[cmp_id];                   \
     XChar2b *char2b;                                                       \
@@ -25736,6 +25829,7 @@ append_glyph (struct it *it)
       glyph->object = it->object;
       if (it->pixel_width > 0)
        {
       glyph->object = it->object;
       if (it->pixel_width > 0)
        {
+         eassert (it->pixel_width <= SHRT_MAX);
          glyph->pixel_width = it->pixel_width;
          glyph->padding_p = false;
        }
          glyph->pixel_width = it->pixel_width;
          glyph->padding_p = false;
        }
@@ -25816,6 +25910,7 @@ append_composite_glyph (struct it *it)
        }
       glyph->charpos = it->cmp_it.charpos;
       glyph->object = it->object;
        }
       glyph->charpos = it->cmp_it.charpos;
       glyph->object = it->object;
+      eassert (it->pixel_width <= SHRT_MAX);
       glyph->pixel_width = it->pixel_width;
       glyph->ascent = it->ascent;
       glyph->descent = it->descent;
       glyph->pixel_width = it->pixel_width;
       glyph->ascent = it->ascent;
       glyph->descent = it->descent;
@@ -25902,7 +25997,6 @@ produce_image_glyph (struct it *it)
   eassert (it->what == IT_IMAGE);
 
   face = FACE_FROM_ID (it->f, it->face_id);
   eassert (it->what == IT_IMAGE);
 
   face = FACE_FROM_ID (it->f, it->face_id);
-  eassert (face);
   /* Make sure X resources of the face is loaded.  */
   prepare_face_for_display (it->f, face);
 
   /* Make sure X resources of the face is loaded.  */
   prepare_face_for_display (it->f, face);
 
@@ -25917,7 +26011,6 @@ produce_image_glyph (struct it *it)
     }
 
   img = IMAGE_FROM_ID (it->f, it->image_id);
     }
 
   img = IMAGE_FROM_ID (it->f, it->image_id);
-  eassert (img);
   /* Make sure X resources of the image is loaded.  */
   prepare_image_for_display (it->f, img);
 
   /* Make sure X resources of the image is loaded.  */
   prepare_image_for_display (it->f, img);
 
@@ -26025,7 +26118,7 @@ produce_image_glyph (struct it *it)
        {
          glyph->charpos = CHARPOS (it->position);
          glyph->object = it->object;
        {
          glyph->charpos = CHARPOS (it->position);
          glyph->object = it->object;
-         glyph->pixel_width = it->pixel_width;
+         glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
          glyph->ascent = glyph_ascent;
          glyph->descent = it->descent;
          glyph->voffset = it->voffset;
          glyph->ascent = glyph_ascent;
          glyph->descent = it->descent;
          glyph->voffset = it->voffset;
@@ -26073,7 +26166,6 @@ produce_xwidget_glyph (struct it *it)
   eassert (it->what == IT_XWIDGET);
 
   struct face *face = FACE_FROM_ID (it->f, it->face_id);
   eassert (it->what == IT_XWIDGET);
 
   struct face *face = FACE_FROM_ID (it->f, it->face_id);
-  eassert (face);
   /* Make sure X resources of the face is loaded.  */
   prepare_face_for_display (it->f, face);
 
   /* Make sure X resources of the face is loaded.  */
   prepare_face_for_display (it->f, face);
 
@@ -26129,7 +26221,7 @@ produce_xwidget_glyph (struct it *it)
        {
          glyph->charpos = CHARPOS (it->position);
          glyph->object = it->object;
        {
          glyph->charpos = CHARPOS (it->position);
          glyph->object = it->object;
-         glyph->pixel_width = it->pixel_width;
+         glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
          glyph->ascent = glyph_ascent;
          glyph->descent = it->descent;
          glyph->voffset = it->voffset;
          glyph->ascent = glyph_ascent;
          glyph->descent = it->descent;
          glyph->voffset = it->voffset;
@@ -26215,7 +26307,9 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
        }
       glyph->charpos = CHARPOS (it->position);
       glyph->object = object;
        }
       glyph->charpos = CHARPOS (it->position);
       glyph->object = object;
-      glyph->pixel_width = width;
+      /* FIXME: It would be better to use TYPE_MAX here, but
+        __typeof__ is not portable enough...  */
+      glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
       glyph->ascent = ascent;
       glyph->descent = height - ascent;
       glyph->voffset = it->voffset;
       glyph->ascent = ascent;
       glyph->descent = height - ascent;
       glyph->voffset = it->voffset;
@@ -26666,6 +26760,7 @@ append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
        }
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
        }
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
+      eassert (it->pixel_width <= SHRT_MAX);
       glyph->pixel_width = it->pixel_width;
       glyph->ascent = it->ascent;
       glyph->descent = it->descent;
       glyph->pixel_width = it->pixel_width;
       glyph->ascent = it->ascent;
       glyph->descent = it->descent;
@@ -27957,7 +28052,7 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
              /* Using a block cursor on large images can be very annoying.
                 So use a hollow cursor for "large" images.
                 If image is not transparent (no mask), also use hollow cursor.  */
              /* Using a block cursor on large images can be very annoying.
                 So use a hollow cursor for "large" images.
                 If image is not transparent (no mask), also use hollow cursor.  */
-             struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
+             struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
              if (img != NULL && IMAGEP (img->spec))
                {
                  /* Arbitrarily, interpret "Large" as >32x32 and >NxN
              if (img != NULL && IMAGEP (img->spec))
                {
                  /* Arbitrarily, interpret "Large" as >32x32 and >NxN
@@ -30044,7 +30139,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
       /* Look for :pointer property on image.  */
       if (glyph != NULL && glyph->type == IMAGE_GLYPH)
        {
       /* Look for :pointer property on image.  */
       if (glyph != NULL && glyph->type == IMAGE_GLYPH)
        {
-         struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
+         struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
          if (img != NULL && IMAGEP (img->spec))
            {
              Lisp_Object image_map, hotspot;
          if (img != NULL && IMAGEP (img->spec))
            {
              Lisp_Object image_map, hotspot;
@@ -31070,7 +31165,7 @@ syms_of_xdisp (void)
   /* Non-nil means don't actually do any redisplay.  */
   DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
 
   /* Non-nil means don't actually do any redisplay.  */
   DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
 
-  DEFSYM (Qredisplay_internal, "redisplay_internal (C function)");
+  DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
 
   DEFVAR_BOOL("inhibit-message", inhibit_message,
               doc:  /* Non-nil means calls to `message' are not displayed.
 
   DEFVAR_BOOL("inhibit-message", inhibit_message,
               doc:  /* Non-nil means calls to `message' are not displayed.
@@ -31141,8 +31236,10 @@ They are still logged to the *Messages* buffer.  */);
   /* Name and number of the face used to highlight escape glyphs.  */
   DEFSYM (Qescape_glyph, "escape-glyph");
 
   /* Name and number of the face used to highlight escape glyphs.  */
   DEFSYM (Qescape_glyph, "escape-glyph");
 
-  /* Name and number of the face used to highlight non-breaking spaces.  */
+  /* Name and number of the face used to highlight non-breaking
+     spaces/hyphens.  */
   DEFSYM (Qnobreak_space, "nobreak-space");
   DEFSYM (Qnobreak_space, "nobreak-space");
+  DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
 
   /* The symbol 'image' which is the car of the lists used to represent
      images in Lisp.  Also a tool bar style.  */
 
   /* The symbol 'image' which is the car of the lists used to represent
      images in Lisp.  Also a tool bar style.  */
@@ -31254,7 +31351,7 @@ The face used for trailing whitespace is `trailing-whitespace'.  */);
     doc: /* Control highlighting of non-ASCII space and hyphen chars.
 If the value is t, Emacs highlights non-ASCII chars which have the
 same appearance as an ASCII space or hyphen, using the `nobreak-space'
     doc: /* Control highlighting of non-ASCII space and hyphen chars.
 If the value is t, Emacs highlights non-ASCII chars which have the
 same appearance as an ASCII space or hyphen, using the `nobreak-space'
-or `escape-glyph' face respectively.
+or `nobreak-hyphen' face respectively.
 
 U+00A0 (no-break space), U+00AD (soft hyphen), U+2010 (hyphen), and
 U+2011 (non-breaking hyphen) are affected.
 
 U+00A0 (no-break space), U+00AD (soft hyphen), U+2010 (hyphen), and
 U+2011 (non-breaking hyphen) are affected.
@@ -31339,8 +31436,11 @@ Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI).  */);
               Vtruncate_partial_width_windows,
     doc: /* Non-nil means truncate lines in windows narrower than the frame.
 For an integer value, truncate lines in each window narrower than the
               Vtruncate_partial_width_windows,
     doc: /* Non-nil means truncate lines in windows narrower than the frame.
 For an integer value, truncate lines in each window narrower than the
-full frame width, provided the window width is less than that integer;
-otherwise, respect the value of `truncate-lines'.
+full frame width, provided the total window width in column units is less
+than that integer; otherwise, respect the value of `truncate-lines'.
+The total width of the window is as returned by `window-total-width', it
+includes the fringes, the continuation and truncation glyphs, the
+display margins (if any), and the scroll bar
 
 For any other non-nil value, truncate lines in all windows that do
 not span the full frame width.
 
 For any other non-nil value, truncate lines in all windows that do
 not span the full frame width.
@@ -31375,7 +31475,7 @@ This variable is not guaranteed to be accurate except while processing
 
   DEFVAR_LISP ("frame-title-format", Vframe_title_format,
     doc: /* Template for displaying the title bar of visible frames.
 
   DEFVAR_LISP ("frame-title-format", Vframe_title_format,
     doc: /* Template for displaying the title bar of visible frames.
-(Assuming the window manager supports this feature.)
+\(Assuming the window manager supports this feature.)
 
 This variable has the same structure as `mode-line-format', except that
 the %c and %l constructs are ignored.  It is used only on frames for
 
 This variable has the same structure as `mode-line-format', except that
 the %c and %l constructs are ignored.  It is used only on frames for
@@ -31383,10 +31483,10 @@ which no explicit name has been set (see `modify-frame-parameters').  */);
 
   DEFVAR_LISP ("icon-title-format", Vicon_title_format,
     doc: /* Template for displaying the title bar of an iconified frame.
 
   DEFVAR_LISP ("icon-title-format", Vicon_title_format,
     doc: /* Template for displaying the title bar of an iconified frame.
-(Assuming the window manager supports this feature.)
+\(Assuming the window manager supports this feature.)
 This variable has the same structure as `mode-line-format' (which see),
 and is used only on frames for which no explicit name has been set
 This variable has the same structure as `mode-line-format' (which see),
 and is used only on frames for which no explicit name has been set
-(see `modify-frame-parameters').  */);
+\(see `modify-frame-parameters').  */);
   Vicon_title_format
     = Vframe_title_format
     = listn (CONSTYPE_PURE, 3,
   Vicon_title_format
     = Vframe_title_format
     = listn (CONSTYPE_PURE, 3,
@@ -31538,7 +31638,12 @@ A value of t means resize them to fit the text displayed in them.
 A value of `grow-only', the default, means let mini-windows grow only;
 they return to their normal size when the minibuffer is closed, or the
 echo area becomes empty.  */);
 A value of `grow-only', the default, means let mini-windows grow only;
 they return to their normal size when the minibuffer is closed, or the
 echo area becomes empty.  */);
-  Vresize_mini_windows = Qgrow_only;
+  /* Contrary to the doc string, we initialize this to nil, so that
+     loading loadup.el won't try to resize windows before loading
+     window.el, where some functions we need to call for this live.
+     We assign the 'grow-only' value right after loading window.el
+     during loadup.  */
+  Vresize_mini_windows = Qnil;
 
   DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
     doc: /* Alist specifying how to blink the cursor off.
 
   DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
     doc: /* Alist specifying how to blink the cursor off.
@@ -31746,6 +31851,12 @@ display table takes effect; in this case, Emacs does not consult
   DEFVAR_LISP ("redisplay--variables", Vredisplay__variables,
      doc: /* A hash-table of variables changing which triggers a thorough redisplay.  */);
   Vredisplay__variables = Qnil;
   DEFVAR_LISP ("redisplay--variables", Vredisplay__variables,
      doc: /* A hash-table of variables changing which triggers a thorough redisplay.  */);
   Vredisplay__variables = Qnil;
+
+  DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
+     doc: /* Non-nil means it is not safe to attempt bidi reordering for display.  */);
+  /* Initialize to t, since we need to disable reordering until
+     loadup.el successfully loads charprop.el.  */
+  redisplay__inhibit_bidi = true;
 }
 
 
 }