]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Merge from emacs-24; up to 2014-07-17T10:18:19Z!dmantipov@yandex.ru
[gnu-emacs] / src / xdisp.c
index 1585164f4394d8aa2dacd0daa90408c2ac390470..bf73de69669e8e9b3990174f58f278d52bda2872 100644 (file)
@@ -98,7 +98,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
       This function attempts to redisplay a window by reusing parts of
       its existing display.  It finds and reuses the part that was not
-      changed, and redraws the rest.
+      changed, and redraws the rest.  (The "id" part in the function's
+      name stands for "insert/delete", not for "identification" or
+      somesuch.)
 
     . try_window
 
@@ -113,6 +115,19 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
    optimizations were successful, redisplay calls redisplay_windows,
    which performs a full redisplay of all windows.
 
+   Note that there's one more important optimization up Emacs's
+   sleeve, but it is related to actually redrawing the potentially
+   changed portions of the window/frame, not to reproducing the
+   desired matrices of those potentially changed portions.  Namely,
+   the function update_frame and its subroutines, which you will find
+   in dispnew.c, compare the desired matrices with the current
+   matrices, and only redraw the portions that changed.  So it could
+   happen that the functions in this file for some reason decide that
+   the entire desired matrix needs to be regenerated from scratch, and
+   still only parts of the Emacs display, or even nothing at all, will
+   be actually delivered to the glass, because update_frame has found
+   that the new and the old screen contents are similar or identical.
+
    Desired matrices.
 
    Desired matrices are always built per Emacs window.  The function
@@ -801,11 +816,11 @@ Lisp_Object previous_help_echo_string;
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Non-zero means an hourglass cursor is currently shown.  */
-bool hourglass_shown_p;
+static bool hourglass_shown_p;
 
 /* If non-null, an asynchronous timer that, when it expires, displays
    an hourglass cursor on all frames.  */
-struct atimer *hourglass_atimer;
+static struct atimer *hourglass_atimer;
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
@@ -1009,6 +1024,8 @@ window_text_bottom_y (struct window *w)
   if (WINDOW_WANTS_MODELINE_P (w))
     height -= CURRENT_MODE_LINE_HEIGHT (w);
 
+  height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
+
   return height;
 }
 
@@ -1053,6 +1070,7 @@ window_box_height (struct window *w)
   eassert (height >= 0);
 
   height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+  height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
 
   /* Note: the code below that determines the mode-line/header-line
      height is essentially the same as that contained in the macro
@@ -1126,7 +1144,7 @@ window_box_left_offset (struct window *w, enum glyph_row_area area)
    area AREA of window W.  ANY_AREA means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
-int
+static int
 window_box_right_offset (struct window *w, enum glyph_row_area area)
 {
   /* Don't return more than the window's pixel width.  */
