Merge from emacs-24; up to 2012-12-06T01:39:03Z!monnier@iro.umontreal.ca
[bpt/emacs.git] / src / xdisp.c
index 36196e8..8b0d8b6 100644 (file)
@@ -1,6 +1,7 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
+Inc.
 
 This file is part of GNU Emacs.
 
@@ -273,9 +274,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <stdio.h>
 #include <limits.h>
-#include <setjmp.h>
 
 #include "lisp.h"
+#include "atimer.h"
 #include "keyboard.h"
 #include "frame.h"
 #include "window.h"
@@ -302,7 +303,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
 #include "w32term.h"
 #endif
 #ifdef HAVE_NS
@@ -333,10 +334,10 @@ static Lisp_Object Qinhibit_eval_during_redisplay;
 static Lisp_Object Qbuffer_position, Qposition, Qobject;
 static Lisp_Object Qright_to_left, Qleft_to_right;
 
-/* Cursor shapes */
+/* Cursor shapes */
 Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
 
-/* Pointer shapes */
+/* Pointer shapes */
 static Lisp_Object Qarrow, Qhand;
 Lisp_Object Qtext;
 
@@ -347,6 +348,7 @@ static Lisp_Object Qfontification_functions;
 
 static Lisp_Object Qwrap_prefix;
 static Lisp_Object Qline_prefix;
+static Lisp_Object Qredisplay_internal;
 
 /* Non-nil means don't actually do any redisplay.  */
 
@@ -365,6 +367,28 @@ Lisp_Object Qcenter;
 static Lisp_Object Qmargin, Qpointer;
 static Lisp_Object Qline_height;
 
+/* These setters are used only in this file, so they can be private.  */
+static void
+wset_base_line_number (struct window *w, Lisp_Object val)
+{
+  w->base_line_number = val;
+}
+static void
+wset_base_line_pos (struct window *w, Lisp_Object val)
+{
+  w->base_line_pos = val;
+}
+static void
+wset_column_number_displayed (struct window *w, Lisp_Object val)
+{
+  w->column_number_displayed = val;
+}
+static void
+wset_region_showing (struct window *w, Lisp_Object val)
+{
+  w->region_showing = val;
+}
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Test if overflow newline into fringe.  Called with iterator IT
@@ -492,12 +516,6 @@ Lisp_Object Qmenu_bar_update_hook;
 
 static int overlay_arrow_seen;
 
-/* Number of windows showing the buffer of the selected window (or
-   another buffer with the same base buffer).  keyboard.c refers to
-   this.  */
-
-int buffer_shared;
-
 /* Vector containing glyphs for an ellipsis `...'.  */
 
 static Lisp_Object default_invis_vector[3];
@@ -746,9 +764,9 @@ static int clear_image_cache_count;
 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 #endif
 
-/* Non-zero while redisplay_internal is in progress.  */
+/* True while redisplay_internal is in progress.  */
 
-int redisplaying_p;
+bool redisplaying_p;
 
 static Lisp_Object Qinhibit_free_realized_faces;
 static Lisp_Object Qmode_line_default_help_echo;
@@ -838,7 +856,6 @@ static int string_char_and_length (const unsigned char *, int *);
 static struct text_pos display_prop_end (struct it *, Lisp_Object,
                                          struct text_pos);
 static int compute_window_start_on_continuation_line (struct window *);
-static Lisp_Object safe_eval_handler (Lisp_Object);
 static void insert_left_trunc_glyphs (struct it *);
 static struct glyph_row *get_overlay_arrow_glyph_row (struct window *,
                                                       Lisp_Object);
@@ -853,7 +870,6 @@ static void push_it (struct it *, struct text_pos *);
 static void iterate_out_of_display_property (struct it *);
 static void pop_it (struct it *);
 static void sync_frame_with_window_matrix_rows (struct window *);
-static void select_frame_for_redisplay (Lisp_Object);
 static void redisplay_internal (void);
 static int echo_area_display (int);
 static void redisplay_windows (Lisp_Object);
@@ -906,6 +922,7 @@ static enum move_it_result
        move_it_in_display_line_to (struct it *, ptrdiff_t, int,
                                   enum move_operation_enum);
 void move_it_vertically_backward (struct it *, int);
