]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Avoid crashes due to insanely large columns in tabulated-list-format
[gnu-emacs] / src / xdisp.c
index e7626d1ce2594786ffd3a11b6db76e336285e107..cc2c951ce5c17997470b5b0807940e839cc9b7e8 100644 (file)
@@ -1,14 +1,14 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2015 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2016 Free Software Foundation,
 Inc.
 
 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
-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
@@ -292,7 +292,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "lisp.h"
 #include "atimer.h"
+#include "composite.h"
 #include "keyboard.h"
+#include "systime.h"
 #include "frame.h"
 #include "window.h"
 #include "termchar.h"
@@ -303,17 +305,16 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "indent.h"
 #include "commands.h"
 #include "keymap.h"
-#include "macros.h"
 #include "disptab.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "intervals.h"
 #include "coding.h"
-#include "process.h"
 #include "region-cache.h"
 #include "font.h"
 #include "fontset.h"
 #include "blockinput.h"
+#include "xwidget.h"
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -434,22 +435,58 @@ static Lisp_Object Vmessage_stack;
 
 static bool message_enable_multibyte;
 
-/* Nonzero if we should redraw the mode lines on the next redisplay.
-   If it has value REDISPLAY_SOME, then only redisplay the mode lines where
-   the `redisplay' bit has been set.  Otherwise, redisplay all mode lines
-   (the number used is then only used to track down the cause for this
-   full-redisplay).  */
+/* At each redisplay cycle, we should refresh everything there is to refresh.
+   To do that efficiently, we use many optimizations that try to make sure we
+   don't waste too much time updating things that haven't changed.
+   The coarsest such optimization is that, in the most common cases, we only
+   look at the selected-window.
+
+   To know whether other windows should be considered for redisplay, we use the
+   variable windows_or_buffers_changed: as long as it is 0, it means that we
+   have not noticed anything that should require updating anything else than
+   the selected-window.  If it is set to REDISPLAY_SOME, it means that since
+   last redisplay, some changes have been made which could impact other
+   windows.  To know which ones need redisplay, every buffer, window, and frame
+   has a `redisplay' bit, which (if true) means that this object needs to be
+   redisplayed.  If windows_or_buffers_changed is 0, we know there's no point
+   looking for those `redisplay' bits (actually, there might be some such bits
+   set, but then only on objects which aren't displayed anyway).
+
+   OTOH if it's non-zero we wil have to loop through all windows and then check
+   the `redisplay' bit of the corresponding window, frame, and buffer, in order
+   to decide whether that window needs attention or not.  Note that we can't
+   just look at the frame's redisplay bit to decide that the whole frame can be
+   skipped, since even if the frame's redisplay bit is unset, some of its
+   windows's redisplay bits may be set.
+
+   Mostly for historical reasons, windows_or_buffers_changed can also take
+   other non-zero values.  In that case, the precise value doesn't matter (it
+   encodes the cause of the setting but is only used for debugging purposes),
+   and what it means is that we shouldn't pay attention to any `redisplay' bits
+   and we should simply try and redisplay every window out there.  */
 
-int update_mode_lines;
+int windows_or_buffers_changed;
 
-/* Nonzero if window sizes or contents other than selected-window have changed
-   since last redisplay that finished.
-   If it has value REDISPLAY_SOME, then only redisplay the windows where
-   the `redisplay' bit has been set.  Otherwise, redisplay all windows
-   (the number used is then only used to track down the cause for this
-   full-redisplay).  */
+/* Nonzero if we should redraw the mode lines on the next redisplay.
+   Similarly to `windows_or_buffers_changed', If it has value REDISPLAY_SOME,
+   then only redisplay the mode lines in those buffers/windows/frames where the
+   `redisplay' bit has been set.
+   For any other value, redisplay all mode lines (the number used is then only
+   used to track down the cause for this full-redisplay).
+
+   Since the frame title uses the same %-constructs as the mode line
+   (except %c and %l), if this variable is non-zero, we also consider
+   redisplaying the title of each frame, see x_consider_frame_title.
+
+   The `redisplay' bits are the same as those used for
+   windows_or_buffers_changed, and setting windows_or_buffers_changed also
+   causes recomputation of the mode lines of all those windows.  IOW this
+   variable only has an effect if windows_or_buffers_changed is zero, in which
+   case we should only need to redisplay the mode-line of those objects with
+   a `redisplay' bit set but not the window's text content (tho we may still
+   need to refresh the text content of the selected-window).  */
 
-int windows_or_buffers_changed;
+int update_mode_lines;
 
 /* True after display_mode_line if %l was used and it displayed a
    line number.  */
@@ -584,6 +621,17 @@ bset_update_mode_line (struct buffer *b)
   b->text->redisplay = true;
 }
 
+void
+maybe_set_redisplay (Lisp_Object symbol)
+{
+  if (HASH_TABLE_P (Vredisplay__variables)
+      && hash_lookup (XHASH_TABLE (Vredisplay__variables), symbol, NULL) >= 0)
+    {
+      bset_update_mode_line (current_buffer);
+      current_buffer->prevent_redisplay_optimizations_p = true;
+    }
+}
+
 #ifdef GLYPH_DEBUG
 
 /* True means print traces of redisplay if compiled with
@@ -768,7 +816,7 @@ 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 redisplay_internal (void);
-static bool echo_area_display (bool);
+static void echo_area_display (bool);
 static void redisplay_windows (Lisp_Object);
 static void redisplay_window (Lisp_Object, bool);
 static Lisp_Object redisplay_window_error (Lisp_Object);
@@ -777,6 +825,7 @@ static Lisp_Object redisplay_window_1 (Lisp_Object);
 static bool set_cursor_from_row (struct window *, struct glyph_row *,
                                 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
                                 int, int);
+static bool cursor_row_fully_visible_p (struct window *, bool, bool);
 static bool update_menu_bar (struct frame *, bool, bool);
 static bool try_window_reusing_current_matrix (struct window *);
 static int try_window_id (struct window *);
@@ -807,6 +856,7 @@ static bool next_element_from_buffer (struct it *);
 static bool next_element_from_composition (struct it *);
 static bool next_element_from_image (struct it *);
 static bool next_element_from_stretch (struct it *);
+static bool next_element_from_xwidget (struct it *);
 static void load_overlay_strings (struct it *, ptrdiff_t);
 static bool get_next_display_element (struct it *);
 static enum move_it_result
@@ -2661,10 +2711,18 @@ init_iterator (struct it *it, struct window *w,
      free realized faces now because they depend on face definitions
      that might have changed.  Don't free faces while there might be
      desired matrices pending which reference these faces.  */
-  if (face_change && !inhibit_free_realized_faces)
+  if (!inhibit_free_realized_faces)
     {
-      face_change = false;
-      free_all_realized_faces (Qnil);
+      if (face_change)
+       {
+         face_change = false;
+         free_all_realized_faces (Qnil);
+       }
+      else if (XFRAME (w->frame)->face_change)
+       {
+         XFRAME (w->frame)->face_change = 0;
+         free_all_realized_faces (w->frame);
+       }
     }
 
   /* Perhaps remap BASE_FACE_ID to a user-specified alternative.  */