@@ -1421,7 +1439,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
              (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
 
   if (charpos >= 0
-      && (((!it.bidi_p || it.bidi_it.scan_dir == 1)
+      && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
           && IT_CHARPOS (it) >= charpos)
          /* When scanning backwards under bidi iteration, move_it_to
             stops at or _before_ CHARPOS, because it stops at or to
@@ -1437,15 +1455,19 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
         glyph.  */
       int top_x = it.current_x;
       int top_y = it.current_y;
-      /* Calling line_bottom_y may change it.method, it.position, etc.  */
-      enum it_method it_method = it.method;
-      int bottom_y = (last_height = 0, line_bottom_y (&it));
       int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
+      int bottom_y;
+      struct it save_it;
+      void *save_it_data = NULL;
 
+      /* Calling line_bottom_y may change it.method, it.position, etc.  */
+      SAVE_IT (save_it, it, save_it_data);
+      last_height = 0;
+      bottom_y = line_bottom_y (&it);
       if (top_y < window_top_y)
        visible_p = bottom_y > window_top_y;
       else if (top_y < it.last_visible_y)
-       visible_p = true;
+       visible_p = 1;
       if (bottom_y >= it.last_visible_y
          && it.bidi_p && it.bidi_it.scan_dir == -1
          && IT_CHARPOS (it) < charpos)
@@ -1458,7 +1480,6 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
             move_it_to again with a slightly larger vertical limit,
             and see if it actually moved vertically; if it did, we
             didn't really reach CHARPOS, which is beyond window end.  */
-         struct it save_it = it;
          /* Why 10? because we don't know how many canonical lines
             will the height of the next line(s) be.  So we guess.  */
          int ten_more_lines = 10 * default_line_pixel_height (w);
@@ -1468,11 +1489,11 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
          if (it.current_y > top_y)
            visible_p = 0;
 
-         it = save_it;
        }
+      RESTORE_IT (&it, &save_it, save_it_data);
       if (visible_p)
        {
-         if (it_method == GET_FROM_DISPLAY_VECTOR)
+         if (it.method == GET_FROM_DISPLAY_VECTOR)
            {
              /* We stopped on the last glyph of a display vector.
                 Try and recompute.  Hack alert!  */
@@ -1570,7 +1591,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                  /* Move to the last buffer position before the
                     display property.  */
                  start_display (&it3, w, top);
-                 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
+                 if (start > CHARPOS (top))
+                   move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
                  /* Move forward one more line if the position before
                     the display string is a newline or if it is the
                     rightmost character on a line that is
@@ -1673,7 +1695,9 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
     }
   else
     {
-      /* We were asked to provide info about WINDOW_END.  */
+      /* Either we were asked to provide info about WINDOW_END, or
+        CHARPOS is in the partially visible glyph row at end of
+        window.  */
       struct it it2;
       void *it2data = NULL;
 
@@ -1936,8 +1960,8 @@ pixel_to_glyph_coords (struct frame *f, register int pix_x, register int pix_y,
 
          if (pix_y < 0)
            pix_y = 0;
-         else if (pix_y > FRAME_LINES (f))
-           pix_y = FRAME_LINES (f);
+         else if (pix_y > FRAME_TOTAL_LINES (f))
+           pix_y = FRAME_TOTAL_LINES (f);
        }
     }
 #endif
@@ -2153,7 +2177,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
 
       if (s->x > r.x)
        {
-         r.width -= s->x - r.x;
+         if (r.width >= s->x - r.x)
+           r.width -= s->x - r.x;
+         else  /* R2L hscrolled row with cursor outside text area */
+           r.width = 0;
          r.x = s->x;
        }
       r.width = min (r.width, glyph->pixel_width);
@@ -2480,7 +2507,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
       gx = WINDOW_PIXEL_WIDTH (w) - width;
       goto row_glyph;
 
-    case ON_SCROLL_BAR:
+    case ON_VERTICAL_SCROLL_BAR:
       gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
            ? 0
            : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
@@ -2514,7 +2541,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
       gy = 0;
       /* The bottom divider prevails. */
       height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
-      goto add_edge;;
+      goto add_edge;
 
     case ON_BOTTOM_DIVIDER:
       gx = 0;
@@ -2602,15 +2629,14 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
     {
       ptrdiff_t i;
       ptrdiff_t count = SPECPDL_INDEX ();
-      struct gcpro gcpro1;
-      Lisp_Object *args = alloca (nargs * word_size);
+      Lisp_Object *args;
+      USE_SAFE_ALLOCA;
+      SAFE_ALLOCA_LISP (args, nargs);
 
       args[0] = func;
       for (i = 1; i < nargs; i++)
        args[i] = va_arg (ap, Lisp_Object);
 
-      GCPRO1 (args[0]);
-      gcpro1.nvars = nargs;
       specbind (Qinhibit_redisplay, Qt);
       if (inhibit_quit)
        specbind (Qinhibit_quit, Qt);
@@ -2618,7 +2644,7 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
         so there is no possibility of wanting to redisplay.  */
       val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
                                       safe_eval_handler);
-      UNGCPRO;
+      SAFE_FREE ();
       val = unbind_to (count, val);
     }
 
@@ -2950,10 +2976,6 @@ init_iterator (struct it *it, struct window *w,
   it->glyph_row = row;
   it->area = TEXT_AREA;
 
-  /* Forget any previous info about this row being reversed.  */
-  if (it->glyph_row)
-    it->glyph_row->reversed_p = 0;
-
   /* Get the dimensions of the display area.  The display area
      consists of the visible window area plus a horizontally scrolled
      part to the left of the window.  All x-values are relative to the
@@ -2973,12 +2995,8 @@ init_iterator (struct it *it, struct window *w,
 
       /* If we truncate lines, leave room for the truncation glyph(s) at
         the right margin.  Otherwise, leave room for the continuation
-        glyph(s).  Done only if the window has no fringes.  Since we
-        don't know at this point whether there will be any R2L lines in
-        the window, we reserve space for truncation/continuation glyphs
-        even if only one of the fringes is absent.  */
-      if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
-         || (it->bidi_p && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
+        glyph(s).  Done only if the window has no right fringe.  */
+      if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
        {
          if (it->line_wrap == TRUNCATE)
            it->last_visible_x -= it->truncation_pixel_width;
@@ -3016,6 +3034,7 @@ init_iterator (struct it *it, struct window *w,
      getting overlays and face properties from that position.  */
   if (charpos >= BUF_BEG (current_buffer))
     {
+      it->stop_charpos = charpos;
       it->end_charpos = ZV;
       eassert (charpos == BYTE_TO_CHAR (bytepos));
       IT_CHARPOS (*it) = charpos;
@@ -3042,6 +3061,19 @@ init_iterator (struct it *it, struct window *w,
         iterator.  */
       if (it->bidi_p)
        {
+         /*  Since we don't know at this point whether there will be
+             any R2L lines in the window, we reserve space for
+             truncation/continuation glyphs even if only the left
+             fringe is absent.  */
+         if (base_face_id == DEFAULT_FACE_ID
+             && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
+             && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
+           {
+             if (it->line_wrap == TRUNCATE)
+               it->last_visible_x -= it->truncation_pixel_width;
+             else
+               it->last_visible_x -= it->continuation_pixel_width;
+           }
          /* Note the paragraph direction that this buffer wants to
             use.  */
          if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
@@ -3395,6 +3427,48 @@ handle_stop (struct it *it)
   if (it->selective_display_ellipsis_p)
     it->saved_face_id = it->face_id;
 
+  /* Here's the description of the semantics of, and the logic behind,
+     the various HANDLED_* statuses:
+
+     HANDLED_NORMALLY means the handler did its job, and the loop
+     should proceed to calling the next handler in order.
+
+     HANDLED_RECOMPUTE_PROPS means the handler caused a significant
+     change in the properties and overlays at current position, so the
+     loop should be restarted, to re-invoke the handlers that were
+     already called.  This happens when fontification-functions were
+     called by handle_fontified_prop, and actually fontified
+     something.  Another case where HANDLED_RECOMPUTE_PROPS is
+     returned is when we discover overlay strings that need to be
+     displayed right away.  The loop below will continue for as long
+     as the status is HANDLED_RECOMPUTE_PROPS.
+
+     HANDLED_RETURN means return immediately to the caller, to
+     continue iteration without calling any further handlers.  This is
+     used when we need to act on some property right away, for example
+     when we need to display the ellipsis or a replacing display
+     property, such as display string or image.
+
+     HANDLED_OVERLAY_STRING_CONSUMED means an overlay string was just
+     consumed, and the handler switched to the next overlay string.
+     This signals the loop below to refrain from looking for more
+     overlays before all the overlay strings of the current overlay
+     are processed.
+
+     Some of the handlers called by the loop push the iterator state
+     onto the stack (see 'push_it'), and arrange for the iteration to
+     continue with another object, such as an image, a display string,
+     or an overlay string.  In most such cases, it->stop_charpos is
+     set to the first character of the string, so that when the
+     iteration resumes, this function will immediately be called
+     again, to examine the properties at the beginning of the string.
+
+     When a display or overlay string is exhausted, the iterator state
+     is popped (see 'pop_it'), and iteration continues with the
+     previous object.  Again, in many such cases this function is
+     called again to find the next position where properties might
+     change.  */
+
   do
     {
       handled = HANDLED_NORMALLY;
@@ -3596,6 +3670,7 @@ next_overlay_change (ptrdiff_t pos)
   ptrdiff_t i, noverlays;
   ptrdiff_t endpos;
   Lisp_Object *overlays;
+  USE_SAFE_ALLOCA;
 
   /* Get all overlays at the given position.  */
   GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1);
@@ -3612,6 +3687,7 @@ next_overlay_change (ptrdiff_t pos)
       endpos = min (endpos, oendpos);
     }
 
+  SAFE_FREE ();
   return endpos;
 }
 
@@ -4528,7 +4604,24 @@ handle_invisible_prop (struct it *it)
              && get_overlay_strings (it, it->stop_charpos))
            {
              handled = HANDLED_RECOMPUTE_PROPS;
-             it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
+             if (it->sp > 0)
+               {
+                 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
+                 /* The call to get_overlay_strings above recomputes
+                    it->stop_charpos, but it only considers changes
+                    in properties and overlays beyond iterator's
+                    current position.  This causes us to miss changes
+                    that happen exactly where the invisible property
+                    ended.  So we play it safe here and force the
+                    iterator to check for potential stop positions
+                    immediately after the invisible text.  Note that
+                    if get_overlay_strings returns non-zero, it
+                    normally also pushed the iterator stack, so we
+                    need to update the stop position in the slot
+                    below the current one.  */
+                 it->stack[it->sp - 1].stop_charpos
+                   = CHARPOS (it->stack[it->sp - 1].current.pos);
+               }
            }
          else if (display_ellipsis_p)
             {
@@ -5040,7 +5133,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 
       if (it)
        {
-         int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);;
+         int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
 
          if (CONSP (XCDR (XCDR (spec))))
            {
@@ -5655,10 +5748,11 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
   Lisp_Object overlay, window, str, invisible;
   struct Lisp_Overlay *ov;
   ptrdiff_t start, end;
-  ptrdiff_t size = 20;
   ptrdiff_t n = 0, i, j;
   int invis_p;
-  struct overlay_entry *entries = alloca (size * sizeof *entries);
+  struct overlay_entry entriesbuf[20];
+  ptrdiff_t size = ARRAYELTS (entriesbuf);
+  struct overlay_entry *entries = entriesbuf;
   USE_SAFE_ALLOCA;
 
   if (charpos <= 0)
@@ -8254,7 +8348,7 @@ next_element_from_buffer (struct it *it)
 
       /* Get the next character, maybe multibyte.  */
       p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
-      if (it->multibyte_p && !ASCII_BYTE_P (*p))
+      if (it->multibyte_p && !ASCII_CHAR_P (*p))
        it->c = STRING_CHAR_AND_LENGTH (p, it->len);
       else
        it->c = *p, it->len = 1;
@@ -9232,6 +9326,25 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
                {
                  line_start_x = it->current_x + it->pixel_width
                    - it->last_visible_x;
+                 if (FRAME_WINDOW_P (it->f))
+                   {
+                     struct face *face = FACE_FROM_ID (it->f, it->face_id);
+                     struct font *face_font = face->font;
+
+                     /* When display_line produces a continued line
+                        that ends in a TAB, it skips a tab stop that
+                        is closer than the font's space character
+                        width (see x_produce_glyphs where it produces
+                        the stretch glyph which represents a TAB).
+                        We need to reproduce the same logic here.  */
+                     eassert (face_font);
+                     if (face_font)
+                       {
+                         if (line_start_x < face_font->space_width)
+                           line_start_x
+                             += it->tab_width * face_font->space_width;
+                       }
+                   }
                  set_iterator_to_next (it, 0);
                }
            }
@@ -9314,7 +9427,7 @@ move_it_vertically_backward (struct it *it, int dy)
 
   /* Estimate how many newlines we must move back.  */
   nlines = max (1, dy / default_line_pixel_height (it->w));
-  if (it->line_wrap == TRUNCATE)
+  if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
     pos_limit = BEGV;
   else
     pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
@@ -9569,7 +9682,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
       /* Go back -DVPOS buffer lines, but no farther than -DVPOS full
         screen lines, and reseat the iterator there.  */
       start_charpos = IT_CHARPOS (*it);
-      if (it->line_wrap == TRUNCATE)
+      if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
        pos_limit = BEGV;
       else
        pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
@@ -9639,6 +9752,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
              back_to_previous_visible_line_start (it);
              it->vpos--;
            }
+         reseat_1 (it, it->current.pos, 1);
        }
       else
        RESTORE_IT (it, it, it2data);
@@ -9917,9 +10031,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
          for (i = 0; i < nbytes; i += char_bytes)
            {
              c = string_char_and_length (msg + i, &char_bytes);
-             work[0] = (ASCII_CHAR_P (c)
-                        ? c
-                        : multibyte_char_to_unibyte (c));
+             work[0] = CHAR_TO_BYTE8 (c);
              insert_1_both (work, 1, 1, 1, 0, 0);
            }
        }
@@ -10094,9 +10206,9 @@ message3 (Lisp_Object m)
     {
       ptrdiff_t nbytes = SBYTES (m);
       bool multibyte = STRING_MULTIBYTE (m);
+      char *buffer;
       USE_SAFE_ALLOCA;
-      char *buffer = SAFE_ALLOCA (nbytes);
-      memcpy (buffer, SDATA (m), nbytes);
+      SAFE_ALLOCA_STRING (buffer, m);
       message_dolog (buffer, nbytes, 1, multibyte);
       SAFE_FREE ();
     }
@@ -10201,19 +10313,17 @@ message_with_string (const char *m, Lisp_Object string, int log)
     {
       if (m)
        {
-         /* ENCODE_SYSTEM below can GC and/or relocate the Lisp
-            String whose data pointer might be passed to us in M.  So
-            we use a local copy.  */
-         char *fmt = xstrdup (m);
+         /* ENCODE_SYSTEM below can GC and/or relocate the
+            Lisp data, so make sure we don't use it here.  */
+         eassert (relocatable_string_data_p (m) != 1);
 
          if (noninteractive_need_newline)
            putc ('\n', stderr);
          noninteractive_need_newline = 0;
-         fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string)));
+         fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string)));
          if (!cursor_in_echo_area)
            fprintf (stderr, "\n");
          fflush (stderr);
-         xfree (fmt);
        }
     }
   else if (INTERACTIVE)