+static void get_visually_first_element (struct it *);
 static void init_to_row_start (struct it *, struct window *,
                                struct glyph_row *);
 static int init_to_row_end (struct it *, struct window *,
@@ -1169,7 +1186,7 @@ window_box (struct window *w, int area, int *box_x, int *box_y,
    *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
    box.  */
 
-static inline void
+static void
 window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y,
                   int *bottom_right_x, int *bottom_right_y)
 {
@@ -1256,7 +1273,7 @@ string_from_display_spec (Lisp_Object spec)
 /* Limit insanely large values of W->hscroll on frame F to the largest
    value that will still prevent first_visible_x and last_visible_x of
    'struct it' from overflowing an int.  */
-static inline int
+static int
 window_hscroll_limited (struct window *w, struct frame *f)
 {
   ptrdiff_t window_hscroll = w->hscroll;
@@ -1310,10 +1327,10 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   if (WINDOW_WANTS_HEADER_LINE_P (w))
     current_header_line_height
       = display_mode_line (w, HEADER_LINE_FACE_ID,
-                              BVAR (current_buffer, header_line_format));
+                          BVAR (current_buffer, header_line_format));
 
   start_display (&it, w, top);
-  move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
+  move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
              (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
 
   if (charpos >= 0
@@ -1321,7 +1338,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
           && IT_CHARPOS (it) >= charpos)
          /* When scanning backwards under bidi iteration, move_it_to
             stops at or _before_ CHARPOS, because it stops at or to
-            the _right_ of the character at CHARPOS. */
+            the _right_ of the character at CHARPOS.  */
          || (it.bidi_p && it.bidi_it.scan_dir == -1
              && IT_CHARPOS (it) <= charpos)))
     {
@@ -1603,7 +1620,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
    returns an invalid character.  If we find one, we return a `?', but
    with the length of the invalid character.  */
 
-static inline int
+static int
 string_char_and_length (const unsigned char *str, int *len)
 {
   int c;
@@ -1651,7 +1668,7 @@ string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t ncha
 /* Value is the text position, i.e. character and byte position,
    for character position CHARPOS in STRING.  */
 
-static inline struct text_pos
+static struct text_pos
 string_pos (ptrdiff_t charpos, Lisp_Object string)
 {
   struct text_pos pos;
@@ -2397,9 +2414,10 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
 /* Error handler for safe_eval and safe_call.  */
 
 static Lisp_Object
-safe_eval_handler (Lisp_Object arg)
+safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
 {
-  add_to_log ("Error during redisplay: %S", arg, Qnil);
+  add_to_log ("Error during redisplay: %S signaled %S",
+             Flist (nargs, args), arg);
   return Qnil;
 }
 
@@ -2420,7 +2438,7 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
       ptrdiff_t i;
       ptrdiff_t count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
-      Lisp_Object *args = alloca (nargs * sizeof (Lisp_Object));
+      Lisp_Object *args = alloca (nargs * word_size);
 
       args[0] = func;
       va_start (ap, func);
@@ -2541,8 +2559,24 @@ check_window_end (struct window *w)
 
 #endif /* GLYPH_DEBUG and ENABLE_CHECKING */
 
+/* Return mark position if current buffer has the region of non-zero length,
+   or -1 otherwise.  */
+
+static ptrdiff_t
+markpos_of_region (void)
+{
+  if (!NILP (Vtransient_mark_mode)
+      && !NILP (BVAR (current_buffer, mark_active))
+      && XMARKER (BVAR (current_buffer, mark))->buffer != NULL)
+    {
+      ptrdiff_t markpos = XMARKER (BVAR (current_buffer, mark))->charpos;
+
+      if (markpos != PT)
+       return markpos;
+    }
+  return -1;
+}
 
-\f
 /***********************************************************************
                       Iterator initialization
  ***********************************************************************/
@@ -2571,7 +2605,7 @@ init_iterator (struct it *it, struct window *w,
               ptrdiff_t charpos, ptrdiff_t bytepos,
               struct glyph_row *row, enum face_id base_face_id)
 {
-  int highlight_region_p;
+  ptrdiff_t markpos;
   enum face_id remapped_base_face_id = base_face_id;
 
   /* Some precondition checks.  */
@@ -2591,7 +2625,8 @@ init_iterator (struct it *it, struct window *w,
 
   /* Perhaps remap BASE_FACE_ID to a user-specified alternative.  */
   if (! NILP (Vface_remapping_alist))
-    remapped_base_face_id = lookup_basic_face (XFRAME (w->frame), base_face_id);
+    remapped_base_face_id
+      = lookup_basic_face (XFRAME (w->frame), base_face_id);
 
   /* Use one of the mode line rows of W's desired matrix if
      appropriate.  */
@@ -2659,9 +2694,9 @@ init_iterator (struct it *it, struct window *w,
      is invisible.  >0 means lines indented more than this value are
      invisible.  */
   it->selective = (INTEGERP (BVAR (current_buffer, selective_display))
-                  ? clip_to_bounds (-1, XINT (BVAR (current_buffer,
-                                                    selective_display)),
-                                    PTRDIFF_MAX)
+                  ? (clip_to_bounds
+                     (-1, XINT (BVAR (current_buffer, selective_display)),
+                      PTRDIFF_MAX))
                   : (!NILP (BVAR (current_buffer, selective_display))
                      ? -1 : 0));
   it->selective_display_ellipsis_p
@@ -2673,16 +2708,11 @@ init_iterator (struct it *it, struct window *w,
   /* Are multibyte characters enabled in current_buffer?  */
   it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
 
-  /* Non-zero if we should highlight the region.  */
-  highlight_region_p
-    = (!NILP (Vtransient_mark_mode)
-       && !NILP (BVAR (current_buffer, mark_active))
-       && XMARKER (BVAR (current_buffer, mark))->buffer != 0);
-
-  /* Set IT->region_beg_charpos and IT->region_end_charpos to the
-     start and end of a visible region in window IT->w.  Set both to
-     -1 to indicate no region.  */
-  if (highlight_region_p
+  /* If visible region is of non-zero length, set IT->region_beg_charpos
+     and IT->region_end_charpos to the start and end of a visible region
+     in window IT->w.  Set both to -1 to indicate no region.  */
+  markpos = markpos_of_region ();
+  if (0 <= markpos
       /* Maybe highlight only in selected window.  */
       && (/* Either show region everywhere.  */
          highlight_nonselected_windows
@@ -2694,7 +2724,6 @@ init_iterator (struct it *it, struct window *w,
              && WINDOWP (minibuf_selected_window)
              && w == XWINDOW (minibuf_selected_window))))
     {
-      ptrdiff_t markpos = marker_position (BVAR (current_buffer, mark));
       it->region_beg_charpos = min (PT, markpos);
       it->region_end_charpos = max (PT, markpos);
     }
@@ -3089,6 +3118,40 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
       eassert (STRINGP (it->string));
       it->current.string_pos = pos->string_pos;
       it->method = GET_FROM_STRING;
+      it->end_charpos = SCHARS (it->string);
+      /* Set up the bidi iterator for this overlay string.  */
+      if (it->bidi_p)
+       {
+         it->bidi_it.string.lstring = it->string;
+         it->bidi_it.string.s = NULL;
+         it->bidi_it.string.schars = SCHARS (it->string);
+         it->bidi_it.string.bufpos = it->overlay_strings_charpos;
+         it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
+         it->bidi_it.string.unibyte = !it->multibyte_p;
+         bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
+                       FRAME_WINDOW_P (it->f), &it->bidi_it);
+
+         /* Synchronize the state of the bidi iterator with
+            pos->string_pos.  For any string position other than
+            zero, this will be done automagically when we resume
+            iteration over the string and get_visually_first_element
+            is called.  But if string_pos is zero, and the string is
+            to be reordered for display, we need to resync manually,
+            since it could be that the iteration state recorded in
+            pos ended at string_pos of 0 moving backwards in string.  */
+         if (CHARPOS (pos->string_pos) == 0)
+           {
+             get_visually_first_element (it);
+             if (IT_STRING_CHARPOS (*it) != 0)
+               do {
+                 /* Paranoia.  */
+                 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
+                 bidi_move_to_visually_next (&it->bidi_it);
+               } while (it->bidi_it.charpos != 0);
+           }
+         eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
+                  && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
+       }
     }
 
   if (CHARPOS (pos->string_pos) >= 0)
@@ -3098,6 +3161,9 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
         IT should already be filled with that string.  */
       it->current.string_pos = pos->string_pos;
       eassert (STRINGP (it->string));
+      if (it->bidi_p)
+       bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
+                     FRAME_WINDOW_P (it->f), &it->bidi_it);
     }
 
   /* Restore position in display vector translations, control
@@ -3320,7 +3386,7 @@ compute_stop_pos (struct it *it)
      interval if there isn't such an interval.  */
   position = make_number (charpos);
   iv = validate_interval_range (object, &position, &position, 0);
-  if (!NULL_INTERVAL_P (iv))
+  if (iv)
     {
       Lisp_Object values_here[LAST_PROP_IDX];
       struct props *p;
@@ -3332,7 +3398,7 @@ compute_stop_pos (struct it *it)
       /* Look for an interval following iv that has different
         properties.  */
       for (next_iv = next_interval (iv);
-          (!NULL_INTERVAL_P (next_iv)
+          (next_iv
            && (NILP (limit)
                || XFASTINT (limit) > next_iv->position));
           next_iv = next_interval (next_iv))
@@ -3350,7 +3416,7 @@ compute_stop_pos (struct it *it)
            break;
        }
 
-      if (!NULL_INTERVAL_P (next_iv))
+      if (next_iv)
        {
          if (INTEGERP (limit)
              && next_iv->position >= XFASTINT (limit))
@@ -3643,7 +3709,7 @@ handle_fontified_prop (struct it *it)
        }
       /* There isn't much we can reasonably do to protect against
         misbehaving fontification, but here's a fig leaf.  */
-      else if (!NILP (BVAR (obuf, name)))
+      else if (BUFFER_LIVE_P (obuf))
        set_buffer_internal_1 (obuf);
 
       /* The fontification code may have added/removed text.
@@ -3699,18 +3765,26 @@ handle_face_prop (struct it *it)
       if (new_face_id != it->face_id)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
+         /* If it->face_id is -1, old_face below will be NULL, see
+            the definition of FACE_FROM_ID.  This will happen if this
+            is the initial call that gets the face.  */
+         struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
 
-         /* If new face has a box but old face has not, this is
-            the start of a run of characters with box, i.e. it has
-            a shadow on the left side.  The value of face_id of the
-            iterator will be -1 if this is the initial call that gets
-            the face.  In this case, we have to look in front of IT's
-            position and see whether there is a face != new_face_id.  */
-         it->start_of_box_run_p
-           = (new_face->box != FACE_NO_BOX
-              && (it->face_id >= 0
-                  || IT_CHARPOS (*it) == BEG
-                  || new_face_id != face_before_it_pos (it)));
+         /* If the value of face_id of the iterator is -1, we have to
+            look in front of IT's position and see whether there is a
+            face there that's different from new_face_id.  */
+         if (!old_face && IT_CHARPOS (*it) > BEG)
+           {
+             int prev_face_id = face_before_it_pos (it);
+
+             old_face = FACE_FROM_ID (it->f, prev_face_id);
+           }
+
+         /* If the new face has a box, but the old face does not,
+            this is the start of a run of characters with box face,
+            i.e. this character has a shadow on the left side.  */
+         it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
+                                   && (old_face == NULL || !old_face->box));
          it->face_box_p = new_face->box != FACE_NO_BOX;
        }
     }
@@ -4046,38 +4120,54 @@ static enum prop_handled
 handle_invisible_prop (struct it *it)
 {
   enum prop_handled handled = HANDLED_NORMALLY;
+  int invis_p;
+  Lisp_Object prop;
 
   if (STRINGP (it->string))
     {
-      Lisp_Object prop, end_charpos, limit, charpos;
+      Lisp_Object end_charpos, limit, charpos;
 
       /* Get the value of the invisible text property at the
         current position.  Value will be nil if there is no such
         property.  */
       charpos = make_number (IT_STRING_CHARPOS (*it));
       prop = Fget_text_property (charpos, Qinvisible, it->string);
+      invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
 
-      if (!NILP (prop)
-         && IT_STRING_CHARPOS (*it) < it->end_charpos)
+      if (invis_p && IT_STRING_CHARPOS (*it) < it->end_charpos)
        {
-         ptrdiff_t endpos;
+         /* Record whether we have to display an ellipsis for the
+            invisible text.  */
+         int display_ellipsis_p = (invis_p == 2);
+         ptrdiff_t len, endpos;
 
          handled = HANDLED_RECOMPUTE_PROPS;
 
-         /* Get the position at which the next change of the
-            invisible text property can be found in IT->string.
-            Value will be nil if the property value is the same for
-            all the rest of IT->string.  */
-         XSETINT (limit, SCHARS (it->string));
-         end_charpos = Fnext_single_property_change (charpos, Qinvisible,
-                                                     it->string, limit);
-
-         /* Text at current position is invisible.  The next
-            change in the property is at position end_charpos.
-            Move IT's current position to that position.  */
-         if (INTEGERP (end_charpos)
-             && (endpos = XFASTINT (end_charpos)) < XFASTINT (limit))
+         /* Get the position at which the next visible text can be
+            found in IT->string, if any.  */
+         endpos = len = SCHARS (it->string);
+         XSETINT (limit, len);
+         do
            {
+             end_charpos = Fnext_single_property_change (charpos, Qinvisible,
+                                                         it->string, limit);
+             if (INTEGERP (end_charpos))
+               {
+                 endpos = XFASTINT (end_charpos);
+                 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
+                 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
+                 if (invis_p == 2)
+                   display_ellipsis_p = 1;
+               }
+           }
+         while (invis_p && endpos < len);
+
+         if (display_ellipsis_p)
+           it->ellipsis_p = 1;
+
+         if (endpos < len)
+           {
+             /* Text at END_CHARPOS is visible.  Move IT there.  */
              struct text_pos old;
              ptrdiff_t oldpos;
 
@@ -4113,7 +4203,8 @@ handle_invisible_prop (struct it *it)
              /* The rest of the string is invisible.  If this is an
                 overlay string, proceed with the next overlay string
                 or whatever comes and return a character from there.  */
-             if (it->current.overlay_string_index >= 0)
+             if (it->current.overlay_string_index >= 0
+                 && !display_ellipsis_p)
                {
                  next_overlay_string (it);
                  /* Don't check for overlay strings when we just
@@ -4130,9 +4221,8 @@ handle_invisible_prop (struct it *it)
     }
   else
     {
-      int invis_p;
       ptrdiff_t newpos, next_stop, start_charpos, tem;
-      Lisp_Object pos, prop, overlay;
+      Lisp_Object pos, overlay;
 
       /* First of all, is there invisible text at this position?  */
       tem = start_charpos = IT_CHARPOS (*it);
@@ -5308,6 +5398,7 @@ next_overlay_string (struct it *it)
       SET_TEXT_POS (it->current.string_pos, 0, 0);
       it->method = GET_FROM_STRING;
       it->stop_charpos = 0;
+      it->end_charpos = SCHARS (it->string);
       if (it->cmp_it.stop_pos >= 0)
        it->cmp_it.stop_pos = 0;
       it->prev_stop = 0;
@@ -6009,7 +6100,7 @@ back_to_previous_visible_line_start (struct it *it)
       {
        Lisp_Object prop;
        prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
-                                    Qinvisible, it->window);
+                                  Qinvisible, it->window);
        if (TEXT_PROP_MEANS_INVISIBLE (prop))
          continue;
       }
@@ -6261,6 +6352,8 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
       it->stop_charpos = CHARPOS (pos);
       it->base_level_stop = CHARPOS (pos);
     }
+  /* This make the information stored in it->cmp_it invalidate.  */
+  it->cmp_it.id = -1;
 }
 
 
@@ -7267,7 +7360,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
 
     default:
       /* There are no other methods defined, so this should be a bug.  */
-      abort ();
+      emacs_abort ();
     }
 
   eassert (it->method != GET_FROM_STRING
@@ -7717,12 +7810,12 @@ compute_stop_pos_backwards (struct it *it)
     {
       it->end_charpos = min (charpos + 1, ZV);
       charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
-      SET_TEXT_POS (pos, charpos, BYTE_TO_CHAR (charpos));
+      SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
       reseat_1 (it, pos, 0);
       compute_stop_pos (it);
       /* We must advance forward, right?  */
       if (it->stop_charpos <= charpos)
-       abort ();
+       emacs_abort ();
     }
   while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
 
@@ -7771,7 +7864,7 @@ handle_stop_backwards (struct it *it, ptrdiff_t charpos)
       compute_stop_pos (it);
       /* We must advance forward, right?  */
       if (it->stop_charpos <= it->prev_stop)
-       abort ();
+       emacs_abort ();
       charpos = it->stop_charpos;
     }
   while (charpos <= where_we_are);
@@ -7980,7 +8073,7 @@ run_redisplay_end_trigger_hook (struct it *it)
 
   /* Since we are *trying* to run these functions, don't try to run
      them again, even if they get an error.  */
-  it->w->redisplay_end_trigger = Qnil;
+  wset_redisplay_end_trigger (it->w, Qnil);
   Frun_hook_with_args (3, args);
 
   /* Notice if it changed the face of the character we are on.  */
@@ -8859,7 +8952,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
          break;
 
        default:
-         abort ();
+         emacs_abort ();
        }
 
       /* Reset/increment for the next run.  */
@@ -9252,12 +9345,6 @@ add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   USE_SAFE_ALLOCA;
 
-  /* Do nothing if called asynchronously.  Inserting text into
-     a buffer may call after-change-functions and alike and
-     that would means running Lisp asynchronously.  */
-  if (handling_signal)
-    return;
-
   fmt = msg = Qnil;
   GCPRO4 (fmt, msg, arg1, arg2);
 
@@ -9267,7 +9354,7 @@ add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
   msg = Fformat (3, args);
 
   len = SBYTES (msg) + 1;
-  SAFE_ALLOCA (buffer, char *, len);
+  buffer = SAFE_ALLOCA (len);
   memcpy (buffer, SDATA (msg), len);
 
   message_dolog (buffer, len - 1, 1, 0);
@@ -9311,13 +9398,14 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
       int old_windows_or_buffers_changed = windows_or_buffers_changed;
       ptrdiff_t point_at_end = 0;
       ptrdiff_t zv_at_end = 0;
-      Lisp_Object old_deactivate_mark, tem;
+      Lisp_Object old_deactivate_mark;
+      bool shown;
       struct gcpro gcpro1;
 
       old_deactivate_mark = Vdeactivate_mark;
       oldbuf = current_buffer;
       Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
-      BVAR (current_buffer, undo_list) = Qt;
+      bset_undo_list (current_buffer, Qt);
 
       oldpoint = message_dolog_marker1;
       set_marker_restricted (oldpoint, make_number (PT), Qnil);
@@ -9426,7 +9514,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
              del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
            }
        }
-      BEGV = XMARKER (oldbegv)->charpos;
+      BEGV = marker_position (oldbegv);
       BEGV_BYTE = marker_byte_position (oldbegv);
 
       if (zv_at_end)
@@ -9436,7 +9524,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
        }
       else
        {
-         ZV = XMARKER (oldzv)->charpos;
+         ZV = marker_position (oldzv);
          ZV_BYTE = marker_byte_position (oldzv);
        }
 
@@ -9445,17 +9533,17 @@ message_dolog (const char *m, ptrdiff_t nbytes, int nlflag, int multibyte)
       else
        /* We can't do Fgoto_char (oldpoint) because it will run some
            Lisp code.  */
-       TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
-                         XMARKER (oldpoint)->bytepos);
+       TEMP_SET_PT_BOTH (marker_position (oldpoint),
+                         marker_byte_position (oldpoint));
 
       UNGCPRO;
       unchain_marker (XMARKER (oldpoint));
       unchain_marker (XMARKER (oldbegv));
       unchain_marker (XMARKER (oldzv));
 
-      tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
+      shown = buffer_window_count (current_buffer) > 0;
       set_buffer_internal (oldbuf);
-      if (NILP (tem))
+      if (!shown)
        windows_or_buffers_changed = old_windows_or_buffers_changed;
       message_log_need_newline = !nlflag;
       Vdeactivate_mark = old_deactivate_mark;
@@ -9568,7 +9656,7 @@ message2_nolog (const char *m, ptrdiff_t nbytes, int multibyte)
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+      if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
        (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
 }
@@ -9594,10 +9682,8 @@ message3 (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
   message_log_maybe_newline ();
   if (STRINGP (m))
     {
-      char *buffer;
       USE_SAFE_ALLOCA;
-
-      SAFE_ALLOCA (buffer, char *, nbytes);
+      char *buffer = SAFE_ALLOCA (nbytes);
       memcpy (buffer, SDATA (m), nbytes);
       message_dolog (buffer, nbytes, 1, multibyte);
       SAFE_FREE ();
@@ -9667,7 +9753,7 @@ message3_nolog (Lisp_Object m, ptrdiff_t nbytes, int multibyte)
       do_pending_window_change (0);
       echo_area_display (1);
       do_pending_window_change (0);
-      if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+      if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
        (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
 }
@@ -9872,7 +9958,7 @@ ensure_echo_area_buffers (void)
 
   for (i = 0; i < 2; ++i)
     if (!BUFFERP (echo_buffer[i])
-       || NILP (BVAR (XBUFFER (echo_buffer[i]), name)))
+       || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
       {
        char name[30];
        Lisp_Object old_buffer;
@@ -9881,7 +9967,7 @@ ensure_echo_area_buffers (void)
        old_buffer = echo_buffer[i];
        echo_buffer[i] = Fget_buffer_create
          (make_formatted_string (name, " *Echo Area %d*", i));
-       BVAR (XBUFFER (echo_buffer[i]), truncate_lines) = Qnil;
+       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; */
@@ -9970,12 +10056,12 @@ with_echo_area_buffer (struct window *w, int which,
   set_buffer_internal_1 (XBUFFER (buffer));
   if (w)
     {
-      w->buffer = buffer;
+      wset_buffer (w, buffer);
       set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
     }
 
-  BVAR (current_buffer, undo_list) = Qt;
-  BVAR (current_buffer, read_only) = Qnil;
+  bset_undo_list (current_buffer, Qt);
+  bset_read_only (current_buffer, Qnil);
   specbind (Qinhibit_read_only, Qt);
   specbind (Qinhibit_modification_hooks, Qt);
 
@@ -10020,8 +10106,8 @@ with_echo_area_buffer_unwind_data (struct window *w)
     {
       XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
       ASET (vector, i, w->buffer); ++i;
-      ASET (vector, i, make_number (XMARKER (w->pointm)->charpos)); ++i;
-      ASET (vector, i, make_number (XMARKER (w->pointm)->bytepos)); ++i;
+      ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
+      ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
     }
   else
     {
@@ -10055,7 +10141,7 @@ unwind_with_echo_area_buffer (Lisp_Object vector)
       charpos = AREF (vector, 5);
       bytepos = AREF (vector, 6);
 
-      w->buffer = buffer;
+      wset_buffer (w, buffer);
       set_marker_both (w->pointm, buffer,
                       XFASTINT (charpos), XFASTINT (bytepos));
     }
@@ -10088,7 +10174,7 @@ setup_echo_area_for_printing (int multibyte_p)
 
       /* Switch to that buffer and clear it.  */
       set_buffer_internal (XBUFFER (echo_area_buffer[0]));
-      BVAR (current_buffer, truncate_lines) = Qnil;
+      bset_truncate_lines (current_buffer, Qnil);
 
       if (Z > BEG)
        {
@@ -10131,7 +10217,7 @@ setup_echo_area_for_printing (int multibyte_p)
        {
          /* Someone switched buffers between print requests.  */
          set_buffer_internal (XBUFFER (echo_area_buffer[0]));
-         BVAR (current_buffer, truncate_lines) = Qnil;
+         bset_truncate_lines (current_buffer, Qnil);
        }
     }
 }
@@ -10318,8 +10404,7 @@ resize_mini_window (struct window *w, int exact_p)
        max_height = total_height / 4;
 
       /* Correct that max. height if it's bogus.  */
-      max_height = max (1, max_height);
-      max_height = min (total_height, max_height);
+      max_height = clip_to_bounds (1, max_height, total_height);
 
       /* Find out the height of the text in the window.  */
       if (it.line_wrap == TRUNCATE)
@@ -10443,11 +10528,10 @@ current_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4)
    empty.  This is a relatively infrequent operation, so it's not
    worth optimizing.  */
 
-int
+bool
 push_message (void)
 {
-  Lisp_Object msg;
-  msg = current_message ();
+  Lisp_Object msg = current_message ();
   Vmessage_stack = Fcons (msg, Vmessage_stack);
   return STRINGP (msg);
 }
@@ -10496,7 +10580,7 @@ void
 check_message_stack (void)
 {
   if (!NILP (Vmessage_stack))
-    abort ();
+    emacs_abort ();
 }
 
 
@@ -10535,7 +10619,6 @@ truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2, ptrdiff_t a3, ptrdiff_t a4
   return 0;
 }
 
-
 /* Set the current message to a substring of S or STRING.
 
    If STRING is a Lisp string, set the message to the first NBYTES
@@ -10562,6 +10645,10 @@ set_message (const char *s, Lisp_Object string,
                         (intptr_t) s, string, nbytes, multibyte_p);
   message_buf_print = 0;
   help_echo_showing_p = 0;
+
+  if (STRINGP (Vdebug_on_message)
+      && fast_string_match (Vdebug_on_message, string) >= 0)
+    call_debugger (list2 (Qerror, string));
 }
 
 
@@ -10583,9 +10670,9 @@ set_message_1 (ptrdiff_t a1, Lisp_Object a2, ptrdiff_t nbytes, ptrdiff_t multiby
       != !NILP (BVAR (current_buffer, enable_multibyte_characters)))
     Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
 
-  BVAR (current_buffer, truncate_lines) = message_truncate_lines ? Qt : Qnil;
+  bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
   if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
-    BVAR (current_buffer, bidi_paragraph_direction) = Qleft_to_right;
+    bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
 
   /* Insert new message at BEG.  */
   TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
@@ -10694,7 +10781,7 @@ clear_garbaged_frames (void)
            {
              if (f->resized_p)
                {
-                 Fredraw_frame (frame);
+                 redraw_frame (f);
                  f->force_flush_display_p = 1;
                }
              clear_current_matrices (f);
@@ -10741,8 +10828,7 @@ echo_area_display (int update_frame_p)
 #endif /* HAVE_WINDOW_SYSTEM */
 
   /* Redraw garbaged frames.  */
-  if (frame_garbaged)
-    clear_garbaged_frames ();
+  clear_garbaged_frames ();
 
   if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
     {
@@ -10815,8 +10901,52 @@ echo_area_display (int update_frame_p)
   return window_height_changed_p;
 }
 
+/* Nonzero if the current window's buffer is shown in more than one
+   window and was modified since last redisplay.  */
+
+static int
+buffer_shared_and_changed (void)
+{
+  return (buffer_window_count (current_buffer) > 1
+         && UNCHANGED_MODIFIED < MODIFF);
+}
+
+/* Nonzero if W doesn't reflect the actual state of current buffer due
+   to its text or overlays change.  FIXME: this may be called when
+   XBUFFER (w->buffer) != current_buffer, which looks suspicious.  */
+
+static int
+window_outdated (struct window *w)
+{
+  return (w->last_modified < MODIFF
+         || w->last_overlay_modified < OVERLAY_MODIFF);
+}
+
+/* Nonzero if W's buffer was changed but not saved or Transient Mark mode
+   is enabled and mark of W's buffer was changed since last W's update.  */
+
+static int
+window_buffer_changed (struct window *w)
+{
+  struct buffer *b = XBUFFER (w->buffer);
+
+  eassert (BUFFER_LIVE_P (b));
+
+  return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star)
+         || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active)))
+             != !NILP (w->region_showing)));
+}
+
+/* Nonzero if W has %c in its mode line and mode line should be updated.  */
+
+static int
+mode_line_update_needed (struct window *w)
+{
+  return (!NILP (w->column_number_displayed)
+         && !(PT == w->last_point && !window_outdated (w))
+         && (XFASTINT (w->column_number_displayed) != current_column ()));
+}
 
-\f
 /***********************************************************************
                     Mode Lines and Frame Titles
  ***********************************************************************/
@@ -10892,7 +11022,7 @@ format_mode_line_unwind_data (struct frame *target_frame,
       /* Similarly to `with-selected-window', if the operation selects
         a window on another frame, we must restore that frame's
         selected window, and (for a tty) the top-frame.  */
-      ASET (vector, 8, FVAR (target_frame, selected_window));
+      ASET (vector, 8, target_frame->selected_window);
       if (FRAME_TERMCAP_P (target_frame))
        ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
     }
@@ -11021,17 +11151,15 @@ x_consider_frame_title (Lisp_Object frame)
       || f->explicit_name)
     {
       /* Do we have more than one visible frame on this X display?  */
-      Lisp_Object tail;
-      Lisp_Object fmt;
+      Lisp_Object tail, other_frame, fmt;
       ptrdiff_t title_start;
       char *title;
       ptrdiff_t len;
       struct it it;
       ptrdiff_t count = SPECPDL_INDEX ();
 
-      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+      FOR_EACH_FRAME (tail, other_frame)
        {
-         Lisp_Object other_frame = XCAR (tail);
          struct frame *tf = XFRAME (other_frame);
 
          if (tf != f
@@ -11052,13 +11180,14 @@ x_consider_frame_title (Lisp_Object frame)
                             format_mode_line_unwind_data
                               (f, current_buffer, selected_window, 0));
 
-      Fselect_window (FVAR (f, selected_window), Qt);
-      set_buffer_internal_1 (XBUFFER (XWINDOW (FVAR (f, selected_window))->buffer));
+      Fselect_window (f->selected_window, Qt);
+      set_buffer_internal_1
+       (XBUFFER (XWINDOW (f->selected_window)->buffer));
       fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
 
       mode_line_target = MODE_LINE_TITLE;
       title_start = MODE_LINE_NOPROP_LEN (0);
-      init_iterator (&it, XWINDOW (FVAR (f, selected_window)), -1, -1,
+      init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
                     NULL, DEFAULT_FACE_ID);
       display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
       len = MODE_LINE_NOPROP_LEN (title_start);
@@ -11070,9 +11199,9 @@ x_consider_frame_title (Lisp_Object frame)
         already wasted too much time by walking through the list with
         display_mode_element, then we might need to optimize at a
         higher level than this.)  */
-      if (! STRINGP (FVAR (f, name))
-         || SBYTES (FVAR (f, name)) != len
-         || memcmp (title, SDATA (FVAR (f, name)), len) != 0)
+      if (! STRINGP (f->name)
+         || SBYTES (f->name) != len
+         || memcmp (title, SDATA (f->name), len) != 0)
        x_implicitly_set_name (f, make_string (title, len), Qnil);
     }
 }