@@ -2888,7 +2946,7 @@ init_iterator (struct it *it, struct window *w,
         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;
 
@@ -3720,10 +3778,8 @@ handle_fontified_prop (struct it *it)
       else
        {
          Lisp_Object fns, fn;
-         struct gcpro gcpro1, gcpro2;
 
          fns = Qnil;
-         GCPRO2 (val, fns);
 
          for (; CONSP (val); val = XCDR (val))
            {
@@ -3748,8 +3804,6 @@ handle_fontified_prop (struct it *it)
              else
                safe_call1 (fn, pos);
            }
-
-         UNGCPRO;
        }
 
       unbind_to (count, Qnil);
@@ -4018,21 +4072,26 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
              /* With bidi iteration, the character before the current
                 in the visual order cannot be found by simple
                 iteration, because "reverse" reordering is not
-                supported.  Instead, we need to use the move_it_*
-                family of functions.  */
+                supported.  Instead, we need to start from the string
+                beginning and go all the way to the current string
+                position, remembering the previous position.  */
              /* Ignore face changes before the first visible
                 character on this display line.  */
              if (it->current_x <= it->first_visible_x)
                return it->face_id;
              SAVE_IT (it_copy, *it, it_copy_data);
-             /* Implementation note: Since move_it_in_display_line
-                works in the iterator geometry, and thinks the first
-                character is always the leftmost, even in R2L lines,
-                we don't need to distinguish between the R2L and L2R
-                cases here.  */
-             move_it_in_display_line (&it_copy, SCHARS (it_copy.string),
-                                      it_copy.current_x - 1, MOVE_TO_X);
-             charpos = IT_STRING_CHARPOS (it_copy);
+             IT_STRING_CHARPOS (it_copy) = 0;
+             bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
+
+             do
+               {
+                 charpos = IT_STRING_CHARPOS (it_copy);
+                 if (charpos >= SCHARS (it->string))
+                   break;
+                 bidi_move_to_visually_next (&it_copy.bidi_it);
+               }
+             while (IT_STRING_CHARPOS (it_copy) != IT_STRING_CHARPOS (*it));
+
              RESTORE_IT (it, it, it_copy_data);
            }
          else
@@ -4112,11 +4171,15 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
        {
          if (before_p)
            {
+             int current_x;
+
              /* With bidi iteration, the character before the current
                 in the visual order cannot be found by simple
                 iteration, because "reverse" reordering is not
                 supported.  Instead, we need to use the move_it_*
-                family of functions.  */
+                family of functions, and move to the previous
+                character starting from the beginning of the visual
+                line.  */
              /* Ignore face changes before the first visible
                 character on this display line.  */
              if (it->current_x <= it->first_visible_x)
@@ -4127,8 +4190,9 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
                 character is always the leftmost, even in R2L lines,
                 we don't need to distinguish between the R2L and L2R
                 cases here.  */
-             move_it_in_display_line (&it_copy, ZV,
-                                      it_copy.current_x - 1, MOVE_TO_X);
+             current_x = it_copy.current_x;
+             move_it_vertically_backward (&it_copy, 0);
+             move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
              pos = it_copy.current.pos;
              RESTORE_IT (it, it, it_copy_data);
            }
@@ -4522,11 +4586,15 @@ setup_for_ellipsis (struct it *it, int len)
   it->current.dpvec_index = 0;
   it->dpvec_face_id = -1;
 
-  /* Remember the current face id in case glyphs specify faces.
-     IT's face is restored in set_iterator_to_next.
-     saved_face_id was set to preceding char's face in handle_stop.  */
-  if (it->saved_face_id < 0 || it->saved_face_id != it->face_id)
-    it->saved_face_id = it->face_id = DEFAULT_FACE_ID;
+  /* Use IT->saved_face_id for the ellipsis, so that it has the same
+     face as the preceding text.  IT->saved_face_id was set in
+     handle_stop to the face of the preceding character, and will be
+     different from IT->face_id only if the invisible text skipped in
+     handle_invisible_prop has some non-default face on its first
+     character.  We thus ignore the face of the invisible text when we
+     display the ellipsis.  IT's face is restored in set_iterator_to_next.  */
+  if (it->saved_face_id >= 0)
+    it->face_id = it->saved_face_id;
 
   /* If the ellipsis represents buffer text, it means we advanced in
      the buffer, so we should no longer ignore overlay strings.  */
@@ -4625,6 +4693,9 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
   if (CONSP (spec)
       /* Simple specifications.  */
       && !EQ (XCAR (spec), Qimage)
+#ifdef HAVE_XWIDGETS
+      && !EQ (XCAR (spec), Qxwidget)
+#endif
       && !EQ (XCAR (spec), Qspace)
       && !EQ (XCAR (spec), Qwhen)
       && !EQ (XCAR (spec), Qslice)
@@ -4745,7 +4816,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
   if (!NILP (form) && !EQ (form, Qt))
     {
       ptrdiff_t count = SPECPDL_INDEX ();
-      struct gcpro gcpro1;
 
       /* Bind `object' to the object having the `display' property, a
         buffer or string.  Bind `position' to the position in the
@@ -4757,9 +4827,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
       specbind (Qobject, object);
       specbind (Qposition, make_number (CHARPOS (*position)));
       specbind (Qbuffer_position, make_number (bufpos));
-      GCPRO1 (form);
       form = safe_eval (form);
-      UNGCPRO;
       unbind_to (count, Qnil);
     }
 
@@ -5075,7 +5143,9 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                  || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
                      && valid_image_p (value))
 #endif /* not HAVE_WINDOW_SYSTEM */
-                 || (CONSP (value) && EQ (XCAR (value), Qspace)));
+             || (CONSP (value) && EQ (XCAR (value), Qspace))
+             || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
+                && valid_xwidget_spec_p (value)));
 
   if (valid_p && display_replaced == 0)
     {
@@ -5150,6 +5220,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          *position = it->position = start_pos;
          retval = 1 + (it->area == TEXT_AREA);
        }
+      else if (valid_xwidget_spec_p (value))
+       {
+          it->what = IT_XWIDGET;
+          it->method = GET_FROM_XWIDGET;
+          it->position = start_pos;
+         it->object = NILP (object) ? it->w->contents : object;
+         *position = start_pos;
+          it->xwidget = lookup_xwidget (value);
+       }
 #ifdef HAVE_WINDOW_SYSTEM
       else
        {
@@ -5902,6 +5981,16 @@ push_it (struct it *it, struct text_pos *position)
     case GET_FROM_STRETCH:
       p->u.stretch.object = it->object;
       break;
+    case GET_FROM_XWIDGET:
+      p->u.xwidget.object = it->object;
+      break;
+    case GET_FROM_BUFFER:
+    case GET_FROM_DISPLAY_VECTOR:
+    case GET_FROM_STRING:
+    case GET_FROM_C_STRING:
+      break;
+    default:
+      emacs_abort ();
     }
   p->position = position ? *position : it->position;
   p->current = it->current;
@@ -5972,6 +6061,7 @@ pop_it (struct it *it)
 {
   struct iterator_stack_entry *p;
   bool from_display_prop = it->from_disp_prop_p;
+  ptrdiff_t prev_pos = IT_CHARPOS (*it);
 
   eassert (it->sp > 0);
   --it->sp;
@@ -5995,6 +6085,9 @@ pop_it (struct it *it)
       it->object = p->u.image.object;
       it->slice = p->u.image.slice;
       break;
+    case GET_FROM_XWIDGET:
+      it->object = p->u.xwidget.object;
+      break;
     case GET_FROM_STRETCH:
       it->object = p->u.stretch.object;
       break;
@@ -6023,6 +6116,11 @@ pop_it (struct it *it)
          it->method = GET_FROM_BUFFER;
          it->object = it->w->contents;
        }
+      break;
+    case GET_FROM_C_STRING:
+      break;
+    default:
+      emacs_abort ();
     }
   it->end_charpos = p->end_charpos;
   it->string_nchars = p->string_nchars;
@@ -6060,6 +6158,11 @@ pop_it (struct it *it)
                   && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
               || (CONSP (it->object) && it->method == GET_FROM_STRETCH));
     }
+  /* If we move the iterator over text covered by a display property
+     to a new buffer position, any info about previously seen overlays
+     is no longer valid.  */
+  if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
+    it->ignore_overlay_strings_at_pos_p = false;
 }
 
 
@@ -6538,7 +6641,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 =
-    NILP (Vpurify_flag)
+    !redisplay__inhibit_bidi
     && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
 
   if (s == NULL)