@@ -10300,11 +10410,13 @@ vmessage (const char *m, va_list ap)
            {
              ptrdiff_t len;
              ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
-             char *message_buf = alloca (maxsize + 1);
+             USE_SAFE_ALLOCA;
+             char *message_buf = SAFE_ALLOCA (maxsize + 1);
 
              len = doprnt (message_buf, maxsize, m, 0, ap);
 
              message3 (make_string (message_buf, len));
+             SAFE_FREE ();
            }
          else
            message1 (0);
@@ -10470,6 +10582,7 @@ with_echo_area_buffer (struct window *w, int which,
     {
       wset_buffer (w, buffer);
       set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
+      set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
     }
 
   bset_undo_list (current_buffer, Qt);
@@ -10508,7 +10621,7 @@ with_echo_area_buffer_unwind_data (struct window *w)
   Vwith_echo_area_save_vector = Qnil;
 
   if (NILP (vector))
-    vector = Fmake_vector (make_number (9), Qnil);
+    vector = Fmake_vector (make_number (11), Qnil);
 
   XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
   ASET (vector, i, Vdeactivate_mark); ++i;
@@ -10520,12 +10633,14 @@ with_echo_area_buffer_unwind_data (struct window *w)
       ASET (vector, i, w->contents); ++i;
       ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
       ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
+      ASET (vector, i, make_number (marker_position (w->old_pointm))); ++i;
+      ASET (vector, i, make_number (marker_byte_position (w->old_pointm))); ++i;
       ASET (vector, i, make_number (marker_position (w->start))); ++i;
       ASET (vector, i, make_number (marker_byte_position (w->start))); ++i;
     }
   else
     {
-      int end = i + 6;
+      int end = i + 8;
       for (; i < end; ++i)
        ASET (vector, i, Qnil);
     }
@@ -10557,9 +10672,12 @@ unwind_with_echo_area_buffer (Lisp_Object vector)
       set_marker_both (w->pointm, buffer,
                       XFASTINT (AREF (vector, 5)),
                       XFASTINT (AREF (vector, 6)));
-      set_marker_both (w->start, buffer,
+      set_marker_both (w->old_pointm, buffer,
                       XFASTINT (AREF (vector, 7)),
                       XFASTINT (AREF (vector, 8)));
+      set_marker_both (w->start, buffer,
+                      XFASTINT (AREF (vector, 9)),
+                      XFASTINT (AREF (vector, 10)));
     }
 
   Vwith_echo_area_save_vector = vector;
@@ -11808,11 +11926,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-/* Tool-bar item index of the item on which a mouse button was pressed
-   or -1.  */
-
-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
@@ -11839,7 +11952,7 @@ update_tool_bar (struct frame *f, int save_match_data)
   int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
   int do_update = (WINDOWP (f->tool_bar_window)
-                  && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0);
+                  && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
 #endif
 
   if (do_update)
@@ -11935,11 +12048,11 @@ static void
 build_desired_tool_bar_string (struct frame *f)
 {
   int i, size, size_needed;
-  struct gcpro gcpro1, gcpro2, gcpro3;
-  Lisp_Object image, plist, props;
+  struct gcpro gcpro1, gcpro2;
+  Lisp_Object image, plist;
 
-  image = plist = props = Qnil;
-  GCPRO3 (image, plist, props);
+  image = plist = Qnil;
+  GCPRO2 (image, plist);
 
   /* Prepare F->desired_tool_bar_string.  If we can reuse it, do so.
      Otherwise, make a new string.  */
@@ -11958,9 +12071,12 @@ build_desired_tool_bar_string (struct frame *f)
       (f, Fmake_string (make_number (size_needed), make_number (' ')));
   else
     {
-      props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
+      AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
+      struct gcpro gcpro1;
+      GCPRO1 (props);
       Fremove_text_properties (make_number (0), make_number (size),
                               props, f->desired_tool_bar_string);
+      UNGCPRO;
     }
 
   /* Put a `display' property on the string for the images to display,
@@ -12071,8 +12187,10 @@ build_desired_tool_bar_string (struct frame *f)
         the start of this item's properties in the tool-bar items
         vector.  */
       image = Fcons (Qimage, plist);
-      props = list4 (Qdisplay, image,
-                    Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS));
+      AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
+                 make_number (i * TOOL_BAR_ITEM_NSLOTS));
+      struct gcpro gcpro1;
+      GCPRO1 (props);
 
       /* Let the last image hide all remaining spaces in the tool bar
          string.  The string can be longer than needed when we reuse a
@@ -12083,6 +12201,7 @@ build_desired_tool_bar_string (struct frame *f)
        end = i + 1;
       Fadd_text_properties (make_number (i), make_number (end),
                            props, f->desired_tool_bar_string);
+      UNGCPRO;
 #undef PROP
     }
 
@@ -12223,16 +12342,9 @@ display_tool_bar_line (struct it *it, int height)
 }
 
 
-/* Max tool-bar height.  Basically, this is what makes all other windows
-   disappear when the frame gets too small.  Rethink this!  */
-
-#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
-  ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
-
 /* Value is the number of pixels needed to make all tool-bar items of
    frame F visible.  The actual number of glyph rows needed is
    returned in *N_ROWS if non-NULL.  */
-
 static int
 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
 {
@@ -12246,6 +12358,7 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
   /* Initialize an iterator for iteration over
      F->desired_tool_bar_string in the tool-bar window of frame F.  */
   init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
+  temp_row->reversed_p = false;
   it.first_visible_x = 0;
   it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
@@ -12271,11 +12384,6 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
 
 #endif /* !USE_GTK && !HAVE_NS */
 
-#if defined USE_GTK || defined HAVE_NS
-EXFUN (Ftool_bar_height, 2) ATTRIBUTE_CONST;
-EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
-#endif
-
 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
        0, 2, 0,
        doc: /* Return the number of lines occupied by the tool bar of FRAME.
@@ -12306,7 +12414,6 @@ PIXELWISE non-nil means return the height of the tool bar in pixels.  */)
 
 /* Display the tool-bar of frame F.  Value is non-zero if tool-bar's
    height should be changed.  */
-
 static int
 redisplay_tool_bar (struct frame *f)
 {
@@ -12328,7 +12435,7 @@ redisplay_tool_bar (struct frame *f)
      can turn off tool-bars by specifying tool-bar-lines zero.  */
   if (!WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
-          WINDOW_PIXEL_HEIGHT (w) == 0))
+          WINDOW_TOTAL_LINES (w) == 0))
     return 0;
 
   /* Set up an iterator for the tool-bar window.  */
@@ -12336,6 +12443,7 @@ redisplay_tool_bar (struct frame *f)
   it.first_visible_x = 0;
   it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
   row = it.glyph_row;