@@ -11123,7 +11252,7 @@ prepare_menu_bars (void)
   /* Update the menu bar item lists, if appropriate.  This has to be
      done before any actual redisplay or generation of display lines.  */
   all_windows = (update_mode_lines
-                || buffer_shared > 1
+                || buffer_shared_and_changed ()
                 || windows_or_buffers_changed);
   if (all_windows)
     {
@@ -11171,8 +11300,8 @@ prepare_menu_bars (void)
 #ifdef HAVE_NS
           if (windows_or_buffers_changed
              && FRAME_NS_P (f))
-            ns_set_doc_edited (f, Fbuffer_modified_p
-                              (XWINDOW (FVAR (f, selected_window))->buffer));
+            ns_set_doc_edited
+             (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->buffer));
 #endif
          UNGCPRO;
        }
@@ -11237,12 +11366,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
          /* This used to test w->update_mode_line, but we believe
             there is no need to recompute the menu in that case.  */
          || update_mode_lines
-         || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
-              < BUF_MODIFF (XBUFFER (w->buffer)))
-             != w->last_had_star)
-         || ((!NILP (Vtransient_mark_mode)
-              && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
-             != !NILP (w->region_showing)))
+         || window_buffer_changed (w))
        {
          struct buffer *prev = current_buffer;
          ptrdiff_t count = SPECPDL_INDEX ();
@@ -11274,7 +11398,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
            }
 
          XSETFRAME (Vmenu_updating_frame, f);
-         FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+         fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
 
          /* Redisplay the menu bar in case we changed it.  */
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
@@ -11368,11 +11492,11 @@ x_cursor_to (int vpos, int hpos, int y, int x)
      This will also set the cursor position of W.  */
   if (updated_window == NULL)
     {
-      BLOCK_INPUT;
+      block_input ();
       display_and_set_cursor (w, 1, hpos, vpos, x, y);
       if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
        FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ());
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -11394,11 +11518,18 @@ FRAME_PTR last_mouse_frame;
 
 int last_tool_bar_item;
 
-
+/* Select `frame' temporarily without running all the code in
+   do_switch_frame.
+   FIXME: Maybe do_switch_frame should be trimmed down similarly
+   when `norecord' is set.  */
 static Lisp_Object
-update_tool_bar_unwind (Lisp_Object frame)
+fast_set_selected_frame (Lisp_Object frame)
 {
-  selected_frame = frame;
+  if (!EQ (selected_frame, frame))
+    {
+      selected_frame = frame;
+      selected_window = XFRAME (frame)->selected_window;
+    }
   return Qnil;
 }
 
@@ -11413,8 +11544,8 @@ update_tool_bar (struct frame *f, int save_match_data)
 #if defined (USE_GTK) || defined (HAVE_NS)
   int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
-  int do_update = WINDOWP (FVAR (f, tool_bar_window))
-    && WINDOW_TOTAL_LINES (XWINDOW (FVAR (f, tool_bar_window))) > 0;
+  int do_update = WINDOWP (f->tool_bar_window)
+    && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
 #endif
 
   if (do_update)