@@ -6659,7 +6762,8 @@ static next_element_function const get_next_element[NUM_IT_METHODS] =
   next_element_from_string,
   next_element_from_c_string,
   next_element_from_image,
-  next_element_from_stretch
+  next_element_from_stretch,
+  next_element_from_xwidget,
 };
 
 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
@@ -6788,6 +6892,18 @@ merge_glyphless_glyph_face (struct it *it)
   return face_id;
 }
 
+/* Forget the `escape-glyph' and `glyphless-char' faces.  This should
+   be called before redisplaying windows, and when the frame's face
+   cache is freed.  */
+void
+forget_escape_and_glyphless_faces (void)
+{
+  last_escape_glyph_frame = NULL;
+  last_escape_glyph_face_id = (1 << FACE_ID_BITS);
+  last_glyphless_glyph_frame = NULL;
+  last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
+}
+
 /* Load IT's display element fields with information about the next
    display element from the current position of IT.  Value is false if
    end of buffer (or C string) is reached.  */
@@ -6884,9 +7000,10 @@ get_next_display_element (struct it *it)
             non-ASCII spaces and hyphens specially.  */
          if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
            {
-             if (c == 0xA0)
+             if (c == NO_BREAK_SPACE)
                nonascii_space_p = true;
-             else if (c == 0xAD || c == 0x2010 || c == 0x2011)
+             else if (c == SOFT_HYPHEN || c == HYPHEN
+                      || c == NON_BREAKING_HYPHEN)
                nonascii_hyphen_p = true;
            }
 
@@ -7112,30 +7229,72 @@ get_next_display_element (struct it *it)
                {
                  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;
 
-                 /* 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
-                    contrast, it->current.pos was is 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)
-                   pos = (it->stack + it->sp - 1)->position;
+                   {
+                     int stackp = it->sp - 1;
+
+                     /* Find the stack level with data from buffer.  */
+                     while (stackp >= 0
+                            && STRINGP ((it->stack + stackp)->string))
+                       stackp--;
+                     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);
 
-                 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
                    {
-                     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);
@@ -7507,6 +7666,8 @@ set_iterator_to_next (struct it *it, bool reseat_p)
 
     case GET_FROM_IMAGE:
     case GET_FROM_STRETCH:
+    case GET_FROM_XWIDGET:
+
       /* 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.  */
@@ -7968,6 +8129,13 @@ next_element_from_image (struct it *it)
   return true;
 }
 
+static bool
+next_element_from_xwidget (struct it *it)
+{
+  it->what = IT_XWIDGET;
+  return true;
+}
+
 
 /* Fill iterator IT with next display element from a stretch glyph
    property.  IT->object is the value of the text property.  Value is
@@ -9790,33 +9958,53 @@ include the height of both, if present, in the return value.  */)
                               Messages
  ***********************************************************************/
 
+/* Return the number of arguments the format string FORMAT needs.  */
+
+static ptrdiff_t
+format_nargs (char const *format)
+{
+  ptrdiff_t nargs = 0;
+  for (char const *p = format; (p = strchr (p, '%')); p++)
+    if (p[1] == '%')
+      p++;
+    else
+      nargs++;
+  return nargs;
+}
 
-/* Add a message with format string FORMAT and arguments ARG1 and ARG2
+/* Add a message with format string FORMAT and formatted arguments
    to *Messages*.  */
 
 void
-add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
+add_to_log (const char *format, ...)
 {
-  Lisp_Object msg, fmt;
-  char *buffer;
-  ptrdiff_t len;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-  USE_SAFE_ALLOCA;
-
-  fmt = msg = Qnil;
-  GCPRO4 (fmt, msg, arg1, arg2);
-
-  fmt = build_string (format);
-  msg = CALLN (Fformat, fmt, arg1, arg2);
+  va_list ap;
+  va_start (ap, format);
+  vadd_to_log (format, ap);
+  va_end (ap);
+}
 
-  len = SBYTES (msg) + 1;
-  buffer = SAFE_ALLOCA (len);
+void
+vadd_to_log (char const *format, va_list ap)
+{
+  ptrdiff_t form_nargs = format_nargs (format);
+  ptrdiff_t nargs = 1 + form_nargs;
+  Lisp_Object args[10];
+  eassert (nargs <= ARRAYELTS (args));
+  AUTO_STRING (args0, format);
+  args[0] = args0;
+  for (ptrdiff_t i = 1; i <= nargs; i++)
+    args[i] = va_arg (ap, Lisp_Object);
+  Lisp_Object msg = Qnil;
+  msg = Fformat_message (nargs, args);
+
+  ptrdiff_t len = SBYTES (msg) + 1;
+  USE_SAFE_ALLOCA;
+  char *buffer = SAFE_ALLOCA (len);
   memcpy (buffer, SDATA (msg), len);
 
-  message_dolog (buffer, len - 1, true, false);
+  message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
   SAFE_FREE ();
-
-  UNGCPRO;
 }
 
 
@@ -9855,7 +10043,6 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
       ptrdiff_t point_at_end = 0;
       ptrdiff_t zv_at_end = 0;
       Lisp_Object old_deactivate_mark;
-      struct gcpro gcpro1;
 
       old_deactivate_mark = Vdeactivate_mark;
       oldbuf = current_buffer;
@@ -9877,7 +10064,6 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
       set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
       oldzv = message_dolog_marker3;
       set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
-      GCPRO1 (old_deactivate_mark);
 
       if (PT == Z)
        point_at_end = 1;
@@ -10001,7 +10187,6 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
        TEMP_SET_PT_BOTH (marker_position (oldpoint),
                          marker_byte_position (oldpoint));
 
-      UNGCPRO;
       unchain_marker (XMARKER (oldpoint));
       unchain_marker (XMARKER (oldbegv));
       unchain_marker (XMARKER (oldzv));
@@ -10069,9 +10254,6 @@ message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
 void
 message3 (Lisp_Object m)
 {
-  struct gcpro gcpro1;
-
-  GCPRO1 (m);
   clear_message (true, true);
   cancel_echoing ();
 
@@ -10089,9 +10271,36 @@ message3 (Lisp_Object m)
     }
   if (! inhibit_message)
     message3_nolog (m);
-  UNGCPRO;
 }
 
+/* Log the message M to stderr.  Log an empty line if M is not a string.  */
+
+static void
+message_to_stderr (Lisp_Object m)
+{
+  if (noninteractive_need_newline)
+    {
+      noninteractive_need_newline = false;
+      fputc ('\n', stderr);
+    }
+  if (STRINGP (m))
+    {
+      Lisp_Object coding_system = Vlocale_coding_system;
+      Lisp_Object s;
+
+      if (!NILP (Vcoding_system_for_write))
+       coding_system = Vcoding_system_for_write;
+      if (!NILP (coding_system))
+       s = code_convert_string_norecord (m, coding_system, true);
+      else
+       s = m;
+
+      fwrite (SDATA (s), SBYTES (s), 1, stderr);
+    }
+  if (!cursor_in_echo_area)
+    fputc ('\n', stderr);
+  fflush (stderr);
+}
 
 /* The non-logging version of message3.
    This does not cancel echoing, because it is used for echoing.
@@ -10104,20 +10313,7 @@ message3_nolog (Lisp_Object m)
   struct frame *sf = SELECTED_FRAME ();
 
   if (FRAME_INITIAL_P (sf))
-    {
-      if (noninteractive_need_newline)
-       putc ('\n', stderr);
-      noninteractive_need_newline = false;
-      if (STRINGP (m))
-       {
-         Lisp_Object s = ENCODE_SYSTEM (m);
-
-         fwrite (SDATA (s), SBYTES (s), 1, stderr);
-       }
-      if (!cursor_in_echo_area)
-       fprintf (stderr, "\n");
-      fflush (stderr);
-    }
+    message_to_stderr (m);
   /* Error messages get reported properly by cmd_error, so this must be just an
      informative message; if the frame hasn't really been initialized yet, just
      toss it.  */