+  row->reversed_p = false;
 
   /* Build a string that represents the contents of the tool-bar.  */
   build_desired_tool_bar_string (f);
@@ -12355,14 +12463,7 @@ redisplay_tool_bar (struct frame *f)
 
       if (new_height != WINDOW_PIXEL_HEIGHT (w))
        {
-         Lisp_Object frame;
-         int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
-                          / FRAME_LINE_HEIGHT (f));
-
-         XSETFRAME (frame, f);
-         Fmodify_frame_parameters (frame,
-                                   list1 (Fcons (Qtool_bar_lines,
-                                                 make_number (new_lines))));
+         x_change_tool_bar_height (f, new_height);
          /* Always do that now.  */
          clear_glyph_matrix (w->desired_matrix);
          f->fonts_changed = 1;
@@ -12415,14 +12516,11 @@ redisplay_tool_bar (struct frame *f)
 
   if (!NILP (Vauto_resize_tool_bars))
     {
-      /* Do we really allow the toolbar to occupy the whole frame?  */
-      int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
       int change_height_p = 0;
 
       /* If we couldn't display everything, change the tool-bar's
         height if there is room for more.  */
-      if (IT_STRING_CHARPOS (it) < it.end_charpos
-         && it.current_y < max_tool_bar_height)
+      if (IT_STRING_CHARPOS (it) < it.end_charpos)
        change_height_p = 1;
 
       /* We subtract 1 because display_tool_bar_line advances the
@@ -12441,15 +12539,13 @@ redisplay_tool_bar (struct frame *f)
       /* If row displays tool-bar items, but is partially visible,
         change the tool-bar's height.  */
       if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
-         && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y
-         && MATRIX_ROW_BOTTOM_Y (row) < max_tool_bar_height)
+         && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
        change_height_p = 1;
 
       /* Resize windows as needed by changing the `tool-bar-lines'
         frame parameter.  */
       if (change_height_p)
        {
-         Lisp_Object frame;
          int nrows;
          int new_height = tool_bar_height (f, &nrows, 1);
 
@@ -12461,35 +12557,12 @@ redisplay_tool_bar (struct frame *f)
 
          if (change_height_p)
            {
-             /* Current size of the tool-bar window in canonical line
-                units.  */
-             int old_lines = WINDOW_TOTAL_LINES (w);
-             /* Required size of the tool-bar window in canonical
-                line units. */
-             int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
-                              / FRAME_LINE_HEIGHT (f));
-             /* Maximum size of the tool-bar window in canonical line
-                units that this frame can allow. */
-             int max_lines =
-               WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1;
-
-             /* Don't try to change the tool-bar window size and set
-                the fonts_changed flag unless really necessary.  That
-                flag causes redisplay to give up and retry
-                redisplaying the frame from scratch, so setting it
-                unnecessarily can lead to nasty redisplay loops.  */
-             if (new_lines <= max_lines
-                 && eabs (new_lines - old_lines) >= 1)
-               {
-                 XSETFRAME (frame, f);
-                 Fmodify_frame_parameters (frame,
-                                           list1 (Fcons (Qtool_bar_lines,
-                                                         make_number (new_lines))));
-                 clear_glyph_matrix (w->desired_matrix);
-                 f->n_tool_bar_rows = nrows;
-                 f->fonts_changed = 1;
-                 return 1;
-               }
+             x_change_tool_bar_height (f, new_height);
+             clear_glyph_matrix (w->desired_matrix);
+             f->n_tool_bar_rows = nrows;
+             f->fonts_changed = 1;
+
+             return 1;
            }
        }
     }
@@ -12614,7 +12687,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
      where the button was pressed, disregarding where it was
      released.  */
   if (NILP (Vmouse_highlight) && !down_p)
-    prop_idx = last_tool_bar_item;
+    prop_idx = f->last_tool_bar_item;
 
   /* If item is disabled, do nothing.  */
   enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
@@ -12626,7 +12699,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
       /* Show item in pressed state.  */
       if (!NILP (Vmouse_highlight))
        show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
-      last_tool_bar_item = prop_idx;
+      f->last_tool_bar_item = prop_idx;
     }
   else
     {
@@ -12651,7 +12724,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
       event.arg = key;
       event.modifiers = modifiers;
       kbd_buffer_store_event (&event);
-      last_tool_bar_item = -1;
+      f->last_tool_bar_item = -1;
     }
 }
 
@@ -12701,8 +12774,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
   mouse_down_p = (x_mouse_grabbed (dpyinfo)
                  && f == dpyinfo->last_mouse_frame);
 
-  if (mouse_down_p
-      && last_tool_bar_item != prop_idx)
+  if (mouse_down_p && f->last_tool_bar_item != prop_idx)
     return;
 
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
@@ -12824,14 +12896,33 @@ hscroll_window_tree (Lisp_Object window)
          /* Scroll when cursor is inside this scroll margin.  */
          h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
 
+         /* If the position of this window's point has explicitly
+            changed, no more suspend auto hscrolling.  */
+         if (NILP (Fequal (Fwindow_point (window), Fwindow_old_point (window))))
+           w->suspend_auto_hscroll = 0;
+
+         /* Remember window point.  */
+         Fset_marker (w->old_pointm,
+                      ((w == XWINDOW (selected_window))
+                       ? make_number (BUF_PT (XBUFFER (w->contents)))
+                       : Fmarker_position (w->pointm)),
+                      w->contents);
+
          if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
+             && w->suspend_auto_hscroll == 0
+             /* In some pathological cases, like restoring a window
+                configuration into a frame that is much smaller than
+                the one from which the configuration was saved, we
+                get glyph rows whose start and end have zero buffer
+                positions, which we cannot handle below.  Just skip
+                such windows.  */
+             && CHARPOS (cursor_row->start.pos) >= BUF_BEG (w->contents)
              /* For left-to-right rows, hscroll when cursor is either
                 (i) inside the right hscroll margin, or (ii) if it is
                 inside the left margin and the window is already
                 hscrolled.  */
              && ((!row_r2l_p
-                  && ((w->hscroll
-                       && w->cursor.x <= h_margin)
+                  && ((w->hscroll && w->cursor.x <= h_margin)
                       || (cursor_row->enabled_p
                           && cursor_row->truncated_on_right_p
                           && (w->cursor.x >= text_area_width - h_margin))))
@@ -13482,6 +13573,12 @@ redisplay_internal (void)
 
       if (mode_line_update_needed (w))
        w->update_mode_line = 1;
+
+      /* If reconsider_clip_changes above decided that the narrowing
+        in the current buffer changed, make sure all other windows
+        showing that buffer will be redisplayed.  */
+      if (current_buffer->clip_changed)
+       bset_update_mode_line (current_buffer);
     }
 
   /* Normally the message* functions will have already displayed and
@@ -14421,7 +14518,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                                              pos_after, 0);
 
                if (prop_pos >= pos_before)
-                 bpos_max = prop_pos - 1;
+                 bpos_max = prop_pos;
              }
            if (INTEGERP (chprop))
              {
@@ -14495,7 +14592,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                                              pos_after, 0);
 
                if (prop_pos >= pos_before)
-                 bpos_max = prop_pos - 1;
+                 bpos_max = prop_pos;
              }
            if (INTEGERP (chprop))
              {
@@ -14525,7 +14622,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_max < pt_old && pt_old <= bpos_covered))
+      && !(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.
@@ -14905,6 +15002,10 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
    If FORCE_P is non-zero, return 0 even if partial visible cursor row
    is higher than window.
 
+   If CURRENT_MATRIX_P is non-zero, use the information from the
+   window's current glyph matrix; otherwise use the desired glyph
+   matrix.
+
    A value of 0 means the caller should do scrolling
    as if point had gone off the screen.  */
 
@@ -15712,9 +15813,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
   return rc;
 }
 
-#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK
-static
-#endif
+
 void
 set_vertical_scroll_bar (struct window *w)
 {
@@ -15753,11 +15852,120 @@ set_vertical_scroll_bar (struct window *w)
 }
 
 