@@ -11435,12 +11566,7 @@ update_tool_bar (struct frame *f, int save_match_data)
       if (windows_or_buffers_changed
          || w->update_mode_line
          || update_mode_lines
-         || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
-              < BUF_MODIFF (XBUFFER (w->buffer)))
-             != w->last_had_star)
-         || ((!NILP (Vtransient_mark_mode)
-              && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
-             != !NILP (w->region_showing)))
+         || window_buffer_changed (w))
        {
          struct buffer *prev = current_buffer;
          ptrdiff_t count = SPECPDL_INDEX ();
@@ -11470,26 +11596,31 @@ update_tool_bar (struct frame *f, int save_match_data)
             before calling tool_bar_items, because the calculation of
             the tool-bar keymap uses the selected frame (see
             `tool-bar-make-keymap' in tool-bar.el).  */
-         record_unwind_protect (update_tool_bar_unwind, selected_frame);
+         eassert (EQ (selected_window,
+                      /* Since we only explicitly preserve selected_frame,
+                         check that selected_window would be redundant.  */
+                      XFRAME (selected_frame)->selected_window));
+         record_unwind_protect (fast_set_selected_frame, selected_frame);
          XSETFRAME (frame, f);
-         selected_frame = frame;
+         fast_set_selected_frame (frame);
 
          /* Build desired tool-bar items from keymaps.  */
-          new_tool_bar = tool_bar_items 
-           (Fcopy_sequence (FVAR (f, tool_bar_items)), &new_n_tool_bar);
+          new_tool_bar
+           = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
+                             &new_n_tool_bar);
 
          /* Redisplay the tool-bar if we changed it.  */
          if (new_n_tool_bar != f->n_tool_bar_items
-             || NILP (Fequal (new_tool_bar, FVAR (f, tool_bar_items))))
+             || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
             {
               /* Redisplay that happens asynchronously due to an expose event
                  may access f->tool_bar_items.  Make sure we update both
                  variables within BLOCK_INPUT so no such event interrupts.  */
-              BLOCK_INPUT;
-              FVAR (f, tool_bar_items) = new_tool_bar;
+              block_input ();
+              fset_tool_bar_items (f, new_tool_bar);
               f->n_tool_bar_items = new_n_tool_bar;
               w->update_mode_line = 1;
-              UNBLOCK_INPUT;
+              unblock_input ();
             }
 
          UNGCPRO;
@@ -11519,22 +11650,22 @@ build_desired_tool_bar_string (struct frame *f)
      Otherwise, make a new string.  */
 
   /* The size of the string we might be able to reuse.  */
-  size = (STRINGP (FVAR (f, desired_tool_bar_string))
-         ? SCHARS (FVAR (f, desired_tool_bar_string))
+  size = (STRINGP (f->desired_tool_bar_string)
+         ? SCHARS (f->desired_tool_bar_string)
          : 0);
 
   /* We need one space in the string for each image.  */
   size_needed = f->n_tool_bar_items;
 
   /* Reuse f->desired_tool_bar_string, if possible.  */
-  if (size < size_needed || NILP (FVAR (f, desired_tool_bar_string)))
-    FVAR (f, desired_tool_bar_string)
-      = Fmake_string (make_number (size_needed), make_number (' '));
+  if (size < size_needed || NILP (f->desired_tool_bar_string))
+    fset_desired_tool_bar_string
+      (f, Fmake_string (make_number (size_needed), make_number (' ')));
   else
     {
       props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
       Fremove_text_properties (make_number (0), make_number (size),
-                              props, FVAR (f, desired_tool_bar_string));
+                              props, f->desired_tool_bar_string);
     }
 
   /* Put a `display' property on the string for the images to display,
@@ -11543,7 +11674,7 @@ build_desired_tool_bar_string (struct frame *f)
   for (i = 0; i < f->n_tool_bar_items; ++i)
     {
 #define PROP(IDX) \
-  AREF (FVAR (f, tool_bar_items), i * TOOL_BAR_ITEM_NSLOTS + (IDX))
+  AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
 
       int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
       int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
@@ -11652,11 +11783,11 @@ build_desired_tool_bar_string (struct frame *f)
          string.  The string can be longer than needed when we reuse a
          previous string.  */
       if (i + 1 == f->n_tool_bar_items)
-       end = SCHARS (FVAR (f, desired_tool_bar_string));
+       end = SCHARS (f->desired_tool_bar_string);
       else
        end = i + 1;
       Fadd_text_properties (make_number (i), make_number (end),
-                           props, FVAR (f, desired_tool_bar_string));
+                           props, f->desired_tool_bar_string);
 #undef PROP
     }
 
@@ -11806,7 +11937,7 @@ display_tool_bar_line (struct it *it, int height)
 static int
 tool_bar_lines_needed (struct frame *f, int *n_rows)
 {
-  struct window *w = XWINDOW (FVAR (f, tool_bar_window));
+  struct window *w = XWINDOW (f->tool_bar_window);
   struct it it;
   /* tool_bar_lines_needed is called from redisplay_tool_bar after building
      the desired matrix, so use (unused) mode-line row as temporary row to
@@ -11818,7 +11949,7 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
   init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
   it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
-  reseat_to_string (&it, NULL, FVAR (f, desired_tool_bar_string), 0, 0, 0, -1);
+  reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
   it.paragraph_embedding = L2R;
 
   while (!ITERATOR_AT_END_P (&it))
@@ -11839,21 +11970,16 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
 
 DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
        0, 1, 0,
-       doc: /* Return the number of lines occupied by the tool bar of FRAME.  */)
+       doc: /* Return the number of lines occupied by the tool bar of FRAME.
+If FRAME is nil or omitted, use the selected frame.  */)
   (Lisp_Object frame)
 {
-  struct frame *f;
+  struct frame *f = decode_any_frame (frame);
   struct window *w;
   int nlines = 0;
 
-  if (NILP (frame))
-    frame = selected_frame;
-  else
-    CHECK_FRAME (frame);
-  f = XFRAME (frame);
-
-  if (WINDOWP (FVAR (f, tool_bar_window))
-      && (w = XWINDOW (FVAR (f, tool_bar_window)),
+  if (WINDOWP (f->tool_bar_window)
+      && (w = XWINDOW (f->tool_bar_window),
          WINDOW_TOTAL_LINES (w) > 0))
     {
       update_tool_bar (f, 1);
@@ -11888,8 +12014,8 @@ redisplay_tool_bar (struct frame *f)
      do anything.  This means you must start with tool-bar-lines
      non-zero to get the auto-sizing effect.  Or in other words, you
      can turn off tool-bars by specifying tool-bar-lines zero.  */
-  if (!WINDOWP (FVAR (f, tool_bar_window))
-      || (w = XWINDOW (FVAR (f, tool_bar_window)),
+  if (!WINDOWP (f->tool_bar_window)
+      || (w = XWINDOW (f->tool_bar_window),
           WINDOW_TOTAL_LINES (w) == 0))
     return 0;
 
@@ -11901,7 +12027,7 @@ redisplay_tool_bar (struct frame *f)
 
   /* Build a string that represents the contents of the tool-bar.  */
   build_desired_tool_bar_string (f);
-  reseat_to_string (&it, NULL, FVAR (f, desired_tool_bar_string), 0, 0, 0, -1);
+  reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
   /* FIXME: This should be controlled by a user option.  But it
      doesn't make sense to have an R2L tool bar if the menu bar cannot
      be drawn also R2L, and making the menu bar R2L is tricky due
@@ -12058,14 +12184,14 @@ tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
   /* This function can be called asynchronously, which means we must
      exclude any possibility that Fget_text_property signals an
      error.  */
-  charpos = min (SCHARS (FVAR (f, current_tool_bar_string)), glyph->charpos);
+  charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
   charpos = max (0, charpos);
 
   /* Get the text property `menu-item' at pos. The value of that
      property is the start index of this item's properties in
      F->tool_bar_items.  */
   prop = Fget_text_property (make_number (charpos),
-                            Qmenu_item, FVAR (f, current_tool_bar_string));
+                            Qmenu_item, f->current_tool_bar_string);
   if (INTEGERP (prop))
     {
       *prop_idx = XINT (prop);
@@ -12093,7 +12219,7 @@ get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
                   int *hpos, int *vpos, int *prop_idx)
 {
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
-  struct window *w = XWINDOW (FVAR (f, tool_bar_window));
+  struct window *w = XWINDOW (f->tool_bar_window);
   int area;
 
   /* Find the glyph under X/Y.  */
@@ -12107,7 +12233,7 @@ get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
     return -1;
 
   /* Is mouse on the highlighted item?  */
-  if (EQ (FVAR (f, tool_bar_window), hlinfo->mouse_face_window)
+  if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
       && *vpos >= hlinfo->mouse_face_beg_row
       && *vpos <= hlinfo->mouse_face_end_row
       && (*vpos > hlinfo->mouse_face_beg_row
@@ -12132,7 +12258,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
                       int modifiers)
 {
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
-  struct window *w = XWINDOW (FVAR (f, tool_bar_window));
+  struct window *w = XWINDOW (f->tool_bar_window);
   int hpos, vpos, prop_idx;
   struct glyph *glyph;
   Lisp_Object enabled_p;
@@ -12143,7 +12269,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
     return;
 
   /* If item is disabled, do nothing.  */
-  enabled_p = AREF (FVAR (f, tool_bar_items), prop_idx + TOOL_BAR_ITEM_ENABLED_P);
+  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
   if (NILP (enabled_p))
     return;
 
@@ -12151,7 +12277,6 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
     {
       /* Show item in pressed state.  */
       show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
-      hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
       last_tool_bar_item = prop_idx;
     }
   else
@@ -12162,9 +12287,8 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
 
       /* Show item in released state.  */
       show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
-      hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
 
-      key = AREF (FVAR (f, tool_bar_items), prop_idx + TOOL_BAR_ITEM_KEY);
+      key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
 
       XSETFRAME (frame, f);
       event.kind = TOOL_BAR_EVENT;
@@ -12189,7 +12313,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
 static void
 note_tool_bar_highlight (struct frame *f, int x, int y)
 {
-  Lisp_Object window = FVAR (f, tool_bar_window);
+  Lisp_Object window = f->tool_bar_window;
   struct window *w = XWINDOW (window);
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
@@ -12231,11 +12355,10 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
       && last_tool_bar_item != prop_idx)
     return;
 
-  hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
 
   /* If tool-bar item is not enabled, don't highlight it.  */
-  enabled_p = AREF (FVAR (f, tool_bar_items), prop_idx + TOOL_BAR_ITEM_ENABLED_P);
+  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
   if (!NILP (enabled_p))
     {
       /* Compute the x-position of the glyph.  In front and past the
@@ -12260,7 +12383,6 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
 
       /* Display it as active.  */
       show_mouse_face (hlinfo, draw);
-      hlinfo->mouse_face_image_state = draw;
     }
 
  set_help_echo:
@@ -12269,9 +12391,9 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
      XTread_socket does the rest.  */
   help_echo_object = help_echo_window = Qnil;
   help_echo_pos = -1;
-  help_echo_string = AREF (FVAR (f, tool_bar_items), prop_idx + TOOL_BAR_ITEM_HELP);
+  help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
   if (NILP (help_echo_string))
-    help_echo_string = AREF (FVAR (f, tool_bar_items), prop_idx + TOOL_BAR_ITEM_CAPTION);
+    help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
 }
 
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -12384,11 +12506,7 @@ hscroll_window_tree (Lisp_Object window)
              if (w == XWINDOW (selected_window))
                pt = PT;
              else
-               {
-                 pt = marker_position (w->pointm);
-                 pt = max (BEGV, pt);
-                 pt = min (ZV, pt);
-               }
+               pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
 
              /* Move iterator to pt starting at cursor_row->start in
                 a line with infinite width.  */
@@ -12540,15 +12658,14 @@ debug_method_add (struct window *w, char const *fmt, ...)
    buffer position, END is given as a distance from Z.  Used in
    redisplay_internal for display optimization.  */
 
-static inline int
+static int
 text_outside_line_unchanged_p (struct window *w,
                               ptrdiff_t start, ptrdiff_t end)
 {
   int unchanged_p = 1;
 
   /* If text or overlays have changed, see where.  */
-  if (w->last_modified < MODIFF
-      || w->last_overlay_modified < OVERLAY_MODIFF)
+  if (window_outdated (w))
     {
       /* Gap in the line?  */
       if (GPT < start || Z - GPT < end)
@@ -12751,7 +12868,7 @@ overlay_arrow_at_row (struct it *it, struct glyph_row *row)
                    return make_number (fringe_bitmap);
                }
 #endif
-             return make_number (-1); /* Use default arrow bitmap */
+             return make_number (-1); /* Use default arrow bitmap */
            }
          return overlay_arrow_string_or_property (var);
        }
@@ -12801,7 +12918,7 @@ check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
 /* Reconsider the setting of B->clip_changed which is displayed
    in window W.  */
 
-static inline void
+static void
 reconsider_clip_changes (struct window *w, struct buffer *b)
 {
   if (b->clip_changed
@@ -12836,37 +12953,6 @@ reconsider_clip_changes (struct window *w, struct buffer *b)
 }
 \f
 
-/* Select FRAME to forward the values of frame-local variables into C
-   variables so that the redisplay routines can access those values
-   directly.  */
-
-static void
-select_frame_for_redisplay (Lisp_Object frame)
-{
-  Lisp_Object tail, tem;
-  Lisp_Object old = selected_frame;
-  struct Lisp_Symbol *sym;
-
-  eassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
-
-  selected_frame = frame;
-
-  do {
-    for (tail = FVAR (XFRAME (frame), param_alist);
-        CONSP (tail); tail = XCDR (tail))
-      if (CONSP (XCAR (tail))
-         && (tem = XCAR (XCAR (tail)),
-             SYMBOLP (tem))
-         && (sym = indirect_variable (XSYMBOL (tem)),
-             sym->redirect == SYMBOL_LOCALIZED)
-         && sym->val.blv->frame_local)
-       /* Use find_symbol_value rather than Fsymbol_value
-          to avoid an error if it is void.  */
-       find_symbol_value (tem);
-  } while (!EQ (frame, old) && (frame = old, 1));
-}
-
-
 #define STOP_POLLING                                   \
 do { if (! polling_stopped_here) stop_polling ();      \
        polling_stopped_here = 1; } while (0)
@@ -12892,13 +12978,14 @@ redisplay_internal (void)
   ptrdiff_t count, count1;
   struct frame *sf;
   int polling_stopped_here = 0;
-  Lisp_Object old_frame = selected_frame;
+  Lisp_Object tail, frame;
+  struct backtrace backtrace;
 
   /* Non-zero means redisplay has to consider all windows on all
      frames.  Zero means, only selected_window is considered.  */
   int consider_all_windows_p;
 
-  /* Non-zero means redisplay has to redisplay the miniwindow */
+  /* Non-zero means redisplay has to redisplay the miniwindow */
   int update_miniwindow_p = 0;
 
   TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
@@ -12928,36 +13015,28 @@ redisplay_internal (void)
   if (redisplaying_p)
     return;
 
-  /* Record a function that resets redisplaying_p to its old value
+  /* Record a function that clears redisplaying_p
      when we leave this function.  */
   count = SPECPDL_INDEX ();
-  record_unwind_protect (unwind_redisplay,
-                        Fcons (make_number (redisplaying_p), selected_frame));
-  ++redisplaying_p;
+  record_unwind_protect (unwind_redisplay, selected_frame);
+  redisplaying_p = 1;
   specbind (Qinhibit_free_realized_faces, Qnil);
 
-  {
-    Lisp_Object tail, frame;
+  /* Record this function, so it appears on the profiler's backtraces.  */
+  backtrace.next = backtrace_list;
+  backtrace.function = Qredisplay_internal;
+  backtrace.args = &Qnil;
+  backtrace.nargs = 0;
+  backtrace.debug_on_exit = 0;
+  backtrace_list = &backtrace;
 
-    FOR_EACH_FRAME (tail, frame)
-      {
-       struct frame *f = XFRAME (frame);
-       f->already_hscrolled_p = 0;
-      }
-  }
+  FOR_EACH_FRAME (tail, frame)
+    XFRAME (frame)->already_hscrolled_p = 0;
 
  retry:
   /* Remember the currently selected window.  */
   sw = w;
 
-  if (!EQ (old_frame, selected_frame)
-      && FRAME_LIVE_P (XFRAME (old_frame)))
-    /* When running redisplay, we play a bit fast-and-loose and allow e.g.
-       selected_frame and selected_window to be temporarily out-of-sync so
-       when we come back here via `goto retry', we need to resync because we
-       may need to run Elisp code (via prepare_menu_bars).  */
-    select_frame_for_redisplay (old_frame);
-
   pending = 0;
   reconsider_clip_changes (w, current_buffer);
   last_escape_glyph_frame = NULL;
@@ -12994,25 +13073,20 @@ redisplay_internal (void)
       FRAME_TTY (sf)->previous_frame = sf;
     }
 
-  /* Set the visible flags for all frames.  Do this before checking
-     for resized or garbaged frames; they want to know if their frames
-     are visible.  See the comment in frame.h for
-     FRAME_SAMPLE_VISIBILITY.  */
-  {
-    Lisp_Object tail, frame;
-
-    number_of_visible_frames = 0;
+  /* Set the visible flags for all frames.  Do this before checking for
+     resized or garbaged frames; they want to know if their frames are
+     visible.  See the comment in frame.h for FRAME_SAMPLE_VISIBILITY.  */
+  number_of_visible_frames = 0;
 
-    FOR_EACH_FRAME (tail, frame)
-      {
-       struct frame *f = XFRAME (frame);
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
 
-       FRAME_SAMPLE_VISIBILITY (f);
-       if (FRAME_VISIBLE_P (f))
-         ++number_of_visible_frames;
-       clear_desired_matrices (f);
-      }
-  }
+      FRAME_SAMPLE_VISIBILITY (f);
+      if (FRAME_VISIBLE_P (f))
+       ++number_of_visible_frames;
+      clear_desired_matrices (f);
+    }
 
   /* Notice any pending interrupt request to change frame size.  */
   do_pending_window_change (1);
@@ -13026,8 +13100,7 @@ redisplay_internal (void)
     }
 
   /* Clear frames marked as garbaged.  */
-  if (frame_garbaged)
-    clear_garbaged_frames ();
+  clear_garbaged_frames ();
 
   /* Build menubar and tool-bar items.  */
   if (NILP (Vmemory_full))
@@ -13040,7 +13113,7 @@ redisplay_internal (void)
   if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
     {
       w->update_mode_line = 1;
-      if (buffer_shared > 1)
+      if (buffer_shared_and_changed ())
        update_mode_lines++;
     }
 
@@ -13048,24 +13121,15 @@ redisplay_internal (void)
   count1 = SPECPDL_INDEX ();
   specbind (Qinhibit_point_motion_hooks, Qt);
 
-  /* If %c is in the mode line, update it if needed.  */
-  if (!NILP (w->column_number_displayed)
-      /* This alternative quickly identifies a common case
-        where no change is needed.  */
-      && !(PT == w->last_point
-          && w->last_modified >= MODIFF
-          && w->last_overlay_modified >= OVERLAY_MODIFF)
-      && (XFASTINT (w->column_number_displayed) != current_column ()))
+  if (mode_line_update_needed (w))
     w->update_mode_line = 1;
 
   unbind_to (count1, Qnil);
 
   FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
 
-  /* The variable buffer_shared is set in redisplay_window and
-     indicates that we redisplay a buffer in different windows.  See
-     there.  */
-  consider_all_windows_p = (update_mode_lines || buffer_shared > 1
+  consider_all_windows_p = (update_mode_lines
+                           || buffer_shared_and_changed ()
                            || cursor_type_changed);
 
   /* If specs for an arrow have changed, do thorough redisplay
@@ -13111,23 +13175,20 @@ redisplay_internal (void)
          /* If window configuration was changed, frames may have been
             marked garbaged.  Clear them or we will experience
             surprises wrt scrolling.  */
-         if (frame_garbaged)
-           clear_garbaged_frames ();
+         clear_garbaged_frames ();
        }
     }
   else if (EQ (selected_window, minibuf_window)
-          && (current_buffer->clip_changed
-              || w->last_modified < MODIFF
-              || w->last_overlay_modified < OVERLAY_MODIFF)
+          && (current_buffer->clip_changed || window_outdated (w))
           && resize_mini_window (w, 0))
     {
       /* Resized active mini-window to fit the size of what it is
          showing if its contents might have changed.  */
       must_finish = 1;
-/* FIXME: this causes all frames to be updated, which seems unnecessary
-   since only the current frame needs to be considered.  This function needs
-   to be rewritten with two variables, consider_all_windows and
-   consider_all_frames.  */
+      /* FIXME: this causes all frames to be updated, which seems unnecessary
+        since only the current frame needs to be considered.  This function
+        needs to be rewritten with two variables, consider_all_windows and
+        consider_all_frames.  */
       consider_all_windows_p = 1;
       ++windows_or_buffers_changed;
       ++update_mode_lines;
@@ -13135,8 +13196,7 @@ redisplay_internal (void)
       /* If window configuration was changed, frames may have been
         marked garbaged.  Clear them or we will experience
         surprises wrt scrolling.  */
-      if (frame_garbaged)
-       clear_garbaged_frames ();
+      clear_garbaged_frames ();
     }
 
 
@@ -13183,9 +13243,7 @@ redisplay_internal (void)
              || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
        /* Former continuation line has disappeared by becoming empty.  */
        goto cancel;
-      else if (w->last_modified < MODIFF
-              || w->last_overlay_modified < OVERLAY_MODIFF
-              || MINI_WINDOW_P (w))
+      else if (window_outdated (w) || MINI_WINDOW_P (w))
        {
          /* We have to handle the case of continuation around a
             wide-column character (see the comment in indent.c around
@@ -13265,12 +13323,12 @@ redisplay_internal (void)
              if ((it.glyph_row - 1)->displays_text_p)
                {
                  if (XFASTINT (w->window_end_vpos) < this_line_vpos)
-                   XSETINT (w->window_end_vpos, this_line_vpos);
+                   wset_window_end_vpos (w, make_number (this_line_vpos));
                }
              else if (XFASTINT (w->window_end_vpos) == this_line_vpos
                       && this_line_vpos > 0)
-               XSETINT (w->window_end_vpos, this_line_vpos - 1);
-             w->window_end_valid = Qnil;
+               wset_window_end_vpos (w, make_number (this_line_vpos - 1));
+             wset_window_end_valid (w, Qnil);
 
              /* Update hint: No need to try to scroll in update_window.  */
              w->desired_matrix->no_scrolling_p = 1;
@@ -13359,7 +13417,7 @@ redisplay_internal (void)
     }
 
   CHARPOS (this_line_start_pos) = 0;
-  consider_all_windows_p |= buffer_shared > 1;
+  consider_all_windows_p |= buffer_shared_and_changed ();
   ++clear_face_cache_count;
 #ifdef HAVE_WINDOW_SYSTEM
   ++clear_image_cache_count;
@@ -13371,15 +13429,9 @@ redisplay_internal (void)
 
   if (consider_all_windows_p)
     {
-      Lisp_Object tail, frame;
-
       FOR_EACH_FRAME (tail, frame)
        XFRAME (frame)->updated_p = 0;
 
-      /* Recompute # windows showing selected buffer.  This will be
-        incremented each time such a window is displayed.  */
-      buffer_shared = 0;
-
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
@@ -13392,11 +13444,6 @@ redisplay_internal (void)
 
          if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
-             if (! EQ (frame, selected_frame))
-               /* Select the frame, for the sake of frame-local
-                  variables.  */
-               select_frame_for_redisplay (frame);
-
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
              if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
@@ -13426,7 +13473,7 @@ redisplay_internal (void)
                  if (!f->already_hscrolled_p)
                    {
                      f->already_hscrolled_p = 1;
-                     if (hscroll_windows (FVAR (f, root_window)))
+                     if (hscroll_windows (f->root_window))
                        goto retry;
                    }
 
@@ -13439,21 +13486,14 @@ redisplay_internal (void)
                  STOP_POLLING;
 
                  /* Update the display.  */
-                 set_window_update_flags (XWINDOW (FVAR (f, root_window)), 1);
+                 set_window_update_flags (XWINDOW (f->root_window), 1);
                  pending |= update_frame (f, 0, 0);
                  f->updated_p = 1;
                }
            }
        }
 
-      if (!EQ (old_frame, selected_frame)
-         && FRAME_LIVE_P (XFRAME (old_frame)))
-       /* We played a bit fast-and-loose above and allowed selected_frame
-          and selected_window to be temporarily out-of-sync but let's make
-          sure this stays contained.  */
-       select_frame_for_redisplay (old_frame);
-      eassert (EQ (FVAR (XFRAME (selected_frame), selected_window),
-                  selected_window));
+      eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
 
       if (!pending)
        {
@@ -13465,7 +13505,7 @@ redisplay_internal (void)
              struct frame *f = XFRAME (frame);
               if (f->updated_p)
                 {
-                  mark_window_display_accurate (FVAR (f, root_window), 1);
+                  mark_window_display_accurate (f->root_window, 1);
                   if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
                     FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
                 }
@@ -13582,7 +13622,6 @@ redisplay_internal (void)
      frames here explicitly.  */
   if (!pending)
     {
-      Lisp_Object tail, frame;
       int new_count = 0;
 
       FOR_EACH_FRAME (tail, frame)
@@ -13633,6 +13672,7 @@ redisplay_internal (void)
 #endif /* HAVE_WINDOW_SYSTEM */
 
  end_of_redisplay:
+  backtrace_list = backtrace.next;
   unbind_to (count, Qnil);
   RESUME_POLLING;
 }
@@ -13671,24 +13711,13 @@ redisplay_preserve_echo_area (int from_where)
 }
 
 
-/* Function registered with record_unwind_protect in
-   redisplay_internal.  Reset redisplaying_p to the value it had
-   before redisplay_internal was called, and clear
-   prevent_freeing_realized_faces_p.  It also selects the previously
-   selected frame, unless it has been deleted (by an X connection
-   failure during redisplay, for example).  */
+/* Function registered with record_unwind_protect in redisplay_internal.
+   Clear redisplaying_p.  Also select the previously selected frame.  */
 
 static Lisp_Object
-unwind_redisplay (Lisp_Object val)
+unwind_redisplay (Lisp_Object old_frame)
 {
-  Lisp_Object old_redisplaying_p, old_frame;
-
-  old_redisplaying_p = XCAR (val);
-  redisplaying_p = XFASTINT (old_redisplaying_p);
-  old_frame = XCDR (val);
-  if (! EQ (old_frame, selected_frame)
-      && FRAME_LIVE_P (XFRAME (old_frame)))
-    select_frame_for_redisplay (old_frame);
+  redisplaying_p = 0;
   return Qnil;
 }
 
@@ -13705,8 +13734,8 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p)
     {
       struct buffer *b = XBUFFER (w->buffer);
 
-      w->last_modified = accurate_p ? BUF_MODIFF(b) : 0;
-      w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF(b) : 0;
+      w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
+      w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
       w->last_had_star
        = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
 
@@ -13730,13 +13759,13 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p)
          if (w == XWINDOW (selected_window))
            w->last_point = BUF_PT (b);
          else