@@ -10184,24 +10380,12 @@ message_with_string (const char *m, Lisp_Object string, bool log)
 {
   CHECK_STRING (string);
 
+  bool need_message;
   if (noninteractive)
-    {
-      if (m)
-       {
-         /* ENCODE_SYSTEM below can GC and/or relocate the
-            Lisp data, so make sure we don't use it here.  */
-         eassert (relocatable_string_data_p (m) != 1);
-
-         if (noninteractive_need_newline)
-           putc ('\n', stderr);
-         noninteractive_need_newline = false;
-         fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string)));
-         if (!cursor_in_echo_area)
-           fprintf (stderr, "\n");
-         fflush (stderr);
-       }
-    }
-  else if (INTERACTIVE)
+    need_message = !!m;
+  else if (!INTERACTIVE)
+    need_message = false;
+  else
     {
       /* The frame whose minibuffer we're going to display the message on.
         It may be larger than the selected frame, so we need
@@ -10217,23 +10401,23 @@ message_with_string (const char *m, Lisp_Object string, bool log)
       /* Error messages get reported properly by cmd_error, so this must be
         just an informative message; if the frame hasn't really been
         initialized yet, just toss it.  */
-      if (f->glyphs_initialized_p)
-       {
-         struct gcpro gcpro1, gcpro2;
-
-         Lisp_Object fmt = build_string (m);
-         Lisp_Object msg = string;
-         GCPRO2 (fmt, msg);
+      need_message = f->glyphs_initialized_p;
+    }
 
-         msg = CALLN (Fformat, fmt, msg);
+  if (need_message)
+    {
+      AUTO_STRING (fmt, m);
+      Lisp_Object msg = CALLN (Fformat_message, fmt, string);
 
+      if (noninteractive)
+       message_to_stderr (msg);
+      else
+       {
          if (log)
            message3 (msg);
          else
            message3_nolog (msg);
 
-         UNGCPRO;
-
          /* Print should start at the beginning of the message
             buffer next time.  */
          message_buf_print = false;
@@ -10245,9 +10429,9 @@ message_with_string (const char *m, Lisp_Object string, bool log)
 /* Dump an informative message to the minibuf.  If M is 0, clear out
    any existing message, and let the mini-buffer text show through.
 
-   The message must be safe ASCII only.  If strings may contain escape
-   sequences or non-ASCII characters, convert them to Lisp strings and
-   use Fmessage.  */
+   The message must be safe ASCII and the format must not contain ` or
+   '.  If your message and format do not fit into this category,
+   convert your arguments to Lisp objects and use Fmessage instead.  */
 
 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
 vmessage (const char *m, va_list ap)
@@ -10373,8 +10557,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
-   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.  */
 
@@ -10408,7 +10592,7 @@ with_echo_area_buffer (struct window *w, int which,
        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]))
     {
@@ -10637,6 +10821,9 @@ display_echo_area (struct window *w)
      reset the echo_area_buffer in question to nil at the end because
      with_echo_area_buffer will sets it to an empty buffer.  */
   bool i = display_last_displayed_message_p;
+  /* According to the C99, C11 and C++11 standards, the integral value
+     of a "bool" is always 0 or 1, so this array access is safe here,
+     if oddly typed. */
   no_message_p = NILP (echo_area_buffer[i]);
 
   window_height_changed_p
@@ -10666,6 +10853,11 @@ display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2)
   Lisp_Object window;
   struct text_pos start;
 
+  /* We are about to enter redisplay without going through
+     redisplay_internal, so we need to forget these faces by hand
+     here.  */
+  forget_escape_and_glyphless_faces ();
+
   /* Do this before displaying, so that we have a large enough glyph
      matrix for the display.  If we can't get enough space for the
      whole text, display the last N lines.  That works by setting w->start.  */
@@ -11073,6 +11265,7 @@ clear_garbaged_frames (void)
   if (frame_garbaged)
     {
       Lisp_Object tail, frame;
+      struct frame *sf = SELECTED_FRAME ();
 
       FOR_EACH_FRAME (tail, frame)
        {
@@ -11080,7 +11273,13 @@ clear_garbaged_frames (void)
 
          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);
@@ -11095,11 +11294,10 @@ clear_garbaged_frames (void)
 }
 
 
-/* Redisplay the echo area of the selected frame.  If UPDATE_FRAME_P,
-   update selected_frame.  Value is true if the mini-windows height
-   has been changed.  */
+/* Redisplay the echo area of the selected frame.  If UPDATE_FRAME_P, update
+   selected_frame.  */
 
-static bool
+static void
 echo_area_display (bool update_frame_p)
 {
   Lisp_Object mini_window;
@@ -11114,14 +11312,14 @@ echo_area_display (bool update_frame_p)
 
   /* Don't display if frame is invisible or not yet initialized.  */
   if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
-    return false;
+    return;
 
 #ifdef HAVE_WINDOW_SYSTEM
   /* When Emacs starts, selected_frame may be the initial terminal
      frame.  If we let this through, a message would be displayed on
      the terminal.  */
   if (FRAME_INITIAL_P (XFRAME (selected_frame)))
-    return false;
+    return;
 #endif /* HAVE_WINDOW_SYSTEM */
 
   /* Redraw garbaged frames.  */
@@ -11159,7 +11357,7 @@ echo_area_display (bool update_frame_p)
                 pending input.  */
              ptrdiff_t count = SPECPDL_INDEX ();
              specbind (Qredisplay_dont_pause, Qt);
-             windows_or_buffers_changed = 44;
+             fset_redisplay (f);
              redisplay_internal ();
              unbind_to (count, Qnil);
            }
@@ -11195,7 +11393,16 @@ echo_area_display (bool update_frame_p)
   if (EQ (mini_window, selected_window))
     CHARPOS (this_line_start_pos) = 0;
 
-  return window_height_changed_p;
+  if (window_height_changed_p)
+    {
+      fset_redisplay (f);
+
+      /* If window configuration was changed, frames may have been
+        marked garbaged.  Clear them or we will experience
+        surprises wrt scrolling.
+        FIXME: How/why/when?  */
+      clear_garbaged_frames ();
+    }
 }
 
 /* True if W's buffer was changed but not saved.  */
@@ -11443,9 +11650,10 @@ x_consider_frame_title (Lisp_Object frame)
 {
   struct frame *f = XFRAME (frame);
 
-  if (FRAME_WINDOW_P (f)
-      || FRAME_MINIBUF_ONLY_P (f)
-      || f->explicit_name)
+  if ((FRAME_WINDOW_P (f)
+       || FRAME_MINIBUF_ONLY_P (f)
+       || f->explicit_name)
+      && NILP (Fframe_parameter (frame, Qtooltip)))
     {
       /* Do we have more than one visible frame on this X display?  */
       Lisp_Object tail, other_frame, fmt;
@@ -11525,7 +11733,6 @@ prepare_menu_bars (void)
 {
   bool all_windows = windows_or_buffers_changed || update_mode_lines;
   bool some_windows = REDISPLAY_SOME_P ();
-  struct gcpro gcpro1, gcpro2;
   Lisp_Object tooltip_frame;
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -11628,7 +11835,6 @@ prepare_menu_bars (void)
              /* Clear flag first in case we get an error below.  */
              FRAME_WINDOW_SIZES_CHANGED (f) = false;
              functions = Vwindow_size_change_functions;
-             GCPRO2 (tail, functions);
 
              while (CONSP (functions))
                {
@@ -11636,15 +11842,12 @@ prepare_menu_bars (void)
                    call1 (XCAR (functions), frame);
                  functions = XCDR (functions);
                }
-             UNGCPRO;
            }
 
-         GCPRO1 (tail);
          menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
 #ifdef HAVE_WINDOW_SYSTEM
          update_tool_bar (f, false);
 #endif
-         UNGCPRO;
        }
 
       unbind_to (count, Qnil);
@@ -11830,7 +12033,6 @@ update_tool_bar (struct frame *f, bool save_match_data)
          ptrdiff_t count = SPECPDL_INDEX ();
          Lisp_Object frame, new_tool_bar;
           int new_n_tool_bar;
-         struct gcpro gcpro1;
 
          /* Set current_buffer to the buffer of the selected
             window of the frame, so that we get the right local
@@ -11848,8 +12050,6 @@ update_tool_bar (struct frame *f, bool save_match_data)
              specbind (Qoverriding_local_map, Qnil);
            }
 
-         GCPRO1 (new_tool_bar);
-
          /* We must temporarily set the selected frame to this frame
             before calling tool_bar_items, because the calculation of
             the tool-bar keymap uses the selected frame (see
@@ -11881,8 +12081,6 @@ update_tool_bar (struct frame *f, bool save_match_data)
               unblock_input ();
             }
 
-         UNGCPRO;
-
          unbind_to (count, Qnil);
          set_buffer_internal_1 (prev);
        }
@@ -11899,11 +12097,9 @@ static void
 build_desired_tool_bar_string (struct frame *f)
 {
   int i, size, size_needed;
-  struct gcpro gcpro1, gcpro2;
   Lisp_Object image, plist;
 
   image = plist = Qnil;
-  GCPRO2 (image, plist);
 
   /* Prepare F->desired_tool_bar_string.  If we can reuse it, do so.
      Otherwise, make a new string.  */
@@ -11923,11 +12119,8 @@ build_desired_tool_bar_string (struct frame *f)
   else
     {
       AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
-      struct gcpro gcpro1;
-      GCPRO1 (props);
       Fremove_text_properties (make_number (0), make_number (size),
                               props, f->desired_tool_bar_string);
-      UNGCPRO;
     }
 
   /* Put a `display' property on the string for the images to display,
@@ -12040,8 +12233,6 @@ build_desired_tool_bar_string (struct frame *f)
       image = Fcons (Qimage, plist);
       AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
                  make_number (i * TOOL_BAR_ITEM_NSLOTS));
-      struct gcpro gcpro1;
-      GCPRO1 (props);
 
       /* Let the last image hide all remaining spaces in the tool bar
          string.  The string can be longer than needed when we reuse a
@@ -12052,11 +12243,8 @@ build_desired_tool_bar_string (struct frame *f)
        end = i + 1;
       Fadd_text_properties (make_number (i), make_number (end),
                            props, f->desired_tool_bar_string);
-      UNGCPRO;
 #undef PROP
     }
-
-  UNGCPRO;
 }
 
 
@@ -12268,6 +12456,7 @@ PIXELWISE non-nil means return the height of the tool bar in pixels.  */)
 static bool
 redisplay_tool_bar (struct frame *f)
 {
+  f->tool_bar_redisplayed = true;
 #if defined (USE_GTK) || defined (HAVE_NS)
 
   if (FRAME_EXTERNAL_TOOL_BAR (f))
@@ -13000,7 +13189,7 @@ text_outside_line_unchanged_p (struct window *w,
         beginning of a paragraph, before the first strong directional
         character, can change the base direction of the paragraph (unless
         the buffer specifies a fixed paragraph direction), which will
-        require to redisplay the whole paragraph.  It might be worthwhile
+        require redisplaying the whole paragraph.  It might be worthwhile
         to find the paragraph limits and widen the range of redisplayed
         lines to that, but for now just give up this optimization.  */
       if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
@@ -13339,10 +13528,9 @@ redisplay_internal (void)
   sw = w;
 
   pending = false;
-  last_escape_glyph_frame = NULL;
-  last_escape_glyph_face_id = (1 << FACE_ID_BITS);
-  last_glyphless_glyph_frame = NULL;
-  last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
+  forget_escape_and_glyphless_faces ();
+
+  inhibit_free_realized_faces = false;
 
   /* If face_change, init_iterator will free all realized faces, which
      includes the faces referenced from current matrices.  So, we
@@ -13391,7 +13579,7 @@ redisplay_internal (void)
          /* If cursor type has been changed on the frame
             other than selected, consider all frames.  */
          if (f != sf && f->cursor_type_changed)
-           update_mode_lines = 31;
+           fset_redisplay (f);
        }
       clear_desired_matrices (f);
     }
@@ -13444,7 +13632,33 @@ redisplay_internal (void)
             echo-area doesn't show through.  */
          && !MINI_WINDOW_P (XWINDOW (selected_window))))
     {
-      bool window_height_changed_p = echo_area_display (false);
+      echo_area_display (false);
+
+      /* If echo_area_display resizes the mini-window, the redisplay and
+        window_sizes_changed flags of the selected frame are set, but
+        it's too late for the hooks in window-size-change-functions,
+        which have been examined already in prepare_menu_bars.  So in
+        that case we call the hooks here only for the selected frame.  */
+      if (sf->redisplay && FRAME_WINDOW_SIZES_CHANGED (sf))
+       {
+         Lisp_Object functions;
+         ptrdiff_t count1 = SPECPDL_INDEX ();
+
+         record_unwind_save_match_data ();
+
+         /* Clear flag first in case we get an error below.  */
+         FRAME_WINDOW_SIZES_CHANGED (sf) = false;
+         functions = Vwindow_size_change_functions;
+
+         while (CONSP (functions))
+           {
+             if (!EQ (XCAR (functions), Qt))
+               call1 (XCAR (functions), selected_frame);
+             functions = XCDR (functions);
+           }
+
+         unbind_to (count1, Qnil);
+       }
 
       if (message_cleared_p)
        update_miniwindow_p = true;
@@ -13457,21 +13671,32 @@ redisplay_internal (void)
         the echo area.  */
       if (!display_last_displayed_message_p)
        message_cleared_p = false;
-
-      if (window_height_changed_p)
-       {
-         windows_or_buffers_changed = 50;
-
-         /* If window configuration was changed, frames may have been
-            marked garbaged.  Clear them or we will experience
-            surprises wrt scrolling.  */
-         clear_garbaged_frames ();
-       }
     }
   else if (EQ (selected_window, minibuf_window)
           && (current_buffer->clip_changed || window_outdated (w))
           && resize_mini_window (w, false))
     {
+      if (sf->redisplay)
+       {
+         Lisp_Object functions;
+         ptrdiff_t count1 = SPECPDL_INDEX ();
+
+         record_unwind_save_match_data ();
+
+         /* Clear flag first in case we get an error below.  */
+         FRAME_WINDOW_SIZES_CHANGED (sf) = false;
+         functions = Vwindow_size_change_functions;
+
+         while (CONSP (functions))
+           {
+             if (!EQ (XCAR (functions), Qt))
+               call1 (XCAR (functions), selected_frame);
+             functions = XCDR (functions);
+           }
+
+         unbind_to (count1, Qnil);
+       }
+
       /* Resized active mini-window to fit the size of what it is
          showing if its contents might have changed.  */
       must_finish = true;
@@ -13499,9 +13724,12 @@ redisplay_internal (void)
   consider_all_windows_p = (update_mode_lines
                            || windows_or_buffers_changed);
 
-#define AINC(a,i) \
-  if (VECTORP (a) && i >= 0 && i < ASIZE (a) && INTEGERP (AREF (a, i))) \
-    ASET (a, i, make_number (1 + XINT (AREF (a, i))))
+#define AINC(a,i)                                                      \
+  {                                                                    \
+    Lisp_Object entry = Fgethash (make_number (i), a, make_number (0));        \
+    if (INTEGERP (entry))                                              \
+      Fputhash (make_number (i), make_number (1 + XINT (entry)), a);   \
+  }
 
   AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
   AINC (Vredisplay__mode_lines_cause, update_mode_lines);
@@ -13520,6 +13748,7 @@ redisplay_internal (void)
       && FRAME_VISIBLE_P (XFRAME (w->frame))
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
       && !XFRAME (w->frame)->cursor_type_changed
+      && !XFRAME (w->frame)->face_change
       /* Make sure recorded data applies to current buffer, etc.  */
       && this_line_buffer == current_buffer
       && match_p
@@ -13693,11 +13922,16 @@ redisplay_internal (void)
              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 (cursor_row_fully_visible_p (w, false, true))
+               {
 #ifdef GLYPH_DEBUG
-             *w->desired_matrix->method = 0;
-             debug_method_add (w, "optimization 3");
+                 *w->desired_matrix->method = 0;
+                 debug_method_add (w, "optimization 3");
 #endif
-             goto update;
+                 goto update;
+               }
+             else
+               goto cancel;
            }
          else
            goto cancel;