+void
+set_horizontal_scroll_bar (struct window *w)
+{
+  int start, end, whole, portion;
+
+  if (!MINI_WINDOW_P (w)
+      || (w == XWINDOW (minibuf_window)
+         && NILP (echo_area_buffer[0])))
+    {
+      struct buffer *b = XBUFFER (w->contents);
+      struct buffer *old_buffer = NULL;
+      struct it it;
+      struct text_pos startp;
+
+      if (b != current_buffer)
+       {
+         old_buffer = current_buffer;
+         set_buffer_internal (b);
+       }
+
+      SET_TEXT_POS_FROM_MARKER (startp, w->start);
+      start_display (&it, w, startp);
+      it.last_visible_x = INT_MAX;
+      whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
+                         MOVE_TO_X | MOVE_TO_Y);
+      /* whole = move_it_to (&it, w->window_end_pos, INT_MAX,
+                         window_box_height (w), -1,
+                         MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); */
+
+      start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+      end = start + window_box_width (w, TEXT_AREA);
+      portion = end - start;
+      /* After enlarging a horizontally scrolled window such that it
+        gets at least as wide as the text it contains, make sure that
+        the thumb doesn't fill the entire scroll bar so we can still
+        drag it back to see the entire text.  */
+      whole = max (whole, end);
+
+      if (it.bidi_p)
+       {
+         Lisp_Object pdir;
+
+         pdir = Fcurrent_bidi_paragraph_direction (Qnil);
+         if (EQ (pdir, Qright_to_left))
+           {
+             start = whole - end;
+             end = start + portion;
+           }
+       }
+
+      if (old_buffer)
+       set_buffer_internal (old_buffer);
+    }
+  else
+    start = end = whole = portion = 0;
+
+  w->hscroll_whole = whole;
+
+  /* Indicate what this scroll bar ought to be displaying now.  */
+  if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
+    (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
+      (w, portion, whole, start);
+}
+
+
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
    selected_window is redisplayed.
 
    We can return without actually redisplaying the window if fonts has been
-   changed on window's frame.  In that case, redisplay_internal will retry.  */
+   changed on window's frame.  In that case, redisplay_internal will retry.
+
+   As one of the important parts of redisplaying a window, we need to
+   decide whether the previous window-start position (stored in the
+   window's w->start marker position) is still valid, and if it isn't,
+   recompute it.  Some details about that:
+
+    . The previous window-start could be in a continuation line, in
+      which case we need to recompute it when the window width
+      changes.  See compute_window_start_on_continuation_line and its
+      call below.
+
+    . The text that changed since last redisplay could include the
+      previous window-start position.  In that case, we try to salvage
+      what we can from the current glyph matrix by calling
+      try_scrolling, which see.
+
+    . Some Emacs command could force us to use a specific window-start
+      position by setting the window's force_start flag, or gently
+      propose doing that by setting the window's optional_new_start
+      flag.  In these cases, we try using the specified start point if
+      that succeeds (i.e. the window desired matrix is successfully
+      recomputed, and point location is within the window).  In case
+      of optional_new_start, we first check if the specified start
+      position is feasible, i.e. if it will allow point to be
+      displayed in the window.  If using the specified start point
+      fails, e.g., if new fonts are needed to be loaded, we abort the
+      redisplay cycle and leave it up to the next cycle to figure out
+      things.
+
+    . Note that the window's force_start flag is sometimes set by
+      redisplay itself, when it decides that the previous window start
+      point is fine and should be kept.  Search for "goto force_start"
+      below to see the details.  Like the values of window-start
+      specified outside of redisplay, these internally-deduced values
+      are tested for feasibility, and ignored if found to be
+      unfeasible.
+
+    . Note that the function try_window, used to completely redisplay
+      a window, accepts the window's start point as its argument.
+      This is used several times in the redisplay code to control
+      where the window start will be, according to user options such
+      as scroll-conservatively, and also to ensure the screen line
+      showing point will be fully (as opposed to partially) visible on
+      display.  */
 
 static void
 redisplay_window (Lisp_Object window, bool just_this_one_p)
@@ -15803,6 +16011,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   eassert (XMARKER (w->start)->buffer == buffer);
   eassert (XMARKER (w->pointm)->buffer == buffer);
 
+  /* We come here again if we need to run window-text-change-functions
+     below.  */
  restart:
   reconsider_clip_changes (w);
   frame_line_height = default_line_pixel_height (w);
@@ -15867,7 +16077,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
        && !current_buffer->prevent_redisplay_optimizations_p
        && !window_outdated (w));
 