-           w->last_point = XMARKER (w->pointm)->charpos;
+           w->last_point = marker_position (w->pointm);
        }
     }
 
   if (accurate_p)
     {
-      w->window_end_valid = w->buffer;
+      wset_window_end_valid (w, w->buffer);
       w->update_mode_line = 0;
     }
 }
@@ -14152,7 +14181,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
      GLYPH_BEFORE and GLYPH_AFTER.  */
   if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
        && BUFFERP (glyph->object) && glyph->charpos == pt_old)
-      && bpos_covered < pt_old)
+      && !(bpos_max < pt_old && pt_old <= bpos_covered))
     {
       /* An empty line has a single glyph whose OBJECT is zero and
         whose CHARPOS is the position of a newline on that line.
@@ -14161,7 +14190,12 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
         CHARPOS is zero or negative.  */
       int empty_line_p =
        (row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
-       && INTEGERP (glyph->object) && glyph->charpos > 0;
+       && INTEGERP (glyph->object) && glyph->charpos > 0
+       /* On a TTY, continued and truncated rows also have a glyph at
+          their end whose OBJECT is zero and whose CHARPOS is
+          positive (the continuation and truncation glyphs), but such
+          rows are obviously not "empty".  */
+       && !(row->continued_p || row->truncated_on_right_p);
 
       if (row->ends_in_ellipsis_p && pos_after == last_pos)
        {
@@ -14384,7 +14418,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
       for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
        {
          if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
-           abort ();
+           emacs_abort ();
          x += g->pixel_width;
        }
     }
@@ -14498,14 +14532,14 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 
    We assume that the window's buffer is really current.  */
 
-static inline struct text_pos
+static struct text_pos
 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
 {
   struct window *w = XWINDOW (window);
   SET_MARKER_FROM_TEXT_POS (w->start, startp);
 
   if (current_buffer != XBUFFER (w->buffer))
-    abort ();
+    emacs_abort ();
 
   if (!NILP (Vwindow_scroll_functions))
     {
@@ -14513,8 +14547,7 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
                            make_number (CHARPOS (startp)));
       SET_TEXT_POS_FROM_MARKER (startp, w->start);
       /* In case the hook functions switch buffers.  */
-      if (current_buffer != XBUFFER (w->buffer))
-       set_buffer_internal_1 (XBUFFER (w->buffer));
+      set_buffer_internal (XBUFFER (w->buffer));
     }
 
   return startp;
@@ -14712,13 +14745,18 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          if (NUMBERP (aggressive))
            {
              double float_amount = XFLOATINT (aggressive) * height;
-             amount_to_scroll = float_amount;
-             if (amount_to_scroll == 0 && float_amount > 0)
-               amount_to_scroll = 1;
+             int aggressive_scroll = float_amount;
+             if (aggressive_scroll == 0 && float_amount > 0)
+               aggressive_scroll = 1;
              /* Don't let point enter the scroll margin near top of
-                the window.  */
-             if (amount_to_scroll > height - 2*this_scroll_margin + dy)
-               amount_to_scroll = height - 2*this_scroll_margin + dy;
+                the window.  This could happen if the value of
+                scroll_up_aggressively is too large and there are
+                non-zero margins, because scroll_up_aggressively
+                means put point that fraction of window height
+                _from_the_bottom_margin_.  */
+             if (aggressive_scroll + 2*this_scroll_margin > height)
+               aggressive_scroll = height - 2*this_scroll_margin;
+             amount_to_scroll = dy + aggressive_scroll;
            }
        }
 
@@ -14778,7 +14816,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          /* Compute the vertical distance from PT to the scroll
             margin position.  Move as far as scroll_max allows, or
             one screenful, or 10 screen lines, whichever is largest.
-            Give up if distance is greater than scroll_max.  */
+            Give up if distance is greater than scroll_max or if we
+            didn't reach the scroll margin position.  */
          SET_TEXT_POS (pos, PT, PT_BYTE);
          start_display (&it, w, pos);
          y0 = it.current_y;
@@ -14788,7 +14827,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
                      y_to_move, -1,
                      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
          dy = it.current_y - y0;
-         if (dy > scroll_max)
+         if (dy > scroll_max
+             || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
            return SCROLLING_FAILED;
 
          /* Compute new window start.  */
@@ -14806,15 +14846,16 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
              if (NUMBERP (aggressive))
                {
                  double float_amount = XFLOATINT (aggressive) * height;
-                 amount_to_scroll = float_amount;
-                 if (amount_to_scroll == 0 && float_amount > 0)
-                   amount_to_scroll = 1;
-                 amount_to_scroll -=
-                   this_scroll_margin - dy - FRAME_LINE_HEIGHT (f);
+                 int aggressive_scroll = float_amount;
+                 if (aggressive_scroll == 0 && float_amount > 0)
+                   aggressive_scroll = 1;
                  /* Don't let point enter the scroll margin near
-                    bottom of the window.  */
-                 if (amount_to_scroll > height - 2*this_scroll_margin + dy)
-                   amount_to_scroll = height - 2*this_scroll_margin + dy;
+                    bottom of the window, if the value of
+                    scroll_down_aggressively happens to be too
+                    large.  */
+                 if (aggressive_scroll + 2*this_scroll_margin > height)
+                   aggressive_scroll = height - 2*this_scroll_margin;
+                 amount_to_scroll = dy + aggressive_scroll;
                }
            }
 
@@ -14844,7 +14885,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
       if (!just_this_one_p
          || current_buffer->clip_changed
          || BEG_UNCHANGED < CHARPOS (startp))
-       w->base_line_number = Qnil;
+       wset_base_line_number (w, Qnil);
 
       /* If cursor ends up on a partially visible line,
         treat that as being off the bottom of the screen.  */
@@ -14992,8 +15033,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
       /* Can't use this case if highlighting a region.  When a
          region exists, cursor movement has to do more than just
          set the cursor.  */
-      && !(!NILP (Vtransient_mark_mode)
-          && !NILP (BVAR (current_buffer, mark_active)))
+      && markpos_of_region () < 0
       && NILP (w->region_showing)
       && NILP (Vshow_trailing_whitespace)
       /* This code is not used for mini-buffer for the sake of the case
@@ -15342,7 +15382,7 @@ set_vertical_scroll_bar (struct window *w)
    selected_window is redisplayed.
 
    We can return without actually redisplaying the window if
-   fonts_changed_p is nonzero.  In that case, redisplay_internal will
+   fonts_changed_p.  In that case, redisplay_internal will
    retry.  */
 
 static void
@@ -15434,8 +15474,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
     = (!NILP (w->window_end_valid)
        && !current_buffer->clip_changed
        && !current_buffer->prevent_redisplay_optimizations_p
-       && w->last_modified >= MODIFF
-       && w->last_overlay_modified >= OVERLAY_MODIFF);
+       && !window_outdated (w));
 
   /* Run the window-bottom-change-functions
      if it is possible that the text on the screen has changed
@@ -15457,8 +15496,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   buffer_unchanged_p
     = (!NILP (w->window_end_valid)
        && !current_buffer->clip_changed
-       && w->last_modified >= MODIFF
-       && w->last_overlay_modified >= OVERLAY_MODIFF);
+       && !window_outdated (w));
 
   /* When windows_or_buffers_changed is non-zero, we can't rely on
      the window end being valid, so set it to nil there.  */
@@ -15469,46 +15507,24 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
       if (XMARKER (w->start)->buffer == current_buffer)
        compute_window_start_on_continuation_line (w);
 
-      w->window_end_valid = Qnil;
+      wset_window_end_valid (w, Qnil);
     }
 
   /* Some sanity checks.  */
   CHECK_WINDOW_END (w);
   if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
-    abort ();
+    emacs_abort ();
   if (BYTEPOS (opoint) < CHARPOS (opoint))
-    abort ();
-
-  /* If %c is in mode line, update it if needed.  */
-  if (!NILP (w->column_number_displayed)
-      /* This alternative quickly identifies a common case
-        where no change is needed.  */
-      && !(PT == w->last_point
-          && w->last_modified >= MODIFF
-          && w->last_overlay_modified >= OVERLAY_MODIFF)
-      && (XFASTINT (w->column_number_displayed) != current_column ()))
-    update_mode_line = 1;
+    emacs_abort ();
 
-  /* Count number of windows showing the selected buffer.  An indirect
-     buffer counts as its base buffer.  */
-  if (!just_this_one_p)
-    {
-      struct buffer *current_base, *window_base;
-      current_base = current_buffer;
-      window_base = XBUFFER (XWINDOW (selected_window)->buffer);
-      if (current_base->base_buffer)
-       current_base = current_base->base_buffer;
-      if (window_base->base_buffer)
-       window_base = window_base->base_buffer;
-      if (current_base == window_base)
-       buffer_shared++;
-    }
+  if (mode_line_update_needed (w))
+    update_mode_line = 1;
 
   /* Point refers normally to the selected window.  For any other
      window, set up appropriate value.  */
   if (!EQ (window, selected_window))
     {
-      ptrdiff_t new_pt = XMARKER (w->pointm)->charpos;
+      ptrdiff_t new_pt = marker_position (w->pointm);
       ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
       if (new_pt < BEGV)
        {
@@ -15536,8 +15552,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
     {
       struct Lisp_Char_Table *disptab = buffer_display_table ();
 
-      if (! disptab_matches_widthtab (disptab,
-                                      XVECTOR (BVAR (current_buffer, width_table))))
+      if (! disptab_matches_widthtab
+         (disptab, XVECTOR (BVAR (current_buffer, width_table))))
         {
           invalidate_region_cache (current_buffer,
                                    current_buffer->width_run_cache,
@@ -15580,11 +15596,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
       w->force_start = 0;
       w->vscroll = 0;
-      w->window_end_valid = Qnil;
+      wset_window_end_valid (w, Qnil);
 
       /* Forget any recorded base line for line number display.  */
       if (!buffer_unchanged_p)
-       w->base_line_number = Qnil;
+       wset_base_line_number (w, Qnil);
 
       /* Redisplay the mode line.  Select the buffer properly for that.
         Also, run the hook window-scroll-functions
@@ -15634,6 +15650,34 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
             Move it back to a fully-visible line.  */
          new_vpos = window_box_height (w);
        }
+      else if (w->cursor.vpos >=0)
+       {
+         /* Some people insist on not letting point enter the scroll
+            margin, even though this part handles windows that didn't
+            scroll at all.  */
+         int margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+         int pixel_margin = margin * FRAME_LINE_HEIGHT (f);
+         bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
+
+         /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
+            below, which finds the row to move point to, advances by
+            the Y coordinate of the _next_ row, see the definition of
+            MATRIX_ROW_BOTTOM_Y.  */
+         if (w->cursor.vpos < margin + header_line)
+           new_vpos
+             = pixel_margin + (header_line
+                               ? CURRENT_HEADER_LINE_HEIGHT (w)
+                               : 0) + FRAME_LINE_HEIGHT (f);
+         else
+           {
+             int window_height = window_box_height (w);
+
+             if (header_line)
+               window_height += CURRENT_HEADER_LINE_HEIGHT (w);
+             if (w->cursor.y >= window_height - pixel_margin)
+               new_vpos = window_height - pixel_margin;
+           }
+       }
 
       /* If we need to move point for either of the above reasons,
         now actually do it.  */
@@ -15657,8 +15701,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
          /* If we are highlighting the region, then we just changed
             the region, so redisplay to show it.  */
-         if (!NILP (Vtransient_mark_mode)
-             && !NILP (BVAR (current_buffer, mark_active)))
+         if (0 <= markpos_of_region ())
            {
              clear_glyph_matrix (w->desired_matrix);
              if (!try_window (window, startp, 0))
@@ -15689,7 +15732,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          goto try_to_scroll;
 
        default:
-         abort ();
+         emacs_abort ();
        }
     }
   /* If current starting point was originally the beginning of a line
@@ -15727,8 +15770,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
           && (CHARPOS (startp) < ZV
               /* Avoid starting at end of buffer.  */
               || CHARPOS (startp) == BEGV
-              || (w->last_modified >= MODIFF
-                  && w->last_overlay_modified >= OVERLAY_MODIFF)))
+              || !window_outdated (w)))
     {
       int d1, d2, d3, d4, d5, d6;
 
@@ -15798,7 +15840,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
              || current_buffer->clip_changed
              || BEG_UNCHANGED < CHARPOS (startp))
            /* Forget any recorded base line for line number display.  */