@@ -13715,7 +13949,8 @@ redisplay_internal (void)
 #endif
 
   /* Build desired matrices, and update the display.  If
-     consider_all_windows_p, do it for all windows on all frames.
+     consider_all_windows_p, do it for all windows on all frames that
+     require redisplay, as specified by their 'redisplay' flag.
      Otherwise do it for selected_window, only.  */
 
   if (consider_all_windows_p)
@@ -13736,23 +13971,12 @@ redisplay_internal (void)
            continue;
 
        retry_frame:
-
-#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_GTK) && !defined (HAVE_NS)
-         /* Redisplay internal tool bar if this is the first time so we
-            can adjust the frame height right now, if necessary.  */
-         if (!f->tool_bar_redisplayed_once)
-           {
-             if (redisplay_tool_bar (f))
-               adjust_frame_glyphs (f);
-             f->tool_bar_redisplayed_once = true;
-           }
-#endif
-
          if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
              bool gcscrollbars
                /* Only GC scrollbars when we redisplay the whole frame.  */
                = f->redisplay || !REDISPLAY_SOME_P ();
+             bool f_redisplay_flag = f->redisplay;
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
              if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
@@ -13796,6 +14020,20 @@ redisplay_internal (void)
                        goto retry_frame;
                    }
 
+                 /* If the frame's redisplay flag was not set before
+                    we went about redisplaying its windows, but it is
+                    set now, that means we employed some redisplay
+                    optimizations inside redisplay_windows, and
+                    bypassed producing some screen lines.  But if
+                    f->redisplay is now set, it might mean the old
+                    faces are no longer valid (e.g., if redisplaying
+                    some window called some Lisp which defined a new
+                    face or redefined an existing face), so trying to
+                    use them in update_frame will segfault.
+                    Therefore, we must redisplay this frame.  */
+                 if (!f_redisplay_flag && f->redisplay)
+                   goto retry_frame;
+
                  /* Prevent various kinds of signals during display
                     update.  stdio is not robust about handling
                     signals, which can cause an apparent I/O error.  */