-  /* Run the window-bottom-change-functions
+  /* Run the window-text-change-functions
      if it is possible that the text on the screen has changed
      (either due to modification of the text, or any other reason).  */
   if (!current_matrix_up_to_date_p
@@ -15920,6 +16130,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
     {
       ptrdiff_t new_pt = marker_position (w->pointm);
       ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
+
       if (new_pt < BEGV)
        {
          new_pt = BEGV;
@@ -15968,26 +16179,48 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 
   /* If someone specified a new starting point but did not insist,
      check whether it can be used.  */
-  if (w->optional_new_start
+  if ((w->optional_new_start || window_frozen_p (w))
       && CHARPOS (startp) >= BEGV
       && CHARPOS (startp) <= ZV)
     {
+      ptrdiff_t it_charpos;
+
       w->optional_new_start = 0;
       start_display (&it, w, startp);
       move_it_to (&it, PT, 0, it.last_visible_y, -1,
                  MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
-      if (IT_CHARPOS (it) == PT)
-       w->force_start = 1;
-      /* IT may overshoot PT if text at PT is invisible.  */
-      else if (IT_CHARPOS (it) > PT && CHARPOS (startp) <= PT)
-       w->force_start = 1;
+      /* Record IT's position now, since line_bottom_y might change
+        that.  */
+      it_charpos = IT_CHARPOS (it);
+      /* Make sure we set the force_start flag only if the cursor row
+        will be fully visible.  Otherwise, the code under force_start
+        label below will try to move point back into view, which is
+        not what the code which sets optional_new_start wants.  */
+      if ((it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
+         && !w->force_start)
+       {
+         if (it_charpos == PT)
+           w->force_start = 1;
+         /* IT may overshoot PT if text at PT is invisible.  */
+         else if (it_charpos > PT && CHARPOS (startp) <= PT)
+           w->force_start = 1;
+#ifdef GLYPH_DEBUG
+         if (w->force_start)
+           {
+             if (window_frozen_p (w))
+               debug_method_add (w, "set force_start from frozen window start");
+             else
+               debug_method_add (w, "set force_start from optional_new_start");
+           }
+#endif
+       }
     }
 
  force_start:
 
   /* Handle case where place to start displaying has been specified,
      unless the specified location is outside the accessible range.  */
-  if (w->force_start || window_frozen_p (w))
+  if (w->force_start)
     {
       /* We set this later on if we have to adjust point.  */
       int new_vpos = -1;
@@ -16032,7 +16265,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
          goto need_larger_matrices;
        }
 
-      if (w->cursor.vpos < 0 && !window_frozen_p (w))
+      if (w->cursor.vpos < 0)
        {
          /* If point does not appear, try to move point so it does
             appear. The desired matrix has been built above, so we
@@ -16045,6 +16278,18 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
          /* Point does appear, but on a line partly visible at end of window.
             Move it back to a fully-visible line.  */
          new_vpos = window_box_height (w);
+         /* But if window_box_height suggests a Y coordinate that is
+            not less than we already have, that line will clearly not
+            be fully visible, so give up and scroll the display.
+            This can happen when the default face uses a font whose
+            dimensions are different from the frame's default
+            font.  */
+         if (new_vpos >= w->cursor.y)
+           {
+             w->cursor.vpos = -1;
+             clear_glyph_matrix (w->desired_matrix);
+             goto try_to_scroll;
+           }
        }
       else if (w->cursor.vpos >= 0)
        {
@@ -16113,6 +16358,11 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
            }
          */
        }
+      if (w->cursor.vpos < 0 || !cursor_row_fully_visible_p (w, 0, 0))
+       {
+         clear_glyph_matrix (w->desired_matrix);
+         goto try_to_scroll;
+       }
 
 #ifdef GLYPH_DEBUG
       debug_method_add (w, "forced window start");
@@ -16177,7 +16427,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
               || CHARPOS (startp) == BEGV
               || !window_outdated (w)))
     {
-      int d1, d2, d3, d4, d5, d6;
+      int d1, d2, d5, d6;
+      int rtop, rbot;
 
       /* If first window line is a continuation line, and window start
         is inside the modified region, but the first change is before
@@ -16202,14 +16453,20 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
          && compute_window_start_on_continuation_line (w)
          /* It doesn't make sense to force the window start like we
             do at label force_start if it is already known that point
-            will not be visible in the resulting window, because
+            will not be fully visible in the resulting window, because
             doing so will move point from its correct position
             instead of scrolling the window to bring point into view.
             See bug#9324.  */
-         && pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &d6))
+         && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
+         /* A very tall row could need more than the window height,
+            in which case we accept that it is partially visible.  */
+         && (rtop != 0) == (rbot != 0))
        {
          w->force_start = 1;
          SET_TEXT_POS_FROM_MARKER (startp, w->start);
+#ifdef GLYPH_DEBUG
+         debug_method_add (w, "recomputed window start in continuation line");
+#endif
          goto force_start;
        }
 
@@ -16647,7 +16904,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
            redisplay_tool_bar (f);
 #else
          if (WINDOWP (f->tool_bar_window)
-             && (FRAME_TOOL_BAR_HEIGHT (f) > 0
+             && (FRAME_TOOL_BAR_LINES (f) > 0
                  || !NILP (Vauto_resize_tool_bars))
              && redisplay_tool_bar (f))
            ignore_mouse_drag_p = 1;
@@ -16687,10 +16944,15 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   ;
  finish_scroll_bars:
 
-  if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+   if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
     {
-      /* Set the thumb's position and size.  */
-      set_vertical_scroll_bar (w);
+      if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+       /* Set the thumb's position and size.  */
+       set_vertical_scroll_bar (w);
+
+      if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
+       /* Set the thumb's position and size.  */
+       set_horizontal_scroll_bar (w);
 
       /* Note that we actually used the scroll bar attached to this
         window, so it shouldn't be deleted at the end of redisplay.  */
@@ -16746,6 +17008,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
 
   /* Initialize iterator and info to start at POS.  */
   start_display (&it, w, pos);
+  it.glyph_row->reversed_p = false;
 
   /* Display all lines of W.  */
   while (it.current_y < it.last_visible_y)
@@ -16929,6 +17192,7 @@ try_window_reusing_current_matrix (struct window *w)
              && it.current.dpvec_index < 0)
            break;
 
+         it.glyph_row->reversed_p = false;
          if (display_line (&it))
            last_text_row = it.glyph_row - 1;
 
@@ -17949,6 +18213,11 @@ try_window_id (struct window *w)
   w->cursor.vpos = -1;
   last_text_row = NULL;
   overlay_arrow_seen = 0;
+  if (it.current_y < it.last_visible_y
+      && !f->fonts_changed
+      && (first_unchanged_at_end_row == NULL
+         || IT_CHARPOS (it) < stop_pos))
+    it.glyph_row->reversed_p = false;
   while (it.current_y < it.last_visible_y
         && !f->fonts_changed
         && (first_unchanged_at_end_row == NULL
@@ -18493,10 +18762,10 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
   else if (glyphs == 1)
     {
       int area;
+      char s[SHRT_MAX + 4];
 
       for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
        {
-         char *s = alloca (row->used[area] + 4);
          int i;
 
          for (i = 0; i < row->used[area]; ++i)
@@ -18649,7 +18918,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
   struct buffer *buffer = XBUFFER (w->contents);
   struct buffer *old = current_buffer;
   const unsigned char *arrow_string = SDATA (overlay_arrow_string);
-  int arrow_len = SCHARS (overlay_arrow_string);
+  ptrdiff_t arrow_len = SCHARS (overlay_arrow_string);
   const unsigned char *arrow_end = arrow_string + arrow_len;
   const unsigned char *p;
   struct it it;
@@ -18658,6 +18927,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
 
   set_buffer_temp (buffer);
   init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
+  scratch_glyph_row.reversed_p = false;
   it.glyph_row->used[TEXT_AREA] = 0;
   SET_TEXT_POS (it.position, 0, 0);
 
@@ -19169,7 +19439,18 @@ extend_face_to_end_of_line (struct it *it)
 
          for (row_width = 0, g = row_start; g < row_end; g++)
            row_width += g->pixel_width;
-         stretch_width = window_box_width (it->w, TEXT_AREA) - row_width;
+
+         /* FIXME: There are various minor display glitches in R2L
+            rows when only one of the fringes is missing.  The
+            strange condition below produces the least bad effect.  */
+         if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
+             == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
+             || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
+           stretch_width = window_box_width (it->w, TEXT_AREA);
+         else
+           stretch_width = it->last_visible_x - it->first_visible_x;
+         stretch_width -= row_width;
+
          if (stretch_width > 0)
            {
              stretch_ascent =
@@ -19196,6 +19477,12 @@ extend_face_to_end_of_line (struct it *it)
              it->face_id = saved_face_id;
              it->start_of_box_run_p = saved_box_start;
            }
+         /* If stretch_width comes out negative, it means that the
+            last glyph is only partially visible.  In R2L rows, we
+            want the leftmost glyph to be partially visible, so we
+            need to give the row the corresponding left offset.  */
+         if (stretch_width < 0)
+           it->glyph_row->x = stretch_width;
        }
 #endif /* HAVE_WINDOW_SYSTEM */
     }
@@ -19822,6 +20109,7 @@ display_line (struct it *it)
   int cvpos;
   ptrdiff_t min_pos = ZV + 1, max_pos = 0;
   ptrdiff_t min_bpos IF_LINT (= 0), max_bpos IF_LINT (= 0);
+  bool pending_handle_line_prefix = false;
 
   /* We always start displaying at hpos zero even if hscrolled.  */
   eassert (it->hpos == 0 && it->current_x == 0);
@@ -19835,7 +20123,7 @@ display_line (struct it *it)
     }
 
   /* Clear the result glyph row and enable it.  */
-  prepare_desired_row (row);
+  prepare_desired_row (it->w, row, false);
 
   row->y = it->current_y;
   row->start = it->start;
@@ -19882,13 +20170,23 @@ display_line (struct it *it)
       min_pos = CHARPOS (this_line_min_pos);
       min_bpos = BYTEPOS (this_line_min_pos);
     }
-  else
+  else if (it->area == TEXT_AREA)
     {
-      /* We only do this when not calling `move_it_in_display_line_to'
-        above, because move_it_in_display_line_to calls
-        handle_line_prefix itself.  */
+      /* We only do this when not calling move_it_in_display_line_to
+        above, because that function calls itself handle_line_prefix.  */
       handle_line_prefix (it);
     }
+  else
+    {
+      /* Line-prefix and wrap-prefix are always displayed in the text
+        area.  But if this is the first call to display_line after
+        init_iterator, the iterator might have been set up to write
+        into a marginal area, e.g. if the line begins with some
+        display property that writes to the margins.  So we need to
+        wait with the call to handle_line_prefix until whatever
+        writes to the margin has done its job.  */
+      pending_handle_line_prefix = true;
+    }
 
   /* Get the initial row height.  This is either the height of the
      text hscrolled, if there is any, or zero.  */
@@ -20020,6 +20318,14 @@ display_line (struct it *it)
          row->extra_line_spacing = max (row->extra_line_spacing,
                                         it->max_extra_line_spacing);
          set_iterator_to_next (it, 1);
+         /* If we didn't handle the line/wrap prefix above, and the
+            call to set_iterator_to_next just switched to TEXT_AREA,
+            process the prefix now.  */
+         if (it->area == TEXT_AREA && pending_handle_line_prefix)
+           {
+             pending_handle_line_prefix = false;
+             handle_line_prefix (it);
+           }
          continue;
        }
 
@@ -20049,7 +20355,12 @@ display_line (struct it *it)
                                  it->max_phys_ascent + it->max_phys_descent);
          row->extra_line_spacing = max (row->extra_line_spacing,
                                         it->max_extra_line_spacing);
-         if (it->current_x - it->pixel_width < it->first_visible_x)
+         if (it->current_x - it->pixel_width < it->first_visible_x
+             /* In R2L rows, we arrange in extend_face_to_end_of_line
+                to add a right offset to the line, by a suitable
+                change to the stretch glyph that is the leftmost
+                glyph of the line.  */
+             && !row->reversed_p)
            row->x = x - it->first_visible_x;
          /* Record the maximum and minimum buffer positions seen so
             far in glyphs that will be displayed by this row.  */