-           w->base_line_number = Qnil;
+           wset_base_line_number (w, Qnil);
 
          if (!cursor_row_fully_visible_p (w, 1, 0))
            {
@@ -15852,7 +15894,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          break;
 
        default:
-         abort ();
+         emacs_abort ();
        }
     }
 
@@ -15869,7 +15911,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
   /* Forget any previously recorded base line for line number display.  */
   if (!buffer_unchanged_p)
-    w->base_line_number = Qnil;
+    wset_base_line_number (w, Qnil);
 
   /* Determine the window start relative to point.  */
   init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
@@ -16127,8 +16169,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   if (!line_number_displayed
       && !BUFFERP (w->base_line_pos))
     {
-      w->base_line_pos = Qnil;
-      w->base_line_number = Qnil;
+      wset_base_line_pos (w, Qnil);
+      wset_base_line_number (w, Qnil);
     }
 
  finish_menu_bars:
@@ -16161,7 +16203,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          if (FRAME_EXTERNAL_TOOL_BAR (f))
            redisplay_tool_bar (f);
 #else
-         if (WINDOWP (FVAR (f, tool_bar_window))
+         if (WINDOWP (f->tool_bar_window)
              && (FRAME_TOOL_BAR_LINES (f) > 0
                  || !NILP (Vauto_resize_tool_bars))
              && redisplay_tool_bar (f))
@@ -16178,15 +16220,15 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
                                    || w->pseudo_window_p)))
     {
       update_begin (f);
-      BLOCK_INPUT;
+      block_input ();
       if (draw_window_fringes (w, 1))
        x_draw_vertical_border (w);
-      UNBLOCK_INPUT;
+      unblock_input ();
       update_end (f);
     }
 #endif /* HAVE_WINDOW_SYSTEM */
 
-  /* We go to this label, with fonts_changed_p nonzero,
+  /* We go to this label, with fonts_changed_p set,
      if it is necessary to try again using larger glyph matrices.
      We have to redeem the scroll bar even in this case,
      because the loop in redisplay_internal expects that.  */
@@ -16305,22 +16347,23 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
       eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
       w->window_end_bytepos
        = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-      w->window_end_pos
-       = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-      w->window_end_vpos
-       = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
-      eassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
-              ->displays_text_p);
+      wset_window_end_pos
+       (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
+      wset_window_end_vpos
+       (w, make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix)));
+      eassert
+       (MATRIX_ROW (w->desired_matrix,
+                    XFASTINT (w->window_end_vpos))->displays_text_p);
     }
   else
     {
       w->window_end_bytepos = Z_BYTE - ZV_BYTE;
-      w->window_end_pos = make_number (Z - ZV);
-      w->window_end_vpos = make_number (0);
+      wset_window_end_pos (w, make_number (Z - ZV));
+      wset_window_end_vpos (w, make_number (0));
     }
 
   /* But that is not valid info until redisplay finishes.  */
-  w->window_end_valid = Qnil;
+  wset_window_end_valid (w, Qnil);
   return 1;
 }
 
@@ -16363,8 +16406,7 @@ try_window_reusing_current_matrix (struct window *w)
     return 0;
 
   /* Can't do this if region may have changed.  */
-  if ((!NILP (Vtransient_mark_mode)
-       && !NILP (BVAR (current_buffer, mark_active)))
+  if (0 <= markpos_of_region ()
       || !NILP (w->region_showing)
       || !NILP (Vshow_trailing_whitespace))
     return 0;
@@ -16544,29 +16586,31 @@ try_window_reusing_current_matrix (struct window *w)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
-         w->window_end_pos
-           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
-         w->window_end_vpos
-           = make_number (MATRIX_ROW_VPOS (last_reused_text_row,
-                                           w->current_matrix));
+         wset_window_end_pos
+           (w, make_number (Z
+                            - MATRIX_ROW_END_CHARPOS (last_reused_text_row)));
+         wset_window_end_vpos
+           (w, make_number (MATRIX_ROW_VPOS (last_reused_text_row,
+                                             w->current_matrix)));
        }
       else if (last_text_row)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-         w->window_end_pos
-           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-         w->window_end_vpos
-           = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+         wset_window_end_pos
+           (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
+         wset_window_end_vpos
+           (w, make_number (MATRIX_ROW_VPOS (last_text_row,
+                                             w->desired_matrix)));
        }
       else
        {
          /* This window must be completely empty.  */
          w->window_end_bytepos = Z_BYTE - ZV_BYTE;
-         w->window_end_pos = make_number (Z - ZV);
-         w->window_end_vpos = make_number (0);
+         wset_window_end_pos (w, make_number (Z - ZV));
+         wset_window_end_vpos (w, make_number (0));
        }
-      w->window_end_valid = Qnil;
+      wset_window_end_valid (w, Qnil);
 
       /* Update hint: don't try scrolling again in update_window.  */
       w->desired_matrix->no_scrolling_p = 1;
@@ -16715,28 +16759,33 @@ try_window_reusing_current_matrix (struct window *w)
            }
          if (row < bottom_row)
            {
-             struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
-             struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
-
-             /* Can't use this optimization with bidi-reordered glyph
-                rows, unless cursor is already at point. */
+             /* Can't simply scan the row for point with
+                bidi-reordered glyph rows.  Let set_cursor_from_row
+                figure out where to put the cursor, and if it fails,
+                give up.  */
              if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
                {
-                 if (!(w->cursor.hpos >= 0
-                       && w->cursor.hpos < row->used[TEXT_AREA]
-                       && BUFFERP (glyph->object)
-                       && glyph->charpos == PT))
-                   return 0;
+                 if (!set_cursor_from_row (w, row, w->current_matrix,
+                                           0, 0, 0, 0))
+                   {
+                     clear_glyph_matrix (w->desired_matrix);
+                     return 0;
+                   }
                }
              else
-               for (; glyph < end
-                      && (!BUFFERP (glyph->object)
-                          || glyph->charpos < PT);
-                    glyph++)
-                 {
-                   w->cursor.hpos++;
-                   w->cursor.x += glyph->pixel_width;
-                 }
+               {
+                 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
+                 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
+
+                 for (; glyph < end
+                        && (!BUFFERP (glyph->object)
+                            || glyph->charpos < PT);
+                      glyph++)
+                   {
+                     w->cursor.hpos++;
+                     w->cursor.x += glyph->pixel_width;
+                   }
+               }
            }
        }
 
@@ -16747,18 +16796,19 @@ try_window_reusing_current_matrix (struct window *w)
        {
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-         w->window_end_pos
-           = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
-         w->window_end_vpos
-           = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+         wset_window_end_pos
+           (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
+         wset_window_end_vpos
+           (w, make_number (MATRIX_ROW_VPOS (last_text_row,
+                                             w->desired_matrix)));
        }
       else
        {
-         w->window_end_vpos
-           = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
+         wset_window_end_vpos
+           (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled));
        }
 
-      w->window_end_valid = Qnil;
+      wset_window_end_valid (w, Qnil);
       w->desired_matrix->no_scrolling_p = 1;
 
 #ifdef GLYPH_DEBUG
@@ -17188,8 +17238,7 @@ try_window_id (struct window *w)
 
   /* Can't use this if highlighting a region because a cursor movement
      will do more than just set the cursor.  */
-  if (!NILP (Vtransient_mark_mode)
-      && !NILP (BVAR (current_buffer, mark_active)))
+  if (0 <= markpos_of_region ())
     GIVE_UP (9);
 
   /* Likewise if highlighting trailing whitespace.  */
@@ -17296,7 +17345,7 @@ try_window_id (struct window *w)
          if (row)
            set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
          else
-           abort ();
+           emacs_abort ();
          return 1;
        }
     }
@@ -17330,8 +17379,8 @@ try_window_id (struct window *w)
        {
          /* We have to compute the window end anew since text
             could have been added/removed after it.  */
-         w->window_end_pos
-           = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+         wset_window_end_pos
+           (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
          w->window_end_bytepos
            = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
 
@@ -17340,7 +17389,7 @@ try_window_id (struct window *w)
          if (row)
            set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
          else
-           abort ();
+           emacs_abort ();
          return 2;
        }
     }
@@ -17663,15 +17712,15 @@ try_window_id (struct window *w)
     {
       rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
                     bottom_vpos, dvpos);
-      enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
-                               bottom_vpos, 0);
+      clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
+                              bottom_vpos);
     }
   else if (dvpos > 0)
     {
       rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
                     bottom_vpos, dvpos);
-      enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
-                               first_unchanged_at_end_vpos + dvpos, 0);
+      clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
+                              first_unchanged_at_end_vpos + dvpos);
     }
 
   /* For frame-based redisplay, make sure that current frame and window
@@ -17765,21 +17814,22 @@ try_window_id (struct window *w)
                                           first_unchanged_at_end_row);
       eassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
 
-      w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+      wset_window_end_pos (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
-      w->window_end_vpos
-       = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
+      wset_window_end_vpos
+       (w, make_number (MATRIX_ROW_VPOS (row, w->current_matrix)));
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "A"));
     }
   else if (last_text_row_at_end)
     {
-      w->window_end_pos
-       = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
+      wset_window_end_pos
+       (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end)));
       w->window_end_bytepos
        = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
-      w->window_end_vpos
-       = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
+      wset_window_end_vpos
+       (w, make_number (MATRIX_ROW_VPOS (last_text_row_at_end,
+                                         desired_matrix)));
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "B"));
     }
@@ -17788,12 +17838,12 @@ try_window_id (struct window *w)
       /* We have displayed either to the end of the window or at the
         end of the window, i.e. the last row with text is to be found
         in the desired matrix.  */
-      w->window_end_pos
-       = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+      wset_window_end_pos
+       (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
       w->window_end_bytepos
        = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
-      w->window_end_vpos
-       = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
+      wset_window_end_vpos
+       (w, make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix)));
       eassert (w->window_end_bytepos >= 0);
     }
   else if (first_unchanged_at_end_row == NULL
@@ -17821,20 +17871,20 @@ try_window_id (struct window *w)
        }
 
       eassert (row != NULL);
-      w->window_end_vpos = make_number (vpos + 1);
-      w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+      wset_window_end_vpos (w, make_number (vpos + 1));
+      wset_window_end_pos (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "C"));
     }
   else
-    abort ();
+    emacs_abort ();
 
   IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
            debug_end_vpos = XFASTINT (w->window_end_vpos));
 
   /* Record that display has not been completed.  */
-  w->window_end_valid = Qnil;
+  wset_window_end_valid (w, Qnil);
   w->desired_matrix->no_scrolling_p = 1;
   return 3;
 
@@ -18116,7 +18166,7 @@ GLYPH > 1 or omitted means dump glyphs in long form.  */)
   (Lisp_Object row, Lisp_Object glyphs)
 {
   struct frame *sf = SELECTED_FRAME ();
-  struct glyph_matrix *m = XWINDOW (FVAR (sf, tool_bar_window))->current_matrix;
+  struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
   EMACS_INT vpos;
 
   CHECK_NUMBER (row);
@@ -18521,6 +18571,7 @@ append_space_for_newline (struct it *it, int default_face_p)
          int saved_char_to_display = it->char_to_display;
          int saved_x = it->current_x;
          int saved_face_id = it->face_id;
+         int saved_box_end = it->end_of_box_run_p;
          struct text_pos saved_pos;
          Lisp_Object saved_object;
          struct face *face;
@@ -18542,6 +18593,16 @@ append_space_for_newline (struct it *it, int default_face_p)
            it->face_id = it->saved_face_id;
          face = FACE_FROM_ID (it->f, it->face_id);
          it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
+         /* In R2L rows, we will prepend a stretch glyph that will
+            have the end_of_box_run_p flag set for it, so there's no
+            need for the appended newline glyph to have that flag
+            set.  */
+         if (it->glyph_row->reversed_p
+             /* But if the appended newline glyph goes all the way to
+                the end of the row, there will be no stretch glyph,
+                so leave the box flag set.  */
+             && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x)
+           it->end_of_box_run_p = 0;
 
          PRODUCE_GLYPHS (it);
 
@@ -18555,6 +18616,7 @@ append_space_for_newline (struct it *it, int default_face_p)
          it->len = saved_len;
          it->c = saved_c;
          it->char_to_display = saved_char_to_display;
+         it->end_of_box_run_p = saved_box_end;
          return 1;
        }
     }
@@ -18644,7 +18706,7 @@ extend_face_to_end_of_line (struct it *it)
          struct glyph *g;
          int row_width, stretch_ascent, stretch_width;
          struct text_pos saved_pos;
-         int saved_face_id, saved_avoid_cursor;
+         int saved_face_id, saved_avoid_cursor, saved_box_start;
 
          for (row_width = 0, g = row_start; g < row_end; g++)
            row_width += g->pixel_width;
@@ -18659,6 +18721,7 @@ extend_face_to_end_of_line (struct it *it)
              saved_avoid_cursor = it->avoid_cursor_p;
              it->avoid_cursor_p = 1;
              saved_face_id = it->face_id;
+             saved_box_start = it->start_of_box_run_p;
              /* The last row's stretch glyph should get the default
                 face, to avoid painting the rest of the window with
                 the region face, if the region ends at ZV.  */
@@ -18666,11 +18729,13 @@ extend_face_to_end_of_line (struct it *it)
                it->face_id = default_face->id;
              else
                it->face_id = face->id;