@@ -13849,9 +14087,27 @@ redisplay_internal (void)
       /* Compare desired and current matrices, perform output.  */
 
     update:
-      /* If fonts changed, display again.  */
-      if (sf->fonts_changed)
-       goto retry;
+      /* If fonts changed, display again.  Likewise if redisplay_window_1
+        above caused some change (e.g., a change in faces) that requires
+        considering the entire frame again.  */
+      if (sf->fonts_changed || sf->redisplay)
+       {
+         if (sf->redisplay)
+           {
+             /* Set this to force a more thorough redisplay.
+                Otherwise, we might immediately loop back to the
+                above "else-if" clause (since all the conditions that
+                led here might still be true), and we will then
+                infloop, because the selected-frame's redisplay flag
+                is not (and cannot be) reset.  */
+             windows_or_buffers_changed = 50;
+           }
+         goto retry;
+       }
+
+      /* Prevent freeing of realized faces, since desired matrices are
+        pending that reference the faces we computed and cached.  */
+      inhibit_free_realized_faces = true;
 
       /* Prevent various kinds of signals during display update.
         stdio is not robust about handling signals,
@@ -15878,6 +16134,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       && REDISPLAY_SOME_P ()
       && !w->redisplay
       && !w->update_mode_line
+      && !f->face_change
       && !f->redisplay
       && !buffer->text->redisplay
       && BUF_PT (buffer) == w->last_point)
@@ -16144,9 +16401,33 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       if (w->cursor.vpos < 0)
        {
          /* If point does not appear, try to move point so it does
-            appear. The desired matrix has been built above, so we
-            can use it here.  */
-         new_vpos = window_box_height (w) / 2;
+            appear.  The desired matrix has been built above, so we
+            can use it here.  First see if point is in invisible
+            text, and if so, move it to the first visible buffer
+            position past that.  */
+         struct glyph_row *r = NULL;
+         Lisp_Object invprop =
+           get_char_property_and_overlay (make_number (PT), Qinvisible,
+                                          Qnil, NULL);
+
+         if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
+           {
+             ptrdiff_t alt_pt;
+             Lisp_Object invprop_end =
+               Fnext_single_char_property_change (make_number (PT), Qinvisible,
+                                                  Qnil, Qnil);
+
+             if (NATNUMP (invprop_end))
+               alt_pt = XFASTINT (invprop_end);
+             else
+               alt_pt = ZV;
+             r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
+                                     NULL, 0);
+           }
+         if (r)
+           new_vpos = MATRIX_ROW_BOTTOM_Y (r);
+         else  /* Give up and just move to the middle of the window.  */
+           new_vpos = window_box_height (w) / 2;
        }
 
       if (!cursor_row_fully_visible_p (w, false, false))
@@ -16563,6 +16844,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   startp = run_window_scroll_functions (window, it.current.pos);
 
   /* Redisplay the window.  */
+  bool use_desired_matrix = false;
   if (!current_matrix_up_to_date_p
       || windows_or_buffers_changed
       || f->cursor_type_changed
@@ -16573,7 +16855,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       || MINI_WINDOW_P (w)
       || !(used_current_matrix_p
           = try_window_reusing_current_matrix (w)))
-    try_window (window, startp, 0);
+    use_desired_matrix = (try_window (window, startp, 0) == 1);
 
   /* If new fonts have been loaded (due to fontsets), give up.  We
      have to start a new redisplay since we need to re-adjust glyph
@@ -16613,9 +16895,15 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
      and similar ones.  */
   if (w->cursor.vpos < 0)
     {
+      /* Prefer the desired matrix to the current matrix, if possible,
+        in the fallback calculations below.  This is because using
+        the current matrix might completely goof, e.g. if its first
+        row is after point.  */
+      struct glyph_matrix *matrix =
+       use_desired_matrix ? w->desired_matrix : w->current_matrix;
       /* First, try locating the proper glyph row for PT.  */
       struct glyph_row *row =
-       row_containing_pos (w, PT, w->current_matrix->rows, NULL, 0);
+       row_containing_pos (w, PT, matrix->rows, NULL, 0);
 
       /* Sometimes point is at the beginning of invisible text that is
         before the 1st character displayed in the row.  In that case,
@@ -16640,8 +16928,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
                alt_pos = XFASTINT (invis_end);
              else
                alt_pos = ZV;
-             row = row_containing_pos (w, alt_pos, w->current_matrix->rows,
-                                       NULL, 0);
+             row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
            }
        }
       /* Finally, fall back on the first row of the window after the
@@ -16649,11 +16936,11 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
         displaying the cursor at all.  */
       if (!row)
        {
-         row = w->current_matrix->rows;
+         row = matrix->rows;
          if (row->mode_line_p)
            ++row;
        }
-      set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+      set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
     }
 
   if (!cursor_row_fully_visible_p (w, false, false))
@@ -16673,7 +16960,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       if (scroll_conservatively > SCROLL_LIMIT)
        {
          int window_total_lines
-           = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) * frame_line_height;
+           = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
          int margin =
            scroll_margin > 0
            ? min (scroll_margin, window_total_lines / 4)