@@ -20063,7 +20374,13 @@ display_line (struct it *it)
 
          for (i = 0; i < nglyphs; ++i, x = new_x)
            {
-             glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
+             /* Identify the glyphs added by the last call to
+                PRODUCE_GLYPHS.  In R2L rows, they are prepended to
+                the previous glyphs.  */
+             if (!row->reversed_p)
+               glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
+             else
+               glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
              new_x = x + glyph->pixel_width;
 
              if (/* Lines are continued.  */
@@ -20263,10 +20580,28 @@ display_line (struct it *it)
                  if (it->bidi_p)
                    RECORD_MAX_MIN_POS (it);
 
-                 if (x < it->first_visible_x)
+                 if (x < it->first_visible_x && !row->reversed_p)
                    /* Glyph is partially visible, i.e. row starts at
-                      negative X position.  */
+                      negative X position.  Don't do that in R2L
+                      rows, where we arrange to add a right offset to
+                      the line in extend_face_to_end_of_line, by a
+                      suitable change to the stretch glyph that is
+                      the leftmost glyph of the line.  */
                    row->x = x - it->first_visible_x;
+                 /* When the last glyph of an R2L row only fits
+                    partially on the line, we need to set row->x to a
+                    negative offset, so that the leftmost glyph is
+                    the one that is partially visible.  But if we are
+                    going to produce the truncation glyph, this will
+                    be taken care of in produce_special_glyphs.  */
+                 if (row->reversed_p
+                     && new_x > it->last_visible_x
+                     && !(it->line_wrap == TRUNCATE
+                          && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
+                   {
+                     eassert (FRAME_WINDOW_P (it->f));
+                     row->x = it->last_visible_x - new_x;
+                   }
                }
              else
                {
@@ -20340,7 +20675,10 @@ display_line (struct it *it)
                  that they are cropped at the right edge of the
                  window, so an image glyph will always end exactly at
                  last_visible_x, even if there's no right fringe.  */
-              && (WINDOW_RIGHT_FRINGE_WIDTH (it->w) || it->what == IT_IMAGE))
+              && ((row->reversed_p
+                   ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                   : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
+                  || it->what == IT_IMAGE))
              ? (it->current_x >= it->last_visible_x)
              : (it->current_x > it->last_visible_x)))
        {
@@ -20417,7 +20755,15 @@ display_line (struct it *it)
          row->truncated_on_right_p = 1;
          it->continuation_lines_width = 0;
          reseat_at_next_visible_line_start (it, 0);
-         row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
+         /* We insist below that IT's position be at ZV because in
+            bidi-reordered lines the character at visible line start
+            might not be the character that follows the newline in
+            the logical order.  */
+         if (IT_BYTEPOS (*it) > BEG_BYTE)
+           row->ends_at_zv_p =
+             IT_BYTEPOS (*it) >= ZV_BYTE && FETCH_BYTE (ZV_BYTE - 1) != '\n';
+         else
+           row->ends_at_zv_p = false;
          break;
        }
     }
@@ -20620,7 +20966,8 @@ See also `bidi-paragraph-direction'.  */)
         the previous non-empty line.  */
       if (pos >= ZV && pos > BEGV)
        DEC_BOTH (pos, bytepos);
-      if (fast_looking_at (build_string ("[\f\t ]*\n"),
+      AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
+      if (fast_looking_at (trailing_white_space,
                           pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
        {
          while ((c = FETCH_BYTE (bytepos)) == '\n'
@@ -20701,6 +21048,10 @@ Value is the new character position of point.  */)
       && !b->clip_changed
       && !b->prevent_redisplay_optimizations_p
       && !window_outdated (w)
+      /* We rely below on the cursor coordinates to be up to date, but
+        we cannot trust them if some command moved point since the
+        last complete redisplay.  */
+      && w->last_point == BUF_PT (b)
       && w->cursor.vpos >= 0
       && w->cursor.vpos < w->current_matrix->nrows
       && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
@@ -20727,7 +21078,7 @@ Value is the new character position of point.  */)
                  if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
                    new_pos += (row->reversed_p ? -dir : dir);
                  else
-                   new_pos -= (row->reversed_p ? -dir : dir);;
+                   new_pos -= (row->reversed_p ? -dir : dir);
                }
              else if (BUFFERP (g->object))
                new_pos = g->charpos;
@@ -21195,6 +21546,7 @@ display_menu_bar (struct window *w)
       clear_glyph_row (row);
       row->enabled_p = true;
       row->full_width_p = 1;
+      row->reversed_p = false;
     }
 
   /* Display all items of the menu bar.  */
@@ -21470,7 +21822,7 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
   /* Don't extend on a previously drawn mode-line.
      This may happen if called from pos_visible_p.  */
   it.glyph_row->enabled_p = false;
-  prepare_desired_row (it.glyph_row);
+  prepare_desired_row (w, it.glyph_row, true);
 
   it.glyph_row->mode_line_p = 1;
 
@@ -22428,10 +22780,8 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_
        }
       else if (CHARACTERP (eoltype))
        {
-         unsigned char *tmp = alloca (MAX_MULTIBYTE_LENGTH);
          int c = XFASTINT (eoltype);
-         eol_str_len = CHAR_STRING (c, tmp);
-         eol_str = tmp;
+         return buf + CHAR_STRING (c, (unsigned char *) buf);
        }
       else
        {
@@ -22567,7 +22917,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        }
 
     case 'e':
-#ifndef SYSTEM_MALLOC
+#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
       {
        if (NILP (Vmemory_full))
          return "";
@@ -22805,8 +23155,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
     case '@':
       {
        ptrdiff_t count = inhibit_garbage_collection ();
-       Lisp_Object val = call1 (intern ("file-remote-p"),
-                                BVAR (current_buffer, directory));
+       Lisp_Object curdir = BVAR (current_buffer, directory);
+       Lisp_Object val = Qnil;
+
+       if (STRINGP (curdir))
+         val = call1 (intern ("file-remote-p"), curdir);
+
        unbind_to (count, Qnil);
 
        if (NILP (val))
@@ -23685,7 +24039,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
 #endif
     {
       eassert (face != NULL);
-      PREPARE_FACE_FOR_DISPLAY (f, face);
+      prepare_face_for_display (f, face);
     }
 
   return face;
@@ -23708,7 +24062,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 
   /* Make sure X resources of the face are allocated.  */
   eassert (face != NULL);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
+  prepare_face_for_display (f, face);
 
   if (two_byte_p)
     *two_byte_p = 0;
@@ -24025,7 +24379,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
   s->ybase += voffset;
 
   /* The case that face->gc == 0 is handled when drawing the glyph
-     string by calling PREPARE_FACE_FOR_DISPLAY.  */
+     string by calling prepare_face_for_display.  */
   eassert (s->face);
   return glyph - s->row->glyphs[s->area];
 }
@@ -24343,7 +24697,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
         face_id = (row)->glyphs[area][START].face_id;                     \
                                                                           \
         s = alloca (sizeof *s);                                           \
-        char2b = alloca ((END - START) * sizeof *char2b);                 \
+        SAFE_NALLOCA (char2b, 1, (END) - (START));                        \
         INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);           \
         append_glyph_string (&HEAD, &TAIL, s);                            \
         s->x = (X);                                                       \
@@ -24371,7 +24725,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
     struct glyph_string *first_s = NULL;                                   \
     int n;                                                                 \
                                                                            \
-    char2b = alloca (cmp->glyph_len * sizeof *char2b);                     \
+    SAFE_NALLOCA (char2b, 1, cmp->glyph_len);                              \
                                                                            \
     /* Make glyph_strings for each glyph sequence that is drawable by      \
        the same face, and append them to HEAD/TAIL.  */                            \
@@ -24406,7 +24760,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
     gstring = (composition_gstring_from_id                               \
               ((row)->glyphs[area][START].u.cmp.id));                    \
     s = alloca (sizeof *s);                                              \
-    char2b = alloca (LGSTRING_GLYPH_LEN (gstring) * sizeof *char2b);     \
+    SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring));              \
     INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);              \
     append_glyph_string (&(HEAD), &(TAIL), s);                           \
     s->x = (X);                                                                  \
@@ -24558,6 +24912,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
      BUILD_GLYPH_STRINGS will modify its start parameter.  That's
      the reason we use a separate variable `i'.  */
   i = start;
+  USE_SAFE_ALLOCA;
   BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
   if (tail)
     x_reached = tail->x + tail->background_width;
@@ -24757,6 +25112,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
 
   RELEASE_HDC (hdc, f);
 
+  SAFE_FREE ();
   return x_reached;
 }
 
@@ -24974,7 +25330,7 @@ produce_image_glyph (struct it *it)
   face = FACE_FROM_ID (it->f, it->face_id);
   eassert (face);
   /* Make sure X resources of the face is loaded.  */
-  PREPARE_FACE_FOR_DISPLAY (it->f, face);
+  prepare_face_for_display (it->f, face);
 
   if (it->image_id < 0)
     {
@@ -25153,6 +25509,24 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
          for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
            g[1] = *g;
          glyph = it->glyph_row->glyphs[area];
+
+         /* Decrease the width of the first glyph of the row that
+            begins before first_visible_x (e.g., due to hscroll).
+            This is so the overall width of the row becomes smaller
+            by the scroll amount, and the stretch glyph appended by
+            extend_face_to_end_of_line will be wider, to shift the
+            row glyphs to the right.  (In L2R rows, the corresponding
+            left-shift effect is accomplished by setting row->x to a
+            negative value, which won't work with R2L rows.)
+
+            This must leave us with a positive value of WIDTH, since
+            otherwise the call to move_it_in_display_line_to at the
+            beginning of display_line would have got past the entire
+            first glyph, and then it->current_x would have been
+            greater or equal to it->first_visible_x.  */
+         if (it->current_x < it->first_visible_x)
+           width -= it->first_visible_x - it->current_x;
+         eassert (width > 0);
        }
       glyph->charpos = CHARPOS (it->position);
       glyph->object = object;
@@ -25252,7 +25626,7 @@ produce_stretch_glyph (struct it *it)
     {
       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);
+      prepare_face_for_display (it->f, face);
     }
 #endif
 
@@ -25482,14 +25856,13 @@ produce_special_glyphs (struct it *it, enum display_element_type what)
 
   temp_it.dp = NULL;
   temp_it.what = IT_CHARACTER;
-  temp_it.len = 1;
   temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
   temp_it.face_id = GLYPH_FACE (glyph);
   temp_it.len = CHAR_BYTES (temp_it.c);
 
   PRODUCE_GLYPHS (&temp_it);
   it->pixel_width = temp_it.pixel_width;
-  it->nglyphs = temp_it.pixel_width;
+  it->nglyphs = temp_it.nglyphs;
 }
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -25716,7 +26089,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
 
       face = FACE_FROM_ID (it->f, face_id);
       font = face->font ? face->font : FRAME_FONT (it->f);
-      PREPARE_FACE_FOR_DISPLAY (it->f, face);
+      prepare_face_for_display (it->f, face);
 
       if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
        {
@@ -25732,7 +26105,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
          sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
          str = buf;
        }
-      for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++)
+      for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
        code[len] = font->driver->encode_char (font, str[len]);
       upper_len = (len + 1) / 2;
       font->driver->text_extents (font, code, upper_len,
@@ -27057,9 +27430,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
 
 /* Erase the image of a cursor of window W from the screen.  */
 
-#ifndef HAVE_NTGUI
-static
-#endif
 void
 erase_phys_cursor (struct window *w)
 {
@@ -27139,7 +27509,7 @@ erase_phys_cursor (struct window *w)
   /* Maybe clear the display under the cursor.  */
   if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
     {
-      int x, y, left_x;
+      int x, y;
       int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
       int width;
 
@@ -27148,13 +27518,15 @@ erase_phys_cursor (struct window *w)
        goto mark_cursor_off;
 
       width = cursor_glyph->pixel_width;
-      left_x = window_box_left_offset (w, TEXT_AREA);
       x = w->phys_cursor.x;
-      if (x < left_x)
-       width -= left_x - x;
+      if (x < 0)
+       {
+         width += x;
+         x = 0;
+       }
       width = min (width, window_box_width (w, TEXT_AREA) - x);
       y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x));
+      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
 
       if (width > 0)
        FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
@@ -27230,6 +27602,10 @@ display_and_set_cursor (struct window *w, bool on,
       && (!on
          || w->phys_cursor.x != x
          || w->phys_cursor.y != y
+         /* HPOS can be negative in R2L rows whose
+            exact_window_width_line_p flag is set (i.e. their newline
+            would "overflow into the fringe").  */
+         || hpos < 0
          || new_cursor_type != w->phys_cursor_type
          || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
              && new_cursor_width != w->phys_cursor_width)))
@@ -28880,7 +29256,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
     else
       cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
   else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
-          || part == ON_SCROLL_BAR)
+          || part == ON_VERTICAL_SCROLL_BAR
+          || part == ON_HORIZONTAL_SCROLL_BAR)
     cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
   else
     cursor = FRAME_X_OUTPUT (f)->text_cursor;
@@ -29003,6 +29380,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
       /* Is this char mouse-active or does it have help-echo?  */
       position = make_number (pos);
 
+      USE_SAFE_ALLOCA;
+
       if (BUFFERP (object))
        {
          /* Put all the overlays we want in a vector in overlay_vec.  */
@@ -29284,6 +29663,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
       BEGV = obegv;
       ZV = ozv;
       current_buffer = obuf;
+      SAFE_FREE ();
     }
 
  set_cursor:
@@ -29801,8 +30181,8 @@ expose_frame (struct frame *f, int x, int y, int w, int h)
   if (w == 0 || h == 0)
     {
       r.x = r.y = 0;
-      r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f);
-      r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f);
+      r.width = FRAME_TEXT_WIDTH (f);
+      r.height = FRAME_TEXT_HEIGHT (f);
     }
   else
     {
@@ -30088,8 +30468,9 @@ A value of nil means no special handling of these characters.  */);
 
   DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
     doc: /* The pointer shape to show in void text areas.
-A value of nil means to show the text pointer.  Other options are `arrow',
-`text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'.  */);
+A value of nil means to show the text pointer.  Other options are
+`arrow', `text', `hand', `vdrag', `hdrag', `nhdrag', `modeline', and
+`hourglass'.  */);
   Vvoid_text_area_pointer = Qarrow;
 
   DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
@@ -30584,10 +30965,10 @@ init_xdisp (void)
       r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
       r->total_cols = FRAME_COLS (f);
       r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
-      r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+      r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
       r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
 
-      m->top_line = FRAME_LINES (f) - 1;
+      m->top_line = FRAME_TOTAL_LINES (f) - 1;
       m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
       m->total_cols = FRAME_COLS (f);
       m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
@@ -30620,7 +31001,38 @@ init_xdisp (void)
 
 /* Platform-independent portion of hourglass implementation.  */
 
+/* Timer function of hourglass_atimer.  */
+
+static void
+show_hourglass (struct atimer *timer)
+{
+  /* The timer implementation will cancel this timer automatically
+     after this function has run.  Set hourglass_atimer to null
+     so that we know the timer doesn't have to be canceled.  */
+  hourglass_atimer = NULL;
+
+  if (!hourglass_shown_p)
+    {
+      Lisp_Object tail, frame;
+
+      block_input ();
+
+      FOR_EACH_FRAME (tail, frame)
+       {
+         struct frame *f = XFRAME (frame);
+
+         if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
+             && FRAME_RIF (f)->show_hourglass)
+           FRAME_RIF (f)->show_hourglass (f);
+       }
+
+      hourglass_shown_p = 1;
+      unblock_input ();
+    }
+}
+
 /* Cancel a currently active hourglass timer, and start a new one.  */
+
 void
 start_hourglass (void)
 {
@@ -30639,20 +31051,13 @@ start_hourglass (void)
   else
     delay = make_timespec (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);
 }
 
-
 /* Cancel the hourglass cursor timer if active, hide a busy cursor if
    shown.  */
+
 void
 cancel_hourglass (void)
 {
@@ -30663,7 +31068,28 @@ cancel_hourglass (void)
     }
 
   if (hourglass_shown_p)
-    hide_hourglass ();
+    {
+      Lisp_Object tail, frame;
+
+      block_input ();
+
+      FOR_EACH_FRAME (tail, frame)
+       {
+         struct frame *f = XFRAME (frame);
+
+         if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
+             && FRAME_RIF (f)->hide_hourglass)
+           FRAME_RIF (f)->hide_hourglass (f);
+#ifdef HAVE_NTGUI
+         /* No cursors on non GUI frames - restore to stock arrow cursor.  */
+         else if (!FRAME_W32_P (f))
+           w32_arrow_cursor ();
+#endif
+       }
+
+      hourglass_shown_p = 0;
+      unblock_input ();
+    }
 }
 
 #endif /* HAVE_WINDOW_SYSTEM */