+             it->start_of_box_run_p = 0;
              append_stretch_glyph (it, make_number (0), stretch_width,
                                    it->ascent + it->descent, stretch_ascent);
              it->position = saved_pos;
              it->avoid_cursor_p = saved_avoid_cursor;
              it->face_id = saved_face_id;
+             it->start_of_box_run_p = saved_box_start;
            }
        }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -19205,7 +19270,7 @@ find_row_edges (struct it *it, struct glyph_row *row,
        /* A line that is entirely from a string/image/stretch...  */
        row->maxpos = row->minpos;
       else
-       abort ();
+       emacs_abort ();
     }
   else
     row->maxpos = it->current.pos;
@@ -19247,7 +19312,7 @@ display_line (struct it *it)
     }
 
   /* Is IT->w showing the region?  */
-  it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
+  wset_region_showing (it->w, it->region_beg_charpos > 0 ? Qt : Qnil);
 
   /* Clear the result glyph row and enable it.  */
   prepare_desired_row (row);
@@ -20046,7 +20111,7 @@ See also `bidi-paragraph-direction'.  */)
          return Qright_to_left;
          break;
        default:
-         abort ();
+         emacs_abort ();
        }
     }
 }
@@ -20101,8 +20166,8 @@ display_menu_bar (struct window *w)
       /* Menu bar lines are displayed in the desired matrix of the
         dummy window menu_bar_window.  */
       struct window *menu_w;
-      eassert (WINDOWP (FVAR (f, menu_bar_window)));
-      menu_w = XWINDOW (FVAR (f, menu_bar_window));
+      eassert (WINDOWP (f->menu_bar_window));
+      menu_w = XWINDOW (f->menu_bar_window);
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
@@ -20124,10 +20189,6 @@ display_menu_bar (struct window *w)
      this.  */
   it.paragraph_embedding = L2R;
 
-  if (! mode_line_inverse_video)
-    /* Force the menu-bar to be displayed in the default face.  */
-    it.base_face_id = it.face_id = DEFAULT_FACE_ID;
-
   /* Clear all rows of the menu bar.  */
   for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
     {
@@ -20241,17 +20302,21 @@ redisplay_mode_lines (Lisp_Object window, int force)
 static int
 display_mode_lines (struct window *w)
 {
-  Lisp_Object old_selected_window, old_selected_frame;
+  Lisp_Object old_selected_window = selected_window;
+  Lisp_Object old_selected_frame = selected_frame;
+  Lisp_Object new_frame = w->frame;
+  Lisp_Object old_frame_selected_window = XFRAME (new_frame)->selected_window;
   int n = 0;
 
-  old_selected_frame = selected_frame;
-  selected_frame = w->frame;
-  old_selected_window = selected_window;
+  selected_frame = new_frame;
+  /* FIXME: If we were to allow the mode-line's computation changing the buffer
+     or window's point, then we'd need select_window_1 here as well.  */
   XSETWINDOW (selected_window, w);
+  XFRAME (new_frame)->selected_window = selected_window;
 
   /* These will be set while the mode line specs are processed.  */
   line_number_displayed = 0;
-  w->column_number_displayed = Qnil;
+  wset_column_number_displayed (w, Qnil);
 
   if (WINDOW_WANTS_MODELINE_P (w))
     {
@@ -20270,6 +20335,7 @@ display_mode_lines (struct window *w)
       ++n;
     }
 
+  XFRAME (new_frame)->selected_window = old_frame_selected_window;
   selected_frame = old_selected_frame;
   selected_window = old_selected_window;
   return n;
@@ -20297,10 +20363,6 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
 
   it.glyph_row->mode_line_p = 1;
 
-  if (! mode_line_inverse_video)
-    /* Force the mode-line to be displayed in the default face.  */
-    it.base_face_id = it.face_id = DEFAULT_FACE_ID;
-
   /* FIXME: This should be controlled by a user option.  But
      supporting such an option is not trivial, since the mode line is
      made up of many separate strings.  */
@@ -20975,10 +21037,8 @@ are the selected window and the WINDOW's buffer).  */)
   Lisp_Object str;
   int string_start = 0;
 
-  if (NILP (window))
-    window = selected_window;
-  CHECK_WINDOW (window);
-  w = XWINDOW (window);
+  w = decode_any_window (window);
+  XSETWINDOW (window, w);
 
   if (NILP (buffer))
     buffer = w->buffer;
@@ -21001,20 +21061,18 @@ are the selected window and the WINDOW's buffer).  */)
     : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
     : DEFAULT_FACE_ID;
 
-  if (XBUFFER (buffer) != current_buffer)
-    old_buffer = current_buffer;
+  old_buffer = current_buffer;
 
   /* Save things including mode_line_proptrans_alist,
      and set that to nil so that we don't alter the outer value.  */
   record_unwind_protect (unwind_format_mode_line,
                         format_mode_line_unwind_data
-                          (XFRAME (WINDOW_FRAME (XWINDOW (window))),
+                          (XFRAME (WINDOW_FRAME (w)),
                            old_buffer, selected_window, 1));
   mode_line_proptrans_alist = Qnil;
 
   Fselect_window (window, Qt);
-  if (old_buffer)
-    set_buffer_internal_1 (XBUFFER (buffer));
+  set_buffer_internal_1 (XBUFFER (buffer));
 
   init_iterator (&it, w, -1, -1, NULL, face_id);
 
@@ -21293,6 +21351,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
   Lisp_Object obj;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
+  /* We are going to use f->decode_mode_spec_buffer as the buffer to
+     produce strings from numerical values, so limit preposterously
+     large values of FIELD_WIDTH to avoid overrunning the buffer's
+     end.  The size of the buffer is enough for FRAME_MESSAGE_BUF_SIZE
+     bytes plus the terminating null.  */
+  int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
   struct buffer *b = current_buffer;
 
   obj = Qnil;
@@ -21357,8 +21421,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        register int i;
 
        /* Let lots_of_dashes be a string of infinite length.  */
-       if (mode_line_target == MODE_LINE_NOPROP ||
-           mode_line_target == MODE_LINE_STRING)
+       if (mode_line_target == MODE_LINE_NOPROP
+           || mode_line_target == MODE_LINE_STRING)
          return "--";
        if (field_width <= 0
            || field_width > sizeof (lots_of_dashes))
@@ -21387,8 +21451,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
       else
        {
          ptrdiff_t col = current_column ();
-         w->column_number_displayed = make_number (col);
-         pint2str (decode_mode_spec_buf, field_width, col);
+         wset_column_number_displayed (w, make_number (col));
+         pint2str (decode_mode_spec_buf, width, col);
          return decode_mode_spec_buf;
        }
 
@@ -21406,10 +21470,10 @@ decode_mode_spec (struct window *w, register int c, int field_width,
 
     case 'F':
       /* %F displays the frame name.  */
-      if (!NILP (FVAR (f, title)))
-       return SSDATA (FVAR (f, title));
+      if (!NILP (f->title))
+       return SSDATA (f->title);
       if (f->explicit_name || ! FRAME_WINDOW_P (f))
-       return SSDATA (FVAR (f, name));
+       return SSDATA (f->name);
       return "Emacs";
 
     case 'f':
@@ -21419,14 +21483,14 @@ decode_mode_spec (struct window *w, register int c, int field_width,
     case 'i':
       {
        ptrdiff_t size = ZV - BEGV;
-       pint2str (decode_mode_spec_buf, field_width, size);
+       pint2str (decode_mode_spec_buf, width, size);
        return decode_mode_spec_buf;
       }
 
     case 'I':
       {
        ptrdiff_t size = ZV - BEGV;
-       pint2hrstr (decode_mode_spec_buf, field_width, size);
+       pint2hrstr (decode_mode_spec_buf, width, size);
        return decode_mode_spec_buf;
       }
 
@@ -21440,7 +21504,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        if (mode_line_target == MODE_LINE_TITLE)
          return "";
 
-       startpos = XMARKER (w->start)->charpos;
+       startpos = marker_position (w->start);
        startpos_byte = marker_byte_position (w->start);
        height = WINDOW_TOTAL_LINES (w);
 
@@ -21450,14 +21514,14 @@ decode_mode_spec (struct window *w, register int c, int field_width,
          goto no_value;
        /* But do forget it, if the window shows a different buffer now.  */
        else if (BUFFERP (w->base_line_pos))
-         w->base_line_pos = Qnil;
+         wset_base_line_pos (w, Qnil);
 
        /* If the buffer is very big, don't waste time.  */
        if (INTEGERP (Vline_number_display_limit)
            && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
          {
-           w->base_line_pos = Qnil;
-           w->base_line_number = Qnil;
+           wset_base_line_pos (w, Qnil);
+           wset_base_line_number (w, Qnil);
            goto no_value;
          }
 
@@ -21489,8 +21553,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
           go back past it.  */
        if (startpos == BUF_BEGV (b))
          {
-           w->base_line_number = make_number (topline);
-           w->base_line_pos = make_number (BUF_BEGV (b));
+           wset_base_line_number (w, make_number (topline));
+           wset_base_line_pos (w, make_number (BUF_BEGV (b)));
          }
        else if (nlines < height + 25 || nlines > height * 3 + 50
                 || linepos == BUF_BEGV (b))
@@ -21516,13 +21580,13 @@ decode_mode_spec (struct window *w, register int c, int field_width,
               give up on line numbers for this window.  */
            if (position == limit_byte && limit == startpos - distance)
              {
-               w->base_line_pos = w->buffer;
-               w->base_line_number = Qnil;
+               wset_base_line_pos (w, w->buffer);
+               wset_base_line_number (w, Qnil);
                goto no_value;
              }
 
-           w->base_line_number = make_number (topline - nlines);
-           w->base_line_pos = make_number (BYTE_TO_CHAR (position));
+           wset_base_line_number (w, make_number (topline - nlines));
+           wset_base_line_pos (w, make_number (BYTE_TO_CHAR (position)));
          }
 
        /* Now count lines from the start pos to point.  */
@@ -21533,12 +21597,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        line_number_displayed = 1;
 
        /* Make the string to show.  */
-       pint2str (decode_mode_spec_buf, field_width, topline + nlines);
+       pint2str (decode_mode_spec_buf, width, topline + nlines);
        return decode_mode_spec_buf;
     no_value:
         {
          char* p = decode_mode_spec_buf;
-         int pad = field_width - 2;
+         int pad = width - 2;
          while (pad-- > 0)
            *p++ = ' ';
          *p++ = '?';
@@ -21674,10 +21738,10 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        obj = Fget_buffer_process (Fcurrent_buffer ());
        if (PROCESSP (obj))
          {
-           p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
-                                        p, eol_flag);
-           p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
-                                        p, eol_flag);
+           p = decode_mode_spec_coding
+             (XPROCESS (obj)->decode_coding_system, p, eol_flag);
+           p = decode_mode_spec_coding
+             (XPROCESS (obj)->encode_coding_system, p, eol_flag);
          }
 #endif /* subprocesses */
 #endif /* 0 */
@@ -21959,7 +22023,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
            {
              /* Glyph is off the left margin of the display area.
                 Should not happen.  */
-             abort ();
+             emacs_abort ();
            }
 
          row->ascent = max (row->ascent, it->max_ascent);
@@ -22452,7 +22516,7 @@ init_glyph_string (struct glyph_string *s,
 /* Append the list of glyph strings with head H and tail T to the list
    with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the result.  */
 
-static inline void
+static void
 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
                           struct glyph_string *h, struct glyph_string *t)
 {
@@ -22472,7 +22536,7 @@ append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tai
    list with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the
    result.  */
 
-static inline void
+static void
 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
                            struct glyph_string *h, struct glyph_string *t)
 {
@@ -22491,7 +22555,7 @@ prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **ta
 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
    Set *HEAD and *TAIL to the resulting list.  */
 
-static inline void
+static void
 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
                     struct glyph_string *s)
 {
@@ -22506,7 +22570,7 @@ append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
    Value is a pointer to a realized face that is ready for display if
    DISPLAY_P is non-zero.  */
 
-static inline struct face *
+static struct face *
 get_char_face_and_encoding (struct frame *f, int c, int face_id,
                            XChar2b *char2b, int display_p)
 {
@@ -22539,7 +22603,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
    The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
    a pointer to a realized face that is ready for display.  */
 
-static inline struct face *
+static struct face *
 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
                             XChar2b *char2b, int *two_byte_p)
 {
@@ -22576,7 +22640,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 /* Get glyph code of character C in FONT in the two-byte form CHAR2B.
    Return 1 if FONT has a glyph for C, otherwise return 0.  */
 
-static inline int
+static int
 get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
 {
   unsigned code;
@@ -23004,7 +23068,8 @@ right_overwritten (struct glyph_string *s)
     {
       int x = 0, i;
       struct glyph *glyphs = s->row->glyphs[s->area];
-      int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+      int first = (s->first_glyph - glyphs
+                  + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
       int end = s->row->used[s->area];
 
       for (i = first; i < end && s->right_overhang > x; ++i)
@@ -23027,7 +23092,8 @@ right_overwriting (struct glyph_string *s)
   int i, k, x;
   int end = s->row->used[s->area];
   struct glyph *glyphs = s->row->glyphs[s->area];
-  int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+  int first = (s->first_glyph - glyphs
+              + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
 
   k = -1;
   x = 0;
@@ -23048,7 +23114,7 @@ right_overwriting (struct glyph_string *s)
    first glyph following S.  LAST_X is the right-most x-position + 1
    in the drawing area.  */
 
-static inline void
+static void
 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
 {
   /* If the face of this glyph string has to be drawn to the end of
@@ -23324,7 +23390,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
              break;                                                    \
                                                                        \
            default:                                                    \
-             abort ();                                                 \
+             emacs_abort ();                                                   \
            }                                                           \
                                                                        \
          if (s)                                                        \
@@ -23374,8 +23440,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 
   /* Let's rather be paranoid than getting a SEGV.  */
   end = min (end, row->used[area]);
-  start = max (0, start);
-  start = min (end, start);
+  start = clip_to_bounds (0, start, end);
 
   /* Translate X to frame coordinates.  Set last_x to the right
      end of the drawing area.  */
@@ -23417,7 +23482,9 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 
       /* If mouse highlighting is on, we may need to draw adjacent
         glyphs using mouse-face highlighting.  */
-      if (area == TEXT_AREA && row->mouse_face_p)
+      if (area == TEXT_AREA && row->mouse_face_p
+         && hlinfo->mouse_face_beg_row >= 0
+         && hlinfo->mouse_face_end_row >= 0)
        {
          struct glyph_row *mouse_beg_row, *mouse_end_row;
 
@@ -23609,7 +23676,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 /* Store one glyph for IT->char_to_display in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
 
-static inline void
+static void
 append_glyph (struct it *it)
 {
   struct glyph *glyph;
@@ -23652,8 +23719,18 @@ append_glyph (struct it *it)
       glyph->type = CHAR_GLYPH;
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+       {
+         /* In R2L rows, the left and the right box edges need to be
+            drawn in reverse direction.  */
+         glyph->right_box_line_p = it->start_of_box_run_p;
+         glyph->left_box_line_p = it->end_of_box_run_p;
+       }
+      else
+       {
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+       }
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
       glyph->glyph_not_available_p = it->glyph_not_available_p;
@@ -23665,7 +23742,7 @@ append_glyph (struct it *it)
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
          if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           abort ();
+           emacs_abort ();
          glyph->bidi_type = it->bidi_it.type;
        }
       else
@@ -23683,7 +23760,7 @@ append_glyph (struct it *it)
    IT->glyph_row.  Called from x_produce_glyphs when IT->glyph_row is
    non-null.  */
 
-static inline void
+static void
 append_composite_glyph (struct it *it)
 {
   struct glyph *glyph;
@@ -23727,8 +23804,18 @@ append_composite_glyph (struct it *it)
        }
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+       {
+         /* In R2L rows, the left and the right box edges need to be
+            drawn in reverse direction.  */
+         glyph->right_box_line_p = it->start_of_box_run_p;
+         glyph->left_box_line_p = it->end_of_box_run_p;
+       }
+      else
+       {
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+       }
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
       glyph->padding_p = 0;
@@ -23739,7 +23826,7 @@ append_composite_glyph (struct it *it)
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
          if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           abort ();
+           emacs_abort ();
          glyph->bidi_type = it->bidi_it.type;
        }
       ++it->glyph_row->used[area];
@@ -23752,7 +23839,7 @@ append_composite_glyph (struct it *it)
 /* Change IT->ascent and IT->height according to the setting of
    IT->voffset.  */
 
-static inline void
+static void
 take_vertical_position_into_account (struct it *it)
 {
   if (it->voffset)
@@ -23905,8 +23992,18 @@ produce_image_glyph (struct it *it)
          glyph->type = IMAGE_GLYPH;
          glyph->avoid_cursor_p = it->avoid_cursor_p;
          glyph->multibyte_p = it->multibyte_p;
-         glyph->left_box_line_p = it->start_of_box_run_p;
-         glyph->right_box_line_p = it->end_of_box_run_p;
+         if (it->glyph_row->reversed_p && area == TEXT_AREA)
+           {
+             /* In R2L rows, the left and the right box edges need to be
+                drawn in reverse direction.  */
+             glyph->right_box_line_p = it->start_of_box_run_p;
+             glyph->left_box_line_p = it->end_of_box_run_p;
+           }
+         else
+           {
+             glyph->left_box_line_p = it->start_of_box_run_p;
+             glyph->right_box_line_p = it->end_of_box_run_p;
+           }
          glyph->overlaps_vertically_p = 0;
           glyph->padding_p = 0;
          glyph->glyph_not_available_p = 0;
@@ -23918,7 +24015,7 @@ produce_image_glyph (struct it *it)
            {
              glyph->resolved_level = it->bidi_it.resolved_level;
              if ((it->bidi_it.type & 7) != it->bidi_it.type)
-               abort ();
+               emacs_abort ();
              glyph->bidi_type = it->bidi_it.type;
            }
          ++it->glyph_row->used[area];
@@ -23965,8 +24062,18 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
       glyph->type = STRETCH_GLYPH;
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+       {
+         /* In R2L rows, the left and the right box edges need to be
+            drawn in reverse direction.  */
+         glyph->right_box_line_p = it->start_of_box_run_p;
+         glyph->left_box_line_p = it->end_of_box_run_p;
+       }
+      else
+       {
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+       }
       glyph->overlaps_vertically_p = 0;
       glyph->padding_p = 0;
       glyph->glyph_not_available_p = 0;
@@ -23979,7 +24086,7 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
          if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           abort ();
+           emacs_abort ();
          glyph->bidi_type = it->bidi_it.type;
        }
       else
@@ -24033,17 +24140,16 @@ produce_stretch_glyph (struct it *it)
   Lisp_Object prop, plist;
   int width = 0, height = 0, align_to = -1;
   int zero_width_ok_p = 0;
-  int ascent = 0;
   double tem;
-  struct face *face = NULL;
   struct font *font = NULL;
 
 #ifdef HAVE_WINDOW_SYSTEM
+  int ascent = 0;
   int zero_height_ok_p = 0;
 
   if (FRAME_WINDOW_P (it->f))
     {
-      face = FACE_FROM_ID (it->f, it->face_id);
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
       font = face->font ? face->font : FRAME_FONT (it->f);
       PREPARE_FACE_FOR_DISPLAY (it->f, face);
     }
@@ -24234,7 +24340,7 @@ produce_special_glyphs (struct it *it, enum display_element_type what)
        }
     }
   else
-    abort ();
+    emacs_abort ();
 
 #ifdef HAVE_WINDOW_SYSTEM
   /* On a GUI frame, when the right fringe (left fringe for R2L rows)
@@ -24419,8 +24525,18 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
       glyph->slice.glyphless.lower_yoff = lower_yoff;
       glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+       {
+         /* In R2L rows, the left and the right box edges need to be
+            drawn in reverse direction.  */
+         glyph->right_box_line_p = it->start_of_box_run_p;
+         glyph->left_box_line_p = it->end_of_box_run_p;
+       }
+      else
+       {
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+       }
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
       glyph->padding_p = 0;
@@ -24431,7 +24547,7 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
          if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           abort ();
+           emacs_abort ();
          glyph->bidi_type = it->bidi_it.type;
        }
       ++it->glyph_row->used[area];
@@ -24952,7 +25068,7 @@ x_produce_glyphs (struct it *it)
          font_descent = FONT_DESCENT (font) - boff;
          font_height = FONT_HEIGHT (font);
 
-         cmp->font = (void *) font;
+         cmp->font = font;
 
          pcm = NULL;
          if (! font_not_found_p)
@@ -25290,7 +25406,7 @@ x_write_glyphs (struct glyph *start, int len)
   if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
     chpos = updated_row->used[TEXT_AREA] - 1;
 
-  BLOCK_INPUT;
+  block_input ();
 
   /* Write glyphs.  */
 
@@ -25308,7 +25424,7 @@ x_write_glyphs (struct glyph *start, int len)
       && chpos < hpos + len)
     updated_window->phys_cursor_on_p = 0;
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* Advance the output cursor.  */
   output_cursor.hpos += len;
@@ -25331,7 +25447,7 @@ x_insert_glyphs (struct glyph *start, int len)
   ptrdiff_t hpos;
 
   eassert (updated_window && updated_row);
-  BLOCK_INPUT;
+  block_input ();
   w = updated_window;
   f = XFRAME (WINDOW_FRAME (w));
 
@@ -25365,7 +25481,7 @@ x_insert_glyphs (struct glyph *start, int len)
   /* Advance the output cursor.  */
   output_cursor.hpos += len;
   output_cursor.x += shift_by_width;
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -25434,10 +25550,10 @@ x_clear_end_of_line (int to_x)
   /* Prevent inadvertently clearing to end of the X window.  */
   if (to_x > from_x && to_y > from_y)
     {
-      BLOCK_INPUT;
+      block_input ();
       FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
                                        to_x - from_x, to_y - from_y);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -25573,7 +25689,7 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
     }
 
   /* Detect a nonselected window or nonselected frame.  */
-  else if (w != XWINDOW (FVAR (f, selected_window))
+  else if (w != XWINDOW (f->selected_window)
           || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
     {
       *active_cursor = 0;
@@ -25764,7 +25880,7 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row,
 {
   int i, x;
 
-  BLOCK_INPUT;
+  block_input ();
 
   x = 0;
   for (i = 0; i < row->used[area];)
@@ -25792,7 +25908,7 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row,
        }
     }
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -26010,7 +26126,7 @@ display_and_set_cursor (struct window *w, int on,
       || (0 <= hpos && hpos < glyph_row->used[TEXT_AREA]))
     glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
 
-  eassert (interrupt_input_blocked);
+  eassert (input_blocked_p ());
 
   /* Set new_cursor_type to the cursor we want to be displayed.  */
   new_cursor_type = get_window_cursor_type (w, glyph,
@@ -26080,10 +26196,10 @@ update_window_cursor (struct window *w, int on)
       if (row->reversed_p && hpos >= row->used[TEXT_AREA])
        hpos = row->used[TEXT_AREA] - 1;
 
-      BLOCK_INPUT;
+      block_input ();
       display_and_set_cursor (w, on, hpos, vpos,
                              w->phys_cursor.x, w->phys_cursor.y);
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 
@@ -26115,7 +26231,7 @@ update_cursor_in_window_tree (struct window *w, int on_p)
 void
 x_update_cursor (struct frame *f, int on_p)
 {
-  update_cursor_in_window_tree (XWINDOW (FVAR (f, root_window)), on_p);
+  update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
 }
 
 
@@ -26261,10 +26377,10 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
          if (row->reversed_p && hpos >= row->used[TEXT_AREA])
            hpos = row->used[TEXT_AREA] - 1;
 
-         BLOCK_INPUT;
+         block_input ();
          display_and_set_cursor (w, 1, hpos, w->phys_cursor.vpos,
                                  w->phys_cursor.x, w->phys_cursor.y);
-         UNBLOCK_INPUT;
+         unblock_input ();
        }
 #endif /* HAVE_WINDOW_SYSTEM */
     }
@@ -26274,7 +26390,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
   if (FRAME_WINDOW_P (f))
     {
       if (draw == DRAW_NORMAL_TEXT
-         && !EQ (hlinfo->mouse_face_window, FVAR (f, tool_bar_window)))
+         && !EQ (hlinfo->mouse_face_window, f->tool_bar_window))
        FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
       else if (draw == DRAW_MOUSE_FACE)
        FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
@@ -27597,12 +27713,6 @@ note_mouse_highlight (struct frame *f, int x, int y)
   if (hlinfo->mouse_face_defer)
     return;
 
-  if (gc_in_progress)
-    {
-      hlinfo->mouse_face_deferred_gc = 1;
-      return;
-    }
-
   /* Which window is that in?  */
   window = window_from_coordinates (f, x, y, &part, 1);
 
@@ -27630,7 +27740,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
 #ifdef HAVE_WINDOW_SYSTEM
   /* Handle tool-bar window differently since it doesn't display a
      buffer.  */
-  if (EQ (window, FVAR (f, tool_bar_window)))
+  if (EQ (window, f->tool_bar_window))
     {
       note_tool_bar_highlight (f, x, y);
       return;
@@ -28079,11 +28189,11 @@ x_clear_window_mouse_face (struct window *w)
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
   Lisp_Object window;
 
-  BLOCK_INPUT;
+  block_input ();
   XSETWINDOW (window, w);
   if (EQ (window, hlinfo->mouse_face_window))
     clear_mouse_face (hlinfo);
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 
@@ -28540,18 +28650,18 @@ expose_frame (struct frame *f, int x, int y, int w, int h)
     }
 
   TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
-  mouse_face_overwritten_p = expose_window_tree (XWINDOW (FVAR (f, root_window)), &r);
+  mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
 
-  if (WINDOWP (FVAR (f, tool_bar_window)))
+  if (WINDOWP (f->tool_bar_window))
     mouse_face_overwritten_p
-      |= expose_window (XWINDOW (FVAR (f, tool_bar_window)), &r);
+      |= expose_window (XWINDOW (f->tool_bar_window), &r);
 
 #ifdef HAVE_X_WINDOWS
 #ifndef MSDOS
 #ifndef USE_X_TOOLKIT
-  if (WINDOWP (FVAR (f, menu_bar_window)))
+  if (WINDOWP (f->menu_bar_window))
     mouse_face_overwritten_p
-      |= expose_window (XWINDOW (FVAR (f, menu_bar_window)), &r);
+      |= expose_window (XWINDOW (f->menu_bar_window), &r);
 #endif /* not USE_X_TOOLKIT */
 #endif
 #endif
@@ -28653,6 +28763,7 @@ syms_of_xdisp (void)
   staticpro (&Vmessage_stack);
 
   DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
+  DEFSYM (Qredisplay_internal, "redisplay_internal (C function)");
 
   message_dolog_marker1 = Fmake_marker ();
   staticpro (&message_dolog_marker1);
@@ -28892,12 +29003,6 @@ A value of nil means to respect the value of `truncate-lines'.
 If `word-wrap' is enabled, you might want to reduce this.  */);
   Vtruncate_partial_width_windows = make_number (50);
 
-  DEFVAR_BOOL ("mode-line-inverse-video", mode_line_inverse_video,
-    doc: /* When nil, display the mode-line/header-line/menu-bar in the default face.
-Any other value means to use the appropriate face, `mode-line',
-`header-line', or `menu' respectively.  */);
-  mode_line_inverse_video = 1;
-
   DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
     doc: /* Maximum buffer size for which line number should be displayed.
 If the buffer is bigger than this, the line number does not appear
@@ -28950,7 +29055,7 @@ and is used only on frames for which no explicit name has been set
     doc: /* Maximum number of lines to keep in the message log buffer.
 If nil, disable message logging.  If t, log messages but don't truncate
 the buffer when it becomes large.  */);