@@ -16759,7 +17046,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 
  finish_menu_bars:
 
-  /* When we reach a frame's selected window, redo the frame's menu bar.  */
+  /* When we reach a frame's selected window, redo the frame's menu
+     bar and the frame's title.  */
   if (update_mode_line
       && EQ (FRAME_SELECTED_WINDOW (f), window))
     {
@@ -16794,6 +17082,16 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
            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);
+      unbind_to (count1, Qnil);
 #endif
     }
 
@@ -17636,7 +17934,7 @@ row_containing_pos (struct window *w, ptrdiff_t charpos,
   while (true)
     {
       /* Give up if we have gone too far.  */
-      if (end && row >= end)
+      if ((end && row >= end) || !row->enabled_p)
        return NULL;
       /* This formerly returned if they were equal.
         I think that both quantities are of a "last plus one" type;
@@ -17833,7 +18131,7 @@ try_window_id (struct window *w)
      beginning of a paragraph, before the first strong directional
      character, can change the base direction of the paragraph (unless
      the buffer specifies a fixed paragraph direction), which will
-     require to redisplay the whole paragraph.  It might be worthwhile
+     require redisplaying the whole paragraph.  It might be worthwhile
      to find the paragraph limits and widen the range of redisplayed
      lines to that, but for now just give up this optimization and
      redisplay from scratch.  */
@@ -18591,6 +18889,29 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
               glyph->left_box_line_p,
               glyph->right_box_line_p);
     }
+  else if (glyph->type == XWIDGET_GLYPH)
+    {
+#ifndef HAVE_XWIDGETS
+      eassume (false);
+#else
+      fprintf (stderr,
+              "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+              glyph - row->glyphs[TEXT_AREA],
+              'X',
+              glyph->charpos,
+              (BUFFERP (glyph->object)
+               ? 'B'
+               : (STRINGP (glyph->object)
+                  ? 'S'
+                  : '-')),
+              glyph->pixel_width,
+              glyph->u.xwidget,
+              '.',
+              glyph->face_id,
+              glyph->left_box_line_p,
+              glyph->right_box_line_p);
+#endif
+    }
 }
 
 
@@ -19222,7 +19543,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
             funny, and height of empty lines will be incorrect.  */
          g = it->glyph_row->glyphs[TEXT_AREA] + n;
          struct font *font = face->font ? face->font : FRAME_FONT (it->f);
-         if (n == 0 || it->glyph_row->height < font->pixel_size)
+         if (n == 0)
            {
              Lisp_Object height, total_height;
              int extra_line_spacing = it->extra_line_spacing;
@@ -19783,7 +20104,8 @@ push_prefix_prop (struct it *it, Lisp_Object prop)
 
   eassert (it->method == GET_FROM_BUFFER
           || it->method == GET_FROM_DISPLAY_VECTOR
-          || it->method == GET_FROM_STRING);
+          || it->method == GET_FROM_STRING
+          || it->method == GET_FROM_IMAGE);
 
   /* We need to save the current buffer/string position, so it will be
      restored by pop_it, because iterate_out_of_display_property
@@ -20950,7 +21272,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 (Vpurify_flag))
+      || redisplay__inhibit_bidi)
     return Qleft_to_right;
   else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
     return BVAR (buf, bidi_paragraph_direction);
@@ -21039,7 +21361,7 @@ window-specific overlays, which can affect the results.
 
 Strong directional characters `L', `R', and `AL' can have their
 intrinsic directionality overridden by directional override
-control characters RLO \(u+202e) and LRO \(u+202d).  See the
+control characters RLO (u+202e) and LRO (u+202d).  See the
 function `get-char-code-property' for a way to inquire about
 the `bidi-class' property of a character.  */)
   (Lisp_Object from, Lisp_Object to, Lisp_Object object)
@@ -21074,7 +21396,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.  */
-         || !NILP (Vpurify_flag))
+         || redisplay__inhibit_bidi)
        return Qnil;
 
       validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
@@ -21102,7 +21424,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.  */
-         || !NILP (Vpurify_flag))
+         || redisplay__inhibit_bidi)
        return Qnil;
 
       set_buffer_temp (buf);
@@ -24064,7 +24386,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
        prop = Qnil;
     }
 
-  if (INTEGERP (prop) || FLOATP (prop))
+  if (NUMBERP (prop))
     {
       int base_unit = (width_p
                       ? FRAME_COLUMN_WIDTH (it->f)
@@ -24088,6 +24410,11 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
 
              return OK_PIXELS (width_p ? img->width : img->height);
            }
+         if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
+           {
+              // TODO: Don't return dummy size.
+              return OK_PIXELS (100);
+            }
 #endif
          if (EQ (car, Qplus) || EQ (car, Qminus))
            {
@@ -24116,7 +24443,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
            car = Qnil;
        }
 
-      if (INTEGERP (car) || FLOATP (car))
+      if (NUMBERP (car))
        {
          double fact;
          pixels = XFLOATINT (car);
@@ -24593,6 +24920,18 @@ fill_image_glyph_string (struct glyph_string *s)
 }
 
 
+#ifdef HAVE_XWIDGETS
+static void
+fill_xwidget_glyph_string (struct glyph_string *s)
+{
+  eassert (s->first_glyph->type == XWIDGET_GLYPH);
+  s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
+  s->font = s->face->font;
+  s->width = s->first_glyph->pixel_width;
+  s->ybase += s->first_glyph->voffset;
+  s->xwidget = s->first_glyph->u.xwidget;
+}
+#endif
 /* Fill glyph string S from a sequence of stretch glyphs.
 
    START is the index of the first glyph to consider,
@@ -24978,6 +25317,22 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
        }                                                               \
      while (false)
 
+#ifndef HAVE_XWIDGETS
+# define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+     eassume (false)
+#else
+# define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+     do                                                                        \
+       {                                                               \
+        s = alloca (sizeof *s);                                        \
+        INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);          \
+        fill_xwidget_glyph_string (s);                                 \
+        append_glyph_string (&(HEAD), &(TAIL), s);                     \
+        ++(START);                                                     \
+         s->x = (X);                                                   \
+       }                                                               \
+     while (false)
+#endif
 
 /* Add a glyph string for a sequence of character glyphs to the list
    of strings between HEAD and TAIL.  START is the index of the first
@@ -25099,7 +25454,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
    to allocate glyph strings (because draw_glyphs can be called
    asynchronously).  */
 
-#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)     \
+#define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X)   \
   do                                                                   \
     {                                                                  \
       HEAD = TAIL = NULL;                                              \
@@ -25130,15 +25485,22 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
            case IMAGE_GLYPH:                                           \
              BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL,         \
                                        HL, X, LAST_X);                 \
-             break;                                                    \
-                                                                       \
+             break;
+
+#define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X)  \
+            case XWIDGET_GLYPH:                                         \
+              BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL,       \
+                                          HL, X, LAST_X);               \
+              break;
+
+#define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)   \
            case GLYPHLESS_GLYPH:                                       \
              BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL,     \
                                            HL, X, LAST_X);             \
              break;                                                    \
                                                                        \
            default:                                                    \
-             emacs_abort ();                                                   \
+             emacs_abort ();                                           \
            }                                                           \
                                                                        \
          if (s)                                                        \
@@ -25150,6 +25512,12 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
     } while (false)
 
 