-  Vmessage_log_max = make_number (100);
+  Vmessage_log_max = make_number (1000);
 
   DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
     doc: /* Functions called before redisplay, if window sizes have changed.
@@ -29264,6 +29369,10 @@ Its value should be an ASCII acronym string, `hex-code', `empty-box', or
   Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
   Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),
                              Qempty_box);
+
+  DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
+              doc: /* If non-nil, debug if a message matching this regexp is displayed.  */);
+  Vdebug_on_message = Qnil;
 }
 
 
@@ -29287,12 +29396,13 @@ init_xdisp (void)
 
       echo_area_window = minibuf_window;
 
-      XSETFASTINT (r->top_line, FRAME_TOP_MARGIN (f));
-      XSETFASTINT (r->total_lines, FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f));
-      XSETFASTINT (r->total_cols, FRAME_COLS (f));
-      XSETFASTINT (m->top_line, FRAME_LINES (f) - 1);
-      XSETFASTINT (m->total_lines, 1);
-      XSETFASTINT (m->total_cols, FRAME_COLS (f));
+      wset_top_line (r, make_number (FRAME_TOP_MARGIN (f)));
+      wset_total_lines
+       (r, make_number (FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f)));
+      wset_total_cols (r, make_number (FRAME_COLS (f)));
+      wset_top_line (m, make_number (FRAME_LINES (f) - 1));
+      wset_total_lines (m, make_number (1));
+      wset_total_cols (m, make_number (FRAME_COLS (f)));
 
       scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
       scratch_glyph_row.glyphs[TEXT_AREA + 1]
@@ -29316,11 +29426,7 @@ init_xdisp (void)
   help_echo_showing_p = 0;
 }
 
-/* Since w32 does not support atimers, it defines its own implementation of
-   the following three functions in w32fns.c.  */
-#ifndef WINDOWSNT
-
-/* Platform-independent portion of hourglass implementation. */
+/* Platform-independent portion of hourglass implementation.  */
 
 /* Cancel a currently active hourglass timer, and start a new one.  */
 void
@@ -29342,6 +29448,13 @@ start_hourglass (void)
   else
     delay = make_emacs_time (DEFAULT_HOURGLASS_DELAY, 0);
 
+#ifdef HAVE_NTGUI
+  {
+    extern void w32_note_current_window (void);
+    w32_note_current_window ();
+  }
+#endif /* HAVE_NTGUI */
+
   hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
                                   show_hourglass, NULL);
 #endif
@@ -29364,4 +29477,3 @@ cancel_hourglass (void)
     hide_hourglass ();
 #endif
 }
-#endif /* ! WINDOWSNT  */