+#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)     \
+    BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X)       \
+    BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X)      \
+    BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
+
+
 /* Draw glyphs between START and END in AREA of ROW on window W,
    starting at x-position X.  X is relative to AREA in W.  HL is a
    face-override with the following meaning:
@@ -25460,6 +25828,7 @@ append_glyph (struct it *it)
       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;
        }
@@ -25540,6 +25909,7 @@ append_composite_glyph (struct it *it)
        }
       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;
@@ -25749,7 +26119,7 @@ produce_image_glyph (struct it *it)
        {
          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;
@@ -25788,6 +26158,109 @@ produce_image_glyph (struct it *it)
     }
 }
 
+static void
+produce_xwidget_glyph (struct it *it)
+{
+#ifdef HAVE_XWIDGETS
+  struct xwidget *xw;
+  int glyph_ascent, crop;
+  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);
+
+  xw = it->xwidget;
+  it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
+  it->descent = xw->height/2;
+  it->phys_descent = it->descent;
+  it->pixel_width = xw->width;
+  /* It's quite possible for images to have an ascent greater than
+     their height, so don't get confused in that case.  */
+  if (it->descent < 0)
+    it->descent = 0;
+
+  it->nglyphs = 1;
+
+  if (face->box != FACE_NO_BOX)
+    {
+      if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
+
+      if (it->start_of_box_run_p)
+       it->pixel_width += eabs (face->box_line_width);
+      it->pixel_width += eabs (face->box_line_width);
+    }
+
+  take_vertical_position_into_account (it);
+
+  /* Automatically crop wide image glyphs at right edge so we can
+     draw the cursor on same display row.  */
+  crop = it->pixel_width - (it->last_visible_x - it->current_x);
+  if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
+    it->pixel_width -= crop;
+
+  if (it->glyph_row)
+    {
+      enum glyph_row_area area = it->area;
+      struct glyph *glyph
+       = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+
+      if (it->glyph_row->reversed_p)
+       {
+         struct glyph *g;
+
+         /* Make room for the new glyph.  */
+         for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
+           g[1] = *g;
+         glyph = it->glyph_row->glyphs[it->area];
+       }
+      if (glyph < it->glyph_row->glyphs[area + 1])
+       {
+         glyph->charpos = CHARPOS (it->position);
+         glyph->object = it->object;
+         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->type = XWIDGET_GLYPH;
+         glyph->avoid_cursor_p = it->avoid_cursor_p;
+         glyph->multibyte_p = it->multibyte_p;
+         if (it->glyph_row->reversed_p && area == TEXT_AREA)
+           {
+             /* In R2L rows, the left and the right box edges need to be
+                drawn in reverse direction.  */
+             glyph->right_box_line_p = it->start_of_box_run_p;
+             glyph->left_box_line_p = it->end_of_box_run_p;
+           }
+         else
+           {
+             glyph->left_box_line_p = it->start_of_box_run_p;
+             glyph->right_box_line_p = it->end_of_box_run_p;
+           }
+          glyph->overlaps_vertically_p = 0;
+          glyph->padding_p = 0;
+         glyph->glyph_not_available_p = 0;
+         glyph->face_id = it->face_id;
+          glyph->u.xwidget = it->xwidget;
+         glyph->font_type = FONT_TYPE_UNKNOWN;
+         if (it->bidi_p)
+           {
+             glyph->resolved_level = it->bidi_it.resolved_level;
+             eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
+             glyph->bidi_type = it->bidi_it.type;
+           }
+         ++it->glyph_row->used[area];
+       }
+      else
+       IT_EXPAND_MATRIX_WIDTH (it, area);
+    }
+#endif
+}
 
 /* Append a stretch glyph to IT->glyph_row.  OBJECT is the source
    of the glyph, WIDTH and HEIGHT are the width and height of the
@@ -25836,7 +26309,9 @@ append_stretch_glyph (struct it *it, Lisp_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;
@@ -25947,9 +26422,7 @@ produce_stretch_glyph (struct it *it)
       zero_width_ok_p = true;
       width = (int)tem;
     }
-#ifdef HAVE_WINDOW_SYSTEM
-  else if (FRAME_WINDOW_P (it->f)
-          && (prop = Fplist_get (plist, QCrelative_width), NUMVAL (prop) > 0))
+  else if (prop = Fplist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
     {
       /* Relative width `:relative-width FACTOR' specified and valid.
         Compute the width of the characters having the `glyph'
@@ -25969,10 +26442,9 @@ produce_stretch_glyph (struct it *it)
 
       it2.glyph_row = NULL;
       it2.what = IT_CHARACTER;
-      x_produce_glyphs (&it2);
+      PRODUCE_GLYPHS (&it2);
       width = NUMVAL (prop) * it2.pixel_width;
     }
-#endif /* HAVE_WINDOW_SYSTEM */
   else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
           && calc_pixel_width_or_height (&tem, it, prop, font, true,
                                          &align_to))
@@ -26290,6 +26762,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;
+      eassert (it->pixel_width <= SHRT_MAX);
       glyph->pixel_width = it->pixel_width;
       glyph->ascent = it->ascent;
       glyph->descent = it->descent;
@@ -27201,6 +27674,8 @@ x_produce_glyphs (struct it *it)
     produce_image_glyph (it);
   else if (it->what == IT_STRETCH)
     produce_stretch_glyph (it);
+  else if (it->what == IT_XWIDGET)
+    produce_xwidget_glyph (it);
 
  done:
   /* Accumulate dimensions.  Note: can't assume that it->descent > 0
@@ -27570,6 +28045,8 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
   /* Use normal cursor if not blinked off.  */
   if (!w->cursor_off_p)
     {
+      if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
+        return NO_CURSOR;
       if (glyph != NULL && glyph->type == IMAGE_GLYPH)
        {
          if (cursor_type == FILLED_BOX_CURSOR)
@@ -29063,7 +29540,7 @@ on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
       Lisp_Object lr, lx0, ly0;
       if (CONSP (circ)
          && CONSP (XCAR (circ))
-         && (lr = XCDR (circ), INTEGERP (lr) || FLOATP (lr))
+         && (lr = XCDR (circ), NUMBERP (lr))
          && (lx0 = XCAR (XCAR (circ)), INTEGERP (lx0))
          && (ly0 = XCDR (XCAR (circ)), INTEGERP (ly0)))
        {
@@ -30959,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
-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.
@@ -30999,7 +31479,7 @@ This variable is not guaranteed to be accurate except while processing
 
 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
-which no explicit name has been set \(see `modify-frame-parameters').  */);
+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.
@@ -31025,11 +31505,13 @@ the buffer when it becomes large.  */);
   Vmessage_log_max = make_number (1000);
 
   DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
-    doc: /* Functions called before redisplay, if window sizes have changed.
+    doc: /* Functions called during redisplay, if window sizes have changed.
 The value should be a list of functions that take one argument.
-Just before redisplay, for each frame, if any of its windows have changed
-size since the last redisplay, or have been split or deleted,
-all the functions in the list are called, with the frame as argument.  */);
+During the first part of redisplay, for each frame, if any of its windows
+have changed size since the last redisplay, or have been split or deleted,
+all the functions in the list are called, with the frame as argument.
+If redisplay decides to resize the minibuffer window, it calls these
+functions on behalf of that as well.  */);
   Vwindow_size_change_functions = Qnil;
 
   DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
@@ -31065,9 +31547,9 @@ A positive number means delay autoselection by that many seconds: a
 window is autoselected only after the mouse has remained in that
 window for the duration of the delay.
 A negative number has a similar effect, but causes windows to be
-autoselected only after the mouse has stopped moving.  \(Because of
+autoselected only after the mouse has stopped moving.  (Because of
 the way Emacs compares mouse events, you will occasionally wait twice
-that time before the window gets selected.\)
+that time before the window gets selected.)
 Any other value means to autoselect window instantaneously when the
 mouse pointer enters it.
 
@@ -31166,7 +31648,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.  */);
-  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.
@@ -31365,13 +31852,21 @@ display table takes effect; in this case, Emacs does not consult
 
   DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
               doc: /*  */);
-  Vredisplay__all_windows_cause
-    = Fmake_vector (make_number (100), make_number (0));
+  Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
 
   DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
               doc: /*  */);
-  Vredisplay__mode_lines_cause
-    = Fmake_vector (make_number (100), make_number (0));
+  Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
+
+  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;
